数字图像处理,中值滤波和均值滤波及其改进算法的C++实现

转载 2014年08月31日 15:02:47

中值滤波

中值滤波法是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值.中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,中值滤波的基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声点。方法是用某种结构的二维滑动模板,将板内像素按照像素值的大小进行排序,生成单调上升(或下降)的为二维数据序列。二维中值滤波输出为g(x,y)=med{f(x-k,y-l),(k,l∈W)} ,其中,f(x,y),g(x,y)分别为原始图像和处理后图像。W为二维模板,通常为3*3,5*5区域,也可以是不同的的形状,如线状,圆形,十字形,圆环形等。

以3*3的滤波窗口为例:

中值滤波就是在3*3中的像素中寻找中值。 来看这样一个描述图(不然无图无真相)

这把可以清晰地看到, 这里有6,2,0,3,97,4,19,3,10这些像素, 然后中间的这些像素值就被这些像素的中位数也就是中值取代了。为了满足和前面一篇文章的格式相对应, 我们马上进入下一个单元, 来看看在平滑和降噪方面的功效!

原图1                                                                           中值滤波之后

 

噪声图(5%)                                                                中值滤波后:

 

很明显中值滤波不仅使得图像变得平滑(也可以理解为图像变得模糊了),但是其对去除了椒盐噪声特别有效,因为中值滤波就是专门针对去除孤立点噪声孕育为生的。从这里中值的逻辑来看, 我们做中值操作的时候, 那么白色(接近255的像素点)和黑色(接近0的像素)因为在窗口排序时是最大最小值, 除非周围的颜色都是黑色或者白色,不然一般都会被剔除掉,所以,一般来说这个中值滤波是去除椒盐噪声的非常理想的选择。

最后还是贴一段我运行的代码:

////////////////中值滤波////////////////////////////////
int media_filter(unsigned char* inbuffer, int width, int height, unsigned char* outbuffer)
{
	int mid=0;
	int winsize = 3;//滤波窗口大小
	int* windows = new int[winsize*winsize];
	int pos = (winsize - 1) / 2;
	memcpy(outbuffer, inbuffer, width*height);
	for (int m = pos; m < height - pos; m++)
	{
		for (int n = pos; n < width - pos; n++)//(m,n)是窗口中心位置
		{
			//提取winsize*winsize的数据进入滤波窗
			int winpos = 0;
			for (int i = -pos; i < (winsize - pos); i++)
				for (int j = -pos; j < (winsize - pos); j++)
					windows[winpos++] = inbuffer[(m + i)*width + n + j];
			//对滤波窗中的数据排序取中值
			sort(windows, winsize*winsize);
			mid = windows[(winsize*winsize)/2];
			outbuffer[m*width + n] = mid;
		}
	}
	//对边界进行处理
	//未被处理的地方均取被处理的最边界
	for (int k = 0; k < pos; k++)
	for (int l = pos; l < width - pos; l++)
		outbuffer[k*width + l] = outbuffer[pos * width + l];//1到pos这几行未被处理的边界数据,始终取被处理的最上边界一层像素

	for (int a = height - pos; a < height; a++)
	for (int b = pos; b < width - pos; b++)
		outbuffer[a*width + b] = outbuffer[(height - pos - 1)*width + b];

	for (int c = 0; c < pos; c++)
	for (int d = 0; d < height; d++)
		outbuffer[d*width + c] = outbuffer[d*width + pos];

	for (int e = width - pos; e < width; e++)
	for (int f = 0; f < height; f++)
		outbuffer[f*width + e] = outbuffer[f*width + width - pos - 1];
	
	delete[] windows;
	windows = NULL;
	return 0;
}



均值滤波

把每个像素都用周围的9个像素来做均值操作 ”, 比如说这里有一个例子:

 

sample

非常明显的, 这个3*3区域像素的颜色值分别是5,3,6,2,1,9,8,4,7那么中间的1这个像素的过滤后的值就是这些值的平均值, 也就是前面的计算方法: (5+3+6+2+1+9+8+4+7)/9=5

一目了然。那么这个均值滤波器有什么用处呢?

主要还是平滑图像的用处, 有的图像的锐度很高,用这样的均值算法,可以把锐度降低。使得图像看上去更加自然,下面就有几幅图我们可以看出一些端倪:

原图:                                                                          原图均值滤波处理之后:

 

这里还是可以明显的感觉到不同的, 没有好坏之分,就是第二幅图片看上去更为平滑。 继续我们的问题, 那这里均值平滑是否具有去除噪声的功能呢? 我们搞来了椒盐噪声(就是随机的白点,黑点)来试试手:

噪声图(5%椒盐噪声):                         均值滤波平滑处理之后:

 

首先这里的噪声还是比较小的, 只有5%,从均值的效果来看的话, 我可以说几乎没有用,其实直观的想也可以判断, 因为这里的处理并没有剔除这些噪声点, 而只是微弱地降低了噪声,所以效果可以想见的。。

好吧, 最后的时候还是贴上一段处理的C++均值滤波算法代码:


