opencv中用c++实现的中值滤波的算法
这是我最近在学习opencv的过程中,自己实现的中值滤波算法 。由于中值滤波的原理比较简单,就不再赘述了,本程序可以有效处理椒盐噪声,下面我只附上代码和效果图,并与opencv自带的函数进行比较。对比之下,效果还是比较好的
代码
#include<opencv2/opencv.hpp>
#include<ctime>
#include<iostream>
using namespace std;
using namespace cv;
void salt(Mat& src, Mat& Saltimg, int n);
void swap(int& x, int& y);
int searchmedia(int* arr, int length);
void MediaFilter(Mat& Saltimg, Mat& dst);
int main(void)
{
Mat src = imread("E://图片//kasha.jpg");
if (src.empty())
{
cout << "fail to load the picture" << endl;
return -1;
}
Mat Saltimg,resultimg1,resultimg2;
salt(src, Saltimg,3000);
MediaFilter(Saltimg, resultimg1);
medianBlur(Saltimg, resultimg2, 3);
namedWindow("原图", WINDOW_NORMAL);
imshow("原图", src);
namedWindow("椒盐噪声", WINDOW_NORMAL);
imshow("椒盐噪声", Saltimg);
namedWindow("中值滤波后", WINDOW_NORMAL);
imshow("中值滤波后", resultimg1);
namedWindow("opencv中值滤波后", WINDOW_NORMAL);
imshow("opencv中值滤波后", resultimg2);
waitKey(0);
return 0;
}
void swap(int& x, int& y)
{
int temp;
temp = x;
x = y;
y = temp;
}
int searchmedia(int *arr,int length)
{
int i, j;
for(i = 0;i<length-1;i++)
for ( j = 0; j < length-i-1; j++)
{
if (arr[j] > arr[j + 1])
swap(arr[j], arr[j + 1]);
}
return arr[4];
}
void salt(Mat& src, Mat& Saltimg,int n)
{
src.copyTo(Saltimg);
srand(time(NULL));
for (int x = 0; x < n - 1; x++)
{
int i = rand() % Saltimg.rows;
int j = rand() % Saltimg.cols;
if (Saltimg.channels() == 1)
{
Saltimg.at<uchar>(i, j) = 255;
}
else if (Saltimg.channels() == 3)
{
Saltimg.at<Vec3b>(i, j)[0] = 255;
Saltimg.at<Vec3b>(i, j)[1] = 255;
Saltimg.at<Vec3b>(i, j)[2] = 255;
}
}
}
void MediaFilter(Mat& Saltimg, Mat& _dst)
{
Mat dst = Mat(Saltimg.size(), Saltimg.type());
int arr[9];
if (dst.channels() == 3)
{
for (int i = 0; i < dst.rows ; i++)
for (int j = 0; j < dst.cols ; j++)
{
if (i - 1 > 0 && j - 1 > 0 && i < dst.rows - 1 && j < dst.cols - 1)
{
arr[0] = Saltimg.at<Vec3b>(i - 1, j - 1)[0];
arr[1] = Saltimg.at<Vec3b>(i - 1, j)[0];
arr[2] = Saltimg.at<Vec3b>(i - 1, j + 1)[0];
arr[3] = Saltimg.at<Vec3b>(i, j - 1)[0];
arr[4] = Saltimg.at<Vec3b>(i, j)[0];
arr[5] = Saltimg.at<Vec3b>(i, j + 1)[0];
arr[6] = Saltimg.at<Vec3b>(i + 1, j - 1)[0];
arr[7] = Saltimg.at<Vec3b>(i + 1, j)[0];
arr[8] = Saltimg.at<Vec3b>(i + 1, j + 1)[0];
dst.at<Vec3b>(i, j)[0] = searchmedia(arr, 9);
arr[0] = Saltimg.at<Vec3b>(i - 1, j - 1)[1];
arr[1] = Saltimg.at<Vec3b>(i - 1, j)[1];
arr[2] = Saltimg.at<Vec3b>(i - 1, j + 1)[1];
arr[3] = Saltimg.at<Vec3b>(i, j - 1)[1];
arr[4] = Saltimg.at<Vec3b>(i, j)[1];
arr[5] = Saltimg.at<Vec3b>(i, j + 1)[1];
arr[6] = Saltimg.at<Vec3b>(i + 1, j - 1)[1];
arr[7] = Saltimg.at<Vec3b>(i + 1, j)[1];
arr[8] = Saltimg.at<Vec3b>(i + 1, j + 1)[1];
dst.at<Vec3b>(i, j)[1] = searchmedia(arr, 9);
arr[0] = Saltimg.at<Vec3b>(i - 1, j - 1)[2];
arr[1] = Saltimg.at<Vec3b>(i - 1, j)[2];
arr[2] = Saltimg.at<Vec3b>(i - 1, j + 1)[2];
arr[3] = Saltimg.at<Vec3b>(i, j - 1)[2];
arr[4] = Saltimg.at<Vec3b>(i, j)[2];
arr[5] = Saltimg.at<Vec3b>(i, j + 1)[2];
arr[6] = Saltimg.at<Vec3b>(i + 1, j - 1)[2];
arr[7] = Saltimg.at<Vec3b>(i + 1, j)[2];
arr[8] = Saltimg.at<Vec3b>(i + 1, j + 1)[2];
dst.at<Vec3b>(i, j)[2] = searchmedia(arr, 9);
}
else
{
dst.at<Vec3b>(i, j)[0] = Saltimg.at<Vec3b>(i, j)[0];
dst.at<Vec3b>(i, j)[1] = Saltimg.at<Vec3b>(i, j)[1];
dst.at<Vec3b>(i, j)[2] = Saltimg.at<Vec3b>(i, j)[2];
}
}
}
else if (dst.channels() == 1)
{
for (int i = 0; i < dst.rows ; i++)
for (int j =0; j < dst.cols ; j++)
{
if (i - 1 > 0 && j - 1 > 0 && i < dst.rows - 1 && j < dst.cols - 1)
{
arr[0] = Saltimg.at<uchar>(i - 1, j - 1);
arr[1] = Saltimg.at<uchar>(i - 1, j);
arr[2] = Saltimg.at<uchar>(i - 1, j + 1);
arr[3] = Saltimg.at<uchar>(i, j - 1);
arr[4] = Saltimg.at<uchar>(i, j);
arr[5] = Saltimg.at<uchar>(i, j + 1);
arr[6] = Saltimg.at<uchar>(i + 1, j - 1);
arr[7] = Saltimg.at<uchar>(i + 1, j);
arr[8] = Saltimg.at<uchar>(i + 1, j + 1);
dst.at<uchar>(i, j) = searchmedia(arr, 9);
}
else
{
dst.at<uchar>(i, j) = Saltimg.at<uchar>(i, j);
}
}
}
dst.copyTo(_dst);
}
效果图
原始图
随机加入3000个椒盐噪声图自己实现的效果图
opencv利用medianBlur函数实现的效果图
总结
程序中的模版是3*3的,如果要用更大的模版,可在程序中自行修改,对灰度图和彩色图都可以滤波。这是本人第一次写博客,写的不对的,请大家指正,一起交流进步。