中值滤波,C语言实现(开园第一篇)

 在学习的道路上,看了许多博客,受益良多。随着看过的内容越来越多,有时很难再找到之前看过的内容,遂决定自己也开一个博客,记录学习的历程。主要是为了方便自己查阅,也许某一天,也能帮助到别人。最近在做毕业设计,需要使用到中值滤波这样的常规图像处理算法,往常都是使用OpenCV中自带的函数进行滤波,非常方便。然而,这次滤波的对象不是一个“正经”的图,它是内存中的一块连续数据,转换成OpenCV中的Mat并不方便,也不搞笑。只好采用直接读取数据进行滤波,需要自己写一段中值滤波。好在中值滤波思想很简单,很容易就能想通是怎么做的,简单的来说就是以一个点的一定邻域内数据的中值来代替这个点的数值。以下内容来自foreverhuylee的博客: 什么是中值滤波? 中值滤波是对一个滑动窗口内的诸像素灰度值排序,用其中值代替窗口中心象素的原来灰度值,它是一种非线性的图像平滑法,它对脉冲干扰级椒盐噪声的抑制效果好,在抑制随机噪声的同时能有效保护边缘少受模糊。中值滤波可以过滤尖峰脉冲。目的在于我们对于滤波后的数据更感兴趣。滤波后的数据保留的原图像的变化趋势,同时去除了尖峰脉冲对分析造成的影响。    以一维信号的中值滤波举例。对灰度序列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:用排序后的中值取代要处理的数据即可 中值滤波的算法实现过程,重点是排序,最常用的冒泡排序~~把滤波区间的数据从小到大进行排序,然后取中值,(如果是奇数个数据,那么中值就只有一个了,如果偶数个数据,中值有两个,可以对两个数据再求平均)下面是一个C语言实现中值滤波的函数:
 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 }

 

 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 }  

 

 

 

 

 

相关内容推荐