图像滤波与OpenCV中的图像平滑处理
.About图像滤波
频率:可以这样理解图像频率,图像中灰度的分布构成一幅图像的纹理。图像的不同本质上是灰度分布规律的不同。但是诸如“蓝色天空”样的图像有着大面积近似的灰度强度,而某个充满微小物体的细微场景则灰度变化迅速。定义图像轻度变化快的信息为一幅图像的高频信息,鲤鱼边缘,定义变换缓慢的信息为低频信息。傅里叶变换或者余弦变换,可以明确的显示图像的频谱。
图像滤波意图在保证细节的情况下对目标图像的噪声进行抑制。是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。滤波的目的有两个:一是抽出对象的特征作为图像识别的特征模式;另一个是为适应图像处理的要求,消除图像数字化时所混入的噪声。其中限定条件为:一不能损坏图像的轮廓及边缘等重要信息;二使图像清晰视觉效果好。滤波旨在增强部分频段,同时限制或者衰减其他频段。
1.低通滤波器
1.1关于平滑(低通滤波)处理
平滑处理Smoothing也称为模糊处理bluring。使用简单频率高。目的一般是减少噪声点和失真,或者降低图像的分辨率。图像有用的信息集中在低频和中频。而高频有用信息往往被噪声淹没。因此降低高频噪声的滤波器(即低通滤波器或者平滑)就能削弱噪声影响。
1.2邻域算子
邻域的大小与效果有恒大关系,邻域越大效果越好,但边缘信息素损失大。利用给定像素周围的像素值的决定此像素的最终输出值的一种算子。而线性邻域滤波是一种常用的邻域算子,像素的输出值取决于输入像素的加权和。邻域算子除了用于局部色调调整以外,还可以用于图像滤波,实现图像的平滑和锐化,图像边缘增强或者图像噪声的去除。
1.3 OpenCV中的常见图像平滑方法
(1)方框滤波——boxblur函数-----线性邻域
(2)邻域平均滤 ——blur函数-----线性邻域
(3)高斯滤波——GaussianBlur函数----线性邻域
(4)中值滤波——medianBlur函数
(5)双边滤波——bilateralFilter函数
2.线性滤波器
线性滤波器:线性滤波器经常用于剔除输入信号中不想要的频率或者从许多频率中选择一个想要的频率。分为:
(1)允许低频率通过的低通滤波器(LPF)。
(2)允许高频率通过的高通滤波器(HPF)。
(3)允许一定范围频率通过的带通滤波器(BPF)。
(4)阻止一定范围频率通过并且允许其它频率通过的带阻滤波器(BSF)。
(5)允许所有频率通过、仅仅改变相位关系的全通滤波器(APF,all-pass filter,APF)。
(6)阻止一个狭窄频率范围通过的特殊带阻滤波器,陷波滤波器(如IIR digital wave notch filter)。
2.1方框滤波boxFilter()
函数原型:
C++:voidboxFilter(InputArray src,OutputArray dst, int ddepth, Size ksize, Pointanchor=Point(-1,-1), boolnormalize=true, int borderType=BORDER_DEFAULT )
参数说明:
(1)输入图像src,输出的同属性(尺寸和类型)图像dst,输出图像的深度ddepth(-1,表示原深度,即src.depth()),掩模尺寸或者核尺寸ksize.
(2)第五个参数,Point类型的anchor,表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。
(3)第六个参数,bool类型的normalize,默认值为true,一个标识符,表示内核是否被其区域归一化(normalized)了。
(4)第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它。
调用例子:
Mat src; Mat dst=src.clone();
BoxBlur(src,dst,-1,Size(5,5));//注意Size(5,5)为掩模尺寸,OpenCV中能够为偶数
2.2 均值滤波blur()
函数原型:
C++: void blur(InputArray src, OutputArraydst, Size ksize, Pointanchor=Point(-1,-1), int borderType=BORDER_DEFAULT )
参数说明:
(1) 输入图像src,即源图像,填Mat类的对象即可。该函数对通道是独立处理的,且可以处理任意通道数的图片,但需要注意,待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
(2) 输出图像dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
(3) Size类型(对Size类型稍后有讲解)的ksize,内核的大小。一般这样写Size( w,h )来表示内核的大小( 其中,w 为像素宽度, h为像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小
(4) Point类型的anchor,表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。
(5) int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,一般不管。
调用例子:
Mat src; Mat dst=src.clone();
blur(src,dst,Size(5,5)) //注意Size(5,5)为掩模尺寸,OpenCV中能够为偶数
2.3高斯平滑滤波器GaussianBlur()
像素的权重与它离开中心的距离成正相关。注意sigma越大曲线越平坦。高斯滤波器是可分离滤波器,可以先对图像的rows运用一维高斯滤波器(影响水平频率),再对图像的列运用一维高斯滤波器(影响的是垂直频率)。即2D高斯滤波器可以分离成2个1D高斯滤波器。
函数原型:
C++: void GaussianBlur(InputArray src,OutputArray dst, Size ksize,double sigmaX, double sigmaY=0, intborderType=BORDER_DEFAULT )
参数说明:
(1)InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。它可以是单独的任意通道数的图片,但需要注意,图片深度应该为CV_8U,CV_16U,CV_16S, CV_32F 以及 CV_64F之一。
(2) OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
(3) Size类型的ksize高斯内核的大小。其中ksize.width和ksize.height可以不同,但他们都必须为正数和奇数。或者,它们可以是零的,它们都是由sigma计算而来。
(4) double类型的sigmaX,表示高斯核函数在X方向的的标准偏差。
(5) double类型的sigmaY,表示高斯核函数在Y方向的的标准偏差。若sigmaY为零,就将它设为sigmaX,如果sigmaX和sigmaY都是0,那么就由ksize.width和ksize.height计算出来。
(6) int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它。
为了结果的正确性着想,最好是把第三个参数Size,第四个参数sigmaX和第五个参数sigmaY全部指定到。
调用例子:
Mat src;Mat dst=src.clone();
GaussianBlur(src,dst,Size(5,5),0.0,0.0);//注意此处尺寸必须为奇数
2.4其他相关函数
(1) 高斯掩模获得函数:
getGaussinaKernel();
Mat guass=getGaussinaKernel(9,sigma,CV_32F)
(2) 2D滤波函数cv:filter2D
(3) 可分离滤波器函数cv:sepFilter2D
以上参考:http://blog.csdn.net/poem_qianmo/article/details/22745559
3.非线性滤波器
线性滤波:输出是模板像素输入的加权和,f(a)+f(b)=f(a+b)。线性滤波器易于构造和从频率的角度分析。但某些时候,非线性滤波却有更好的效果。例如椒盐噪声,散粒噪声而非高斯噪声。线性滤波智能将此类散粒处理成更加柔和的散粒。
3.1中值滤波Median filter---medianBlur()
利用像素点邻域灰度值的中值来代替该像素点的灰度值。由于基于统计排序理论,输出几乎不受到噪声成分的影响。该方法在去除脉冲噪声、椒盐噪声的同时又能保留图像边缘细节。对滤除脉冲干扰及图像扫描噪声非常有效。中值滤波花费的时间是均值滤波的5倍以上。一般采用奇数点邻域,偶数点的去中间两点的平均值。但是对一些细节多,特别是线、尖顶等细节多的图像不宜采用中值滤波。
函数原型:
C++:void medianBlur(InputArray src,OutputArray dst, int ksize)
参数说明:
(1)InputArray类型的src,函数的输入参数,填1、3或者4通道的Mat类型的图像;当ksize为3或者5的时候,图像深度需为CV_8U,CV_16U,或CV_32F其中之一,而对于较大孔径尺寸的图片,它只能是CV_8U。
(2)OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。我们可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
(3)int类型的ksize,孔径的线性尺寸(aperture linearsize),注意这个参数必须是大于1的奇数,比如:3,5,7,9 ...
调用实例:
Mat src; Mat dst=src.clone();
medianBlur(src,dst,7);
3.2双边滤波Bilateral filter---bilateralFilter()
是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、非迭代、局部的特点。边缘保存(edgepreserving)效果好。维纳滤波或者高斯滤波去降噪都会较明显地模糊边缘,对于高频细节的保护效果并不明显。
双边滤波器顾名思义比高斯滤波多了一个高斯方差sigma-d,它是基于空间分布的高斯滤波函数,所以在边缘附近,离的较远的像素不会太多影响到边缘上的像素值,这样就保证了边缘附近像素值的保存。但是由于保存了过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤波。详细理论见链接。
函数原型:
C++: voidbilateralFilter(InputArray src, OutputArraydst, int d, double sigmaColor,double sigmaSpace, int borderType=BORDER_DEFAULT)
参数说明:
(1)InputArray类型的src,输入图像,即源图像,需要为8位或者浮点型单通道、三通道的图像。
(2)OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
(3)int类型的d,表示在过滤过程中每个像素邻域的直径。如果这个值我们设其为非正数,那么OpenCV会从第五个参数sigmaSpace来计算出它来。
(4)double类型的sigmaColor,颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
(5)double类型的sigmaSpace坐标空间中滤波器的sigma值,坐标空间的标注方差。他的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace。
(6)Int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。
调用实例:
Mat src; Mat dst=src.clone();
bilateralFilter(src, dst, 25, 25*2, 25/2 )
以上参考链接
http://blog.csdn.net/poem_qianmo/article/details/23184547