关于中值滤波算法,以及C语言实现

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: 用排序后的中值取代要处理的数据即可
中值滤波的算法实现过程,重点是排序,最常用的冒泡排序~~
把滤波区间的数据从小到大进行排序,然后取中值,(如果是奇数个数据,那么中值就只有一个了,如果偶数个数据,中值有两个,可以对两个数据再求平均)

下面是一个C语言实现中值滤波的函数:

unsigned char GetMedianNum(int * bArray, int iFilterLen)
{
	int i,j;// 循环变量
	unsigned char bTemp;
	
	// 用冒泡法对数组进行排序
	for (j = 0; j < iFilterLen - 1; j ++)
	{
		for (i = 0; i < iFilterLen - j - 1; i ++)
		{
			if (bArray[i] > bArray[i + 1])
			{
				// 互换
				bTemp = bArray[i];
				bArray[i] = bArray[i + 1];
				bArray[i + 1] = bTemp;
			}
		}
	}
	
	// 计算中值
	if ((iFilterLen & 1) > 0)
	{
		// 数组有奇数个元素,返回中间一个元素
		bTemp = bArray[(iFilterLen + 1) / 2];
	}
	else
	{
		// 数组有偶数个元素,返回中间两个元素平均值
		bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2;
	}

	return bTemp;
}

注:bArray 是一个整形指针,我们传入的一般是一个数组,用来存储待排序的数据  
    iFilterLen 是滤波器的长度  
   用在图像处理中时,由于像素的取值范围是0~255,刚好是unsigned char 的范围,所以函数的返回值是unsigned char,如果我们要处理的数是float型,或其他类型,返回值也可以更改~~返回值是bTemp,也即是我们想得到的中值  
下面是一个完整的C语言程序,用在图像处理中

/************************************************************************* 
 * 函数名称: 
 *   MedianFilter() 
 * 参数: 
 *   int   iFilterH         - 滤波器的高度 
 *   int   iFilterW         - 滤波器的宽度 
 *   int   iFilterMX        - 滤波器的中心元素X坐标 
 *   int   iFilterMY        - 滤波器的中心元素Y坐标 
 * 说明: 
 *   该函数对DIB图像进行中值滤波。 
 ************************************************************************/  
#define iFilterW 1  
#define iFilterH 1  
#define iFilterMX 1  
#define iFilterMY 1  
#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4)  
  
  
unsigned char GetMedianNum(int * bArray, int iFilterLen);  
void MedianFilter(unsigned char *pImg1,unsigned char *pImg,int nWidth,int nHeight)  
{         
    unsigned char   *lpSrc;                         // 指向源图像的指针   
    unsigned char   *lpDst;                         // 指向要复制区域的指针  
    int         aValue[iFilterH*iFilterW];          // 指向滤波器数组的指针  
    int         i,j,k,l;                            // 循环变量   
    int         lLineBytes;                         // 图像每行的字节数   
    lLineBytes = WIDTHBYTES(nWidth * 8);  
    for ( i=0;i<nWidth;i++,pImg++ )  
        (*pImg)=0;  
    // 开始中值滤波  
    // 行(除去边缘几行)  
    for(i = iFilterMY; i < nHeight - iFilterH + iFilterMY + 1; i++)  
    {  
        // 列(除去边缘几列)  
        for(j = iFilterMX; j < nWidth - iFilterW + iFilterMX + 1; j++)  
        {  
            // 指向新DIB第i行,第j个象素的指针  
            lpDst = pImg + lLineBytes * (nHeight - 1 - i) + j;  
              
            // 读取滤波器数组  
            for (k = 0; k < iFilterH; k++)  
            {  
                for (l = 0; l < iFilterW; l++)  
                {  
                    // 指向DIB第i - iFilterMY + k行,第j - iFilterMX + l个象素的指针  
                    lpSrc = pImg1 + lLineBytes * (nHeight - 1 - i + iFilterMY - k) + j - iFilterMX + l;  
                  
                    // 保存象素值  
                    aValue[k * iFilterW + l] = *lpSrc;  
                }  
            }  
              
            // 获取中值  
            * lpDst = GetMedianNum(aValue, iFilterH * iFilterW);  
        }  
    }  
  
}  
  
unsigned char GetMedianNum(int * bArray, int iFilterLen)  
{  
    int     i,j;            // 循环变量  
    unsigned char bTemp;  
      
    // 用冒泡法对数组进行排序  
    for (j = 0; j < iFilterLen - 1; j ++)  
    {  
        for (i = 0; i < iFilterLen - j - 1; i ++)  
        {  
            if (bArray[i] > bArray[i + 1])  
            {  
                // 互换  
                bTemp = bArray[i];  
                bArray[i] = bArray[i + 1];  
                bArray[i + 1] = bTemp;  
            }  
        }  
    }  
      
    // 计算中值  
    if ((iFilterLen & 1) > 0)  
    {  
        // 数组有奇数个元素,返回中间一个元素  
        bTemp = bArray[(iFilterLen + 1) / 2];  
    }  
    else  
    {  
        // 数组有偶数个元素,返回中间两个元素平均值  
        bTemp = (bArray[iFilterLen / 2] + bArray[iFilterLen / 2 + 1]) / 2;  
    }  
      
    return bTemp;  
}  



  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值