////////////////均值滤波////////////////////////////////
int mean_filter(unsigned char* inbuffer, int width, int height, unsigned char* outbuffer)
{
	int mid=0;
	int winsize = 3;//滤波窗口大小
	int* windows = new int[winsize*winsize];
	int pos = (winsize - 1) / 2;
	memcpy(outbuffer, inbuffer, width*height);
	for (int m = pos; m < height - pos; m++)
	{
		for (int n = pos; n < width - pos; n++)//(m,n)是窗口中心位置
		{
			//提取winsize*winsize的数据进入滤波窗
			int winpos = 0;
			for (int i = -pos; i < (winsize - pos); i++)
				for (int j = -pos; j < (winsize - pos); j++)
					windows[winpos++] = inbuffer[(m + i)*width + n + j];
			mid=getaverage(windows, winsize*winsize);//对滤波窗中的数据取平均值
			outbuffer[m*width + n] = mid;
		}
	}
	//对边界进行处理
	//未被处理的地方均取被处理的最边界
	for (int k = 0; k < pos; k++)
	for (int l = pos; l < width - pos; l++)
		outbuffer[k*width + l] = outbuffer[pos * width + l];//1到pos这几行未被处理的边界数据,始终取被处理的最上边界一层像素

	for (int a = height - pos; a < height; a++)
	for (int b = pos; b < width - pos; b++)
		outbuffer[a*width + b] = outbuffer[(height - pos - 1)*width + b];

	for (int c = 0; c < pos; c++)
	for (int d = 0; d < height; d++)
		outbuffer[d*width + c] = outbuffer[d*width + pos];

	for (int e = width - pos; e < width; e++)
	for (int f = 0; f < height; f++)
		outbuffer[f*width + e] = outbuffer[f*width + width - pos - 1];
	
	delete[] windows;
	windows = NULL;
	return 0;
}


一种改进的中值滤波(HMF)

在中值滤波器和均值滤波器之后, 这次看到是中值滤波器的改进, Hybrid Median Filter ,这个名字我实在不好把握实在不知道翻译成什么比较妥当.只好沿用了混合动力车里面的混合二字, 姑且把这种滤波器命名为混合中值滤波器. 这个滤波器的工作流程较之原先有些繁琐, 来看看这张图

flow

图截的有些模糊, 但是还是看出了大致的流程, 首先当前像素的上下左右和自身取中值1 然后左上右上左下右下和自身取中值2 完了前面的两个中值和当前像素值再取一次中值 , 得到的值就是最后的终极像素值了. 可以看到这个流程还是有些复杂的.. 那他的效果如何捏? 我们还是和前几次一样来观察一把:

原图:                                                      HMF之后:

 

噪声污染:                                                 HMF之后:

 

从前面的图片可以看到, 图片从高锐度经由混合中值滤波之后, 锐度下降了. 但是在去噪声的环节上, 这个所谓的混合中值滤波器表现的甚至不如中值滤波来的效果好, 当然因为这里的噪声是随机的, 可能有些因素在其中. 但从原理上分析.这种滤波器确实存在不能过滤掉的可能, 原因在什么地方呢? 且看我们这个大图中的一个小局部:

把图放大之后看的很清楚了, 在红色的圆圈圈出来的地方, 不出意外的发现了水平连续的3个白色像素. 再联想到我们之前经过HMF之后的效果图就不难得出结论, 就是者连续的3个点造成了最后的这个白色像素. 怎么说呢? 很简单, 在HMF的第一步过程中, 因为我们选择的点是5各点, 上下左右中, 那么经过计算, 就是白色无疑了, 不管第二步得到什么像素, 在第三步的时候, 让2个白色取中值, 肯定得到的白色像素了! 仔细想来确实是这个么道理.  但是median filter的时候因为要整体考虑9个像素的中值, 这里很有可能就不是白色了! 所以这个混合中值滤波器会在保持线条的边缘上有独到之处(因为比较容易保持联系像素的颜色不受伤害), 而消除噪声还是median filter表现更胜一筹.老规矩, 最后再贴一下处理的函数代码:

