中值滤波

1、什么是中值滤波?

无论是直接获取的灰度图像,还是由彩色图像转换得到的灰度图像,里面都有噪声的存在,噪声对图像质量有很大的影响。进行中值滤波不仅可以去除孤点噪声,而且可以保持图像的边缘特性,不会使图像产生显著的模糊,比较适合于实验中的人脸图像。

    中值滤波是一种非线性的信号处理方法,因此中值滤波器也就是一种非线性的滤波器。在一定条件下,其可以克服线性滤波器处理图像细节模糊的问题,而且它对滤除脉冲干扰和图像扫描噪声非常有效,但是,对点、线、尖顶等细节较多的图像,则会引起图像信息的丢失。中值滤波器最先被应用于一维信号的处理中,后来被人们引用到二维图像的处理中来。

中值滤波是对一个滑动窗口内的诸像素灰度值排序,用其中值代替窗口中心象素的原来灰度值,它是一种非线性的图像平滑法,它对脉冲干扰级椒盐噪声的抑制效果好,在抑制随机噪声的同时能有效保护边缘少受模糊

中值滤波可以过滤尖峰脉冲。目的在于我们对于滤波后的数据更感兴趣。滤波后的数据保留的原图像的变化趋势,同时去除了尖峰脉冲对分析造成的影响。

    以一维信号的中值滤波举例。对灰度序列80、120、90、200、100、110、70,如果按大小顺序排列,其结果为70、80、90、10O、110、120、200,其中间位置上的灰度值为10O,则该灰度序列的中值即为100。一维信号中值滤波实际上就是用中值代替规定位置(一般指原始信号序列中心位置)的信号值。对前面所举的序列而言,中值滤波的结果是用中值100替代序列80、120、90、200、100、110、70中的信号序列中心位置值200,得到的滤波序列就是80、120、90、100、100、110、70。如果在此序列中200是一个噪声信号,则用此方法即可去除这个噪声点。

    二维中值滤波算法是:对于一幅图像的象素矩阵,取以目标象素为中心的一个子矩阵窗口,这个窗口可以是3*3 ,5*5 等根据需要选取,对窗口内的象素灰度排序,取中间一个值作为目标象素的新灰度值。窗口示例如ooooxoooo上面x为目标象素,和周围o组成3*3矩阵Array,然后对这9个元素的灰度进行排序,以排序后的中间元素Array[4]为x的新灰度值,如此就完成对象素x的中值滤波,再迭代对其他需要的象素进行滤波即可。

中值滤波的基本思想是,把局部区域的像素按灰度等级进行排序,取该领域中灰度的中值作为当前像素的灰度值

    中值滤波的步骤为:

    1、将滤波模板(含有若干个点的滑动窗口)在图像中漫游,并将模板中心与图中某个像素位置重合;

    2、读取模板中各对应像素的灰度值;

    3、将这些灰度值从小到大排列;

    4、取这一列数据的中间数据,将其赋给对应模板中心位置的像素。如果窗口中有奇数个元素,中值取元素按灰度值大小排序后的中间元素灰度值。如果窗口中有偶数个元素,中值取元素按灰度值大小排序后,中间两个元素灰度的平均值。因为图像为二维信号,中值滤波的窗口形状和尺寸对滤波器效果影响很大,不同图像内容和不同应用要求往往选用不同的窗口形状和尺寸。

    由以上步骤,可以看出,中值滤波对孤立的噪声像素即椒盐噪声、脉冲噪声具有良好的滤波效果。由于其并不是简单的取均值,所以,它产生的模糊也就相对比较少。

I = im2double(imread('E:/0.jpg')); 
I = rgb2gray(I); 
I1 = imnoise(I,'salt & pepper'); 
I2 = medfilt2(I1); 
I3 = imnoise(I,'gaussian'); 
I4 = medfilt2(I3); 
 
subplot(2,2,1),imshow(I1); 
subplot(2,2,2),imshow(I2); 
subplot(2,2,3),imshow(I3); 
subplot(2,2,4),imshow(I4);

 

图像处理中,中值滤波的实现方法

 

1:通过从图像中的某个采样窗口取出奇数个数据进行排序
2:用排序后的中值取代要处理的数据即可
 
