OpenCV-数字图像处理之中值滤波
中值滤波(median filter)在数字图像处理中属于空域平滑滤波的内容(spatial filtering)。对消除椒盐噪声具有很好的效果。
数学原理
为了讲述的便捷,我们以灰度图为例。RGB三通道的彩色图可以通过每一个通道各自的中值滤波联合得到。
数字图像是以矩阵的方式存储的,具体存储方式可以参见OpenCV手册。中值滤波是通过所谓的mask operation操作进行的。以3x3的mask为例。设图像的矩阵形式如下:
图中每个方框代表一个像素,每个方框里的数字对代表该像素在图中的位置。中值滤波从位置(1,1)开始,建立一个3x3的mask
让(1,1)与(i,j)对其,取出模板所覆盖的范围内像素值,取这九个值得中值然后赋给(1,1),作为(1,1)位置的新像素值。然后移动模板的中心(i,j)至(1,2),重复上面的操作,直至遍历整幅图片。这里面应该注意的是,我们在做中值滤波时,模板里的中值是赋给一个新建的全新图像,被滤波的图像像素值不会改变。这样就保证了每一次模板覆盖的区域都是原图像的像素。
注:
mask并不一定要用3x3的矩阵来做,模板的大小不是一定的。从上面的操作过程可以看到,在图像的最后一行和第一行,最后一列和第一列的像素都没有被遍历到,我们一般有两种方案解决这个问题。可以将该位置的所有像素赋值为零。可以在原图像的上下左右都加上相应的全零向量,然后再进行上述的中值滤波操作,这样所有原图的像素都可以被遍历到。 基于OpenCV中值滤波程序
OpenCV中也用现成的中值滤波函数medianblur,具体用法为
medianBlur(InputArray src,OutputArray dst,int ksize);
其中InputArray src为Mat类的被滤波图片,OutputArray是Mat类的滤波后输出结果,ksize是mask的大小,如,如果用3x3的模板,ksize就传值3;
基于OpenCV的中指滤波代码段如下,
1 //load the Original Image and get some informations2 Mat src = imread("010.jpg",1);3 namedWindow("OriginalImage");4 imshow("OriginalImage",src);5 CV_Assert(src.depth() == CV_8U);6 const int nr = src.rows;7 const int nc = src.cols;8 const int nchannels = src.channels();9 10 //OpenCV Solution11 Mat result_opencv;12 medianBlur(src,result_opencv,3);13 namedWindow("median filter_opencv");14 imshow("median filter_opencv",result_opencv);
仿真结果:
原图:
用medianBlur中值滤波的结果:
基于中值滤波原理编写的中值滤波函数仿真
这次我们进行的不再是灰度图的仿真,所以有必要简单介绍一下彩色图在Mat类里保存的方式,见下图(来源:)。
从图中我们可以看到,彩色图片中像素的三通道是保存在同一行中的,顺序是BGR。假如指针p[i]定位到的是(0,1)的蓝色通道,那么p[i+Mat.channels]定位到的就是下一列的蓝色通道。
基于中值滤波原理编写的中值滤波函数代码段如下
1 //own median filter algorithm2 uchar* previous = NULL;3 uchar* current = NULL;4 uchar* next = NULL;5 uchar* current_result_own = NULL;6 int arr[9]; //use 3*3 mask7 for(int i=1;i<nr-1;i++)8 {9previous = src.ptr<uchar>(i-1);10current = src.ptr<uchar>(i);11next = src.ptr<uchar>(i+1);12current_result_own = result_own.ptr<uchar>(i);13for(int j=nchannels;j<nchannels*(nc-1);j++)14{15 for(int k=0;k<3;k++)16 {17 arr[k] = previous[j+(k-1)*nchannels];18 arr[k+3] = current[j+(k-1)*nchannels];19 arr[k+6] = next[j+(k-1)*nchannels];20 }21 bubble_sort(arr,9);22 current_result_own[j] = arr[4];23}24 }2526 //set the pixels on the borders to zeros27 result_own.row(0).setTo(Scalar(0));28 result_own.row(nr-1).setTo(Scalar(0));29 result_own.col(0).setTo(Scalar(0));30 result_own.col(nc-1).setTo(Scalar(0));31 32 //show the result33 namedWindow("median filter_own");34 imshow("median filter_own",result_own);
其中bubble_sort是我用冒泡排序法写的排序函数,代码段如下,
1 //************************//2 //bubble sort3 //************************//4 void bubble_sort(int* arr,int num)5 {6int temp;7for(int i=1;i<num-1;i++)8{9 for(int j=0;j<num-i;j++)10 {11if(arr[j]>arr[j+1])12{13temp = arr[j];14arr[j] = arr[j+1];15arr[j+1] = temp;16}17 }18}19 }
仿真结果:
转载自:/german-iris/p/4811462.html