unsigned char median(unsigned char* elements, int width)  
{  
    //   Order elements (only half of them)  
    for (int i = 0; i < (width >> 1) + 1; ++i)  
    {  
        //   Find position of minimum element  
        int min = i;  
        for (int j = i + 1; j < width; ++j)  
            if (elements[j] < elements[min])  
                min = j;  
        //   Put found minimum element in its place  
        unsigned char temp = elements[i];  
        elements[i] = elements[min];  
        elements[min] = temp;  
    }  
    //   Get result - the middle element  
    return elements[width >> 1];  
}  
/** 
** method to remove noise from the corrupted image by hybrid median value 
* @param corrupted input grayscale binary array with corrupted info 
* @param smooth output data for smooth result, the memory need to be allocated outside of the function 
* @param width width of the input grayscale image 
* @param height height of the input grayscale image 
*/  
void hybridMedianFilter (unsigned char* corrupted, unsigned char* smooth, int width, int height)  
{  
    memcpy ( smooth, corrupted, width*height*sizeof(unsigned char) );  
    for (int j=1;j<height-1;j++)  
    {  
        for (int i=1;i<width-1;i++)  
        {  
            unsigned char window[5];  
            unsigned char results[3];  
            //   Pick up cross-window elements  
            window[0] = corrupted[(j - 1) * width + i];  
            window[1] = corrupted[j * width + i - 1];  
            window[2] = corrupted[j * width + i];  
            window[3] = corrupted[j * width + i + 1];  
            window[4] = corrupted[(j + 1) * width + i];  
            //   Get median  
            results[0] = median(window, 5);  
            //   Pick up x-window elements  
            window[0] = corrupted[(j - 1) * width + i - 1];  
            window[1] = corrupted[(j - 1) * width + i + 1];  
            window[2] = corrupted[j * width + i];  
            window[3] = corrupted[(j + 1) * width + i - 1];  
            window[4] = corrupted[(j + 1) * width + i + 1];  
            //   Get median  
            results[1] = median(window, 5);  
            //   Pick up leading element  
            results[2] = corrupted[j * width + i];  
            //   Get result  
            smooth[j*width+i] = median(results, 3);  
        }  
    }  
}

因为要取中值, 还附加了一个取中值的函数median



实验结果:

以下所有结果均为C++处理。
1,对原图像进行处理的结果
可以发现对边缘有就很好的保护能力:(左为原图)


2,对噪声图像进行处理的结果
注意这是matlab里面的椒盐噪声,最左边是噪声图像,中间是本文改进中值滤波(HMF)算法,最右边是自适应中值滤波。
去噪效果一般。椒盐是中值滤波系列最容易处理的噪声,可以见得该改进算法有它的不足之处,在椒盐噪声的处理效果上明显不如经典的自适应中值滤波!



中值滤波对噪声图像的效果,存在明显的不足(模糊效果):





参考资源:

【1】百度百科,http://baike.baidu.com/link?url=mQ37rozxl6jHqzdVY56zOO_tpSvInR0EA8AGK5W242ljIXOxPz_xtTT8Bgi8fOVocmp6XpiI1FK6byALfUir1a

【2】hhygcy,http://blog.csdn.net/hhygcy/article/details/4325462


注:本文是在原作者hhygcy基础上二次加工重写,代码有较大改动

十大滤波算法程序大全

转载请注明出处:http://www.geek-workshop.com/thread-7694-1-1.html 1、限幅滤波法(又称程序判断滤波法) 2、中位值滤波法 3、算术平...

均值滤波、中值滤波的matlab实现

目前比较经典的图像去噪算法主要有以下三种:   均值滤波算法:也称线性滤波,主要思想为邻域平均法,即用几个像素灰度 的平均值来代替每个像素的灰度。有效抑制加性噪声,但容易引起图像模糊, 可以对...

算法学习笔记之滑动平均滤波算法

滑动平均滤波算法只采样一次,将一次采样值和过去的若干次采样值一起求平均,得到的有效采样值即可投入使用。如果取N个采样值求平均,存储区中必须开辟N个数据的暂存区。每新采集一个数据便存入暂存区中,同时去掉...

图像噪声的抑制——均值滤波、中值滤波、对称均值滤波

概述 噪声对图像处理的影响很大,它影响图像处理的输入、采集和处理等各个环节以及输出结果。因此,在进行其它的图像处理前,需要对图像进行去噪处理。 从统计学的观点来看,凡是统计特征不随时间变化的噪...
  • luoweifu
  • luoweifu
  • 2012年11月05日 19:05
  • 38567

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

图像处理之滤波算法

一、学习心得: 在我学习基本滤波算法原理的时候,因为刚接触不是很理解算法具体是怎样实现的,不过在学习了图像形态学之后,发现滤波算法其实很简单。所以在此建议初学者在学习滤波算法之前,可以先...

图像滤波常见方法原理总结及VC下实现

在进行图像目标识别与跟踪时,摄像机所采集的图像,在成像、数字化以及传输过程中,难免会受到各种各样噪声的干扰,图像的质量往往会出现不尽人意的退化,影响了图像的视觉效果。通常这些噪声干扰使得图像退化,表现...

图像卷积与滤波的一些知识点

图像卷积与滤波的一些知识点zouxy09@qq.comhttp://blog.csdn.net/zouxy09       之前在学习CNN的时候,有对卷积经常一些学习和整理,后来就烂尾了,现在稍微整...
  • zouxy09
  • zouxy09
  • 2015年10月12日 21:24
  • 91710

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

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

中值滤波的快速算法

我想学过图像处理的人没有人会不知道中值滤波的,最早的时候我是在冈萨雷斯的图像处理课本[1]中学到的,后来在看Sonka的书[2]的时候又看到了中值滤波的介绍,下面我试着结合课本所学和网上的资料自己整理...
  • Linoi
  • Linoi
  • 2014年09月09日 15:18
  • 4593
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:数字图像处理,中值滤波和均值滤波及其改进算法的C++实现
举报原因:
原因补充:

(最多只允许输入30个字)