中值滤波的算法实现过程,重点是排序,最常用的冒泡排序~~
把滤波区间的数据从小到大进行排序,然后取中值,(如果是奇数个数据,那么中值就只有一个了,如果偶数个数据,中值有两个,可以对两个数据再求平均)
下面是一个C语言实现中值滤波的函数:
[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. unsigned char GetMedianNum(int * bArray, int iFilterLen)  
  2. {  
  3.     int i,j;// 循环变量  
  4.     unsigned char bTemp;  
  5.       
  6.     // 用冒泡法对数组进行排序  
  7.     for (j = 0; j < iFilterLen - 1; j ++)  
  8.     {  
  9.         for (i = 0; i < iFilterLen - j - 1; i ++)  
  10.         {  
  11.             if (bArray[i] > bArray[i + 1])  
  12.             {  
  13.                 // 互换  
  14.                 bTemp = bArray[i];  
  15.                 bArray[i] = bArray[i + 1];  
  16.                 bArray[i + 1] = bTemp;  
  17.             }  
  18.         }  
  19.     }  
  20.       
  21.     // 计算中值  
  22.     if ((iFilterLen & 1) > 0)  
  23.     {  
  24.         // 数组有奇数个元素,返回中间一个元素  
  25.         bTemp = bArray[(iFilterLen + 1) / 2];  
  26.     }  
  27.     else  
  28.     {  
  29.         // 数组有偶数个元素,返回中间两个元素平均值  
  30.         bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2;  
  31.     }  
  32.   
  33.     return bTemp;  
  34. }  
[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. 注:bArray 是一个整形指针,我们传入的一般是一个数组,用来存储待排序的数据  
  2.     iFilterLen 是滤波器的长度  
  3.    用在图像处理中时,由于像素的取值范围是0~255,刚好是unsigned char 的范围,所以函数的返回值是unsigned char,如果我们要处理的数是float型,或其他类型,返回值也可以更改~~返回值是bTemp,也即是我们想得到的中值  
[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <span style="color:#333333">下面是一个完整的C语言程序,用在图像处理中</span>  
 
[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. /************************************************************************* 
  2.  * 函数名称: 
  3.  *   MedianFilter() 
  4.  * 参数: 
  5.  *   int   iFilterH         - 滤波器的高度 
  6.  *   int   iFilterW         - 滤波器的宽度 
  7.  *   int   iFilterMX        - 滤波器的中心元素X坐标 
  8.  *   int   iFilterMY        - 滤波器的中心元素Y坐标 
  9.  * 说明: 
  10.  *   该函数对DIB图像进行中值滤波。 
  11.  ************************************************************************/  
  12. #define iFilterW 1  
  13. #define iFilterH 1  
  14. #define iFilterMX 1  
  15. #define iFilterMY 1  
  16. #define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4)  
  17.   
  18.   
  19. unsigned char GetMedianNum(int * bArray, int iFilterLen);  
  20. void MedianFilter(unsigned char *pImg1,unsigned char *pImg,int nWidth,int nHeight)  
  21. {         
  22.     unsigned char   *lpSrc;                         // 指向源图像的指针   
  23.     unsigned char   *lpDst;                         // 指向要复制区域的指针  
  24.     int         aValue[iFilterH*iFilterW];          // 指向滤波器数组的指针  
  25.     int         i,j,k,l;                            // 循环变量   
  26.     int         lLineBytes;                         // 图像每行的字节数   
  27.     lLineBytes = WIDTHBYTES(nWidth * 8);  
  28.     for ( i=0;i<nWidth;i++,pImg++ )  
  29.         (*pImg)=0;  
  30.     // 开始中值滤波  
  31.     // 行(除去边缘几行)  
  32.     for(i = iFilterMY; i < nHeight - iFilterH + iFilterMY + 1; i++)  
  33.     {  
  34.         // 列(除去边缘几列)  
  35.         for(j = iFilterMX; j < nWidth - iFilterW + iFilterMX + 1; j++)  
  36.         {  
  37.             // 指向新DIB第i行,第j个象素的指针  
  38.             lpDst = pImg + lLineBytes * (nHeight - 1 - i) + j;  
  39.               
  40.             // 读取滤波器数组  
  41.             for (k = 0; k < iFilterH; k++)  
  42.             {  
  43.                 for (l = 0; l < iFilterW; l++)  
  44.                 {  
  45.                     // 指向DIB第i - iFilterMY + k行,第j - iFilterMX + l个象素的指针  
  46.                     lpSrc = pImg1 + lLineBytes * (nHeight - 1 - i + iFilterMY - k) + j - iFilterMX + l;  
  47.                   
  48.                     // 保存象素值  
  49.                     aValue[k * iFilterW + l] = *lpSrc;  
  50.                 }  
  51.             }  
  52.               
  53.             // 获取中值  
  54.             * lpDst = GetMedianNum(aValue, iFilterH * iFilterW);  
  55.         }  
  56.     }  
  57.   
  58. }  
  59.   
  60. unsigned char GetMedianNum(int * bArray, int iFilterLen)  
  61. {  
  62.     int     i,j;            // 循环变量  
  63.     unsigned char bTemp;  
  64.       
  65.     // 用冒泡法对数组进行排序  
  66.     for (j = 0; j < iFilterLen - 1; j ++)  
  67.     {  
  68.         for (i = 0; i < iFilterLen - j - 1; i ++)  
  69.         {  
  70.             if (bArray[i] > bArray[i + 1])  
  71.             {  
  72.                 // 互换  
  73.                 bTemp = bArray[i];  
  74.                 bArray[i] = bArray[i + 1];  
  75.                 bArray[i + 1] = bTemp;  
  76.             }  
  77.         }  
  78.     }  
  79.       
  80.     // 计算中值  
  81.     if ((iFilterLen & 1) > 0)  
  82.     {  
  83.         // 数组有奇数个元素,返回中间一个元素  
  84.         bTemp = bArray[(iFilterLen + 1) / 2];  
  85.     }  
  86.     else  
  87.     {  
  88.         // 数组有偶数个元素,返回中间两个元素平均值  
  89.         bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2;  
  90.     }  
  91.       
  92.     return bTemp;  
  93. }  
posted @ 2016-06-23 13:34  emg0818  阅读(5611)  评论(0编辑  收藏  举报