滤波处理分为两大类:线性滤波和非线性滤波。OpenCV里有这些滤波的函数,使用起来非常方便,现在简单介绍其使用方法。 线性滤波: 1.方框滤波:模糊图像 2.均值滤波:模糊图像 3.高斯滤波:信号的平滑处理,去除符合正太分布的噪声 非线性滤波 1.中值滤波:去除椒盐噪声 2.双边滤波:保边去噪 下面对滤波方法进行一一介绍: 方框滤波(box Filter)方框滤波(box Filter)被封装在一个名为boxblur的函数中,即boxblur函数的作用是使用方框滤波器(box filter)来模糊一张图片,从src输入,从dst输出 CV_EXPORTS_W void boxFilter( InputArray src, OutputArray dst, int ddepth,Size ksize, Point anchor=Point(-1,-1),bool normalize=true,int borderType=BORDER_DEFAULT ); 参数解释:
boxFilter()函数方框滤波所用的核为: 其中f表示原图,h表示核,g表示目标图,当normalize=true的时候,方框滤波就变成了我们熟悉的均值滤波。也就是说,均值滤波是方框滤波归一化(normalized)后的特殊情况。其中,归一化就是把要处理的量都缩放到一个范围内,比如(0,1),以便统一处理和直观量化。 而非归一化(Unnormalized)的方框滤波用于计算每个像素邻域内的积分特性,比如密集光流算法(dense optical flow algorithms)中用到的图像倒数的协方差矩阵(covariance matrices of image derivatives) 如果我们要在可变的窗口中计算像素总和,可以使用integral()函数。 2、均值滤波——blur函数均值滤波是最简单的一种滤波操作,输出图像的每一个像素是核窗口内输入图像对应像素的像素的平均值( 所有像素加权系数相等),其实说白了它就是归一化后的方框滤波。blur函数内部中其实就是调用了一下boxFilter。 均值滤波是典型的线性滤波算法,主要方法为邻域平均法,即用一片图像区域的各个像素的均值来代替原图像中的各个像素值。一般需要在图像上对目标像素给出一个模板(内核),该模板包括了其周围的临近像素(比如以目标像素为中心的周围8(3x3-1)个像素,构成一个滤波模板,即去掉目标像素本身)。再用模板中的全体像素的平均值来代替原来像素值。即对待处理的当前像素点(x,y),选择一个模板,该模板由其近邻的若干像素组成,求模板中所有像素的均值,再把该均值赋予当前像素点(x,y),作为处理后图像在该点上的灰度g(x,y),即g(x,y)=1/m ∑f(x,y) ,其中m为该模板中包含当前像素在内的像素总个数。 均值滤波的缺陷: 均值滤波本身存在着固有的缺陷,即它不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪声点。特别是椒盐噪声 blur函数文档中,给出的其核是这样的: CV_EXPORTS_W void blur( InputArray src, OutputArray dst,Size ksize, Point anchor=Point(-1,-1),int borderType=BORDER_DEFAULT ); 参数说明: 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。该函数对通道是独立处理的,且可以处理任意通道数的图片,但需要注意,待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一。 第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。 第三个参数,Size类型(对Size类型稍后有讲解)的ksize,内核的大小。一般这样写Size( w,h )来表示内核的大小( 其中,w 为像素宽度, h为像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小 第四个参数,Point类型的anchor,表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。 第五个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它。 3、高斯滤波——GaussianBlur函数高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。高斯滤波最有用的滤波操作,虽然效率往往不是最高的。需要注意的是opencv中的GaussianBlur()是高斯低通滤波器,用来模糊减噪,所以叫高斯模糊。 高斯模糊技术生成的图像,其视觉效果就像是经过一个半透明屏幕在观察图像,这与镜头焦外成像效果散景以及普通照明阴影中的效果都明显不同。高斯平滑也用于计算机视觉算法中的预先处理阶段,以增强图像在不同比例大小下的图像效果(参见尺度空间表示以及尺度空间实现)。从数学的角度来看,图像的高斯模糊过程就是图像与正态分布做卷积。由于正态分布又叫作高斯分布,所以这项技术就叫作高斯模糊。 图像与圆形方框模糊做卷积将会生成更加精确的焦外成像效果。由于高斯函数的傅立叶变换是另外一个高斯函数,所以高斯模糊对于图像来说就是一个低通滤波操作。高斯滤波器是一类根据高斯函数的形状来选择权值的线性平滑滤波器。高斯平滑滤波器对于抑制服从正态分布的噪声非常有效。对于图像处理来说,常用二维零均值离散高斯函数作平滑滤波器。 一维零均值高斯函数和二维高斯函数为: 其中,高斯分布参数Sigma决定了高斯函数的宽度。sigma的取值决定了高斯函数窗口的大小。在实际中经常看到sigma取值0.8或者1。正常情况下我们由高斯函数计算得到的模板是浮点型数,即double,但是有些情况我们为了加快计算需要将模板处理成整数,对于常见的3x3或者5x5其整数模板如下: 整数模板用的比较多,常见的3x3或者5x5的整数模板如下。更多高斯滤波的讲解可以参考下面这篇博客http://blog.csdn.net/yansmile1/article/details/46275791 from:https://blog.csdn.net/kuweicai/article/details/74276824 GaussianBlur函数的作用是用高斯滤波器来模糊一张图片,对输入的图像src进行高斯滤波后用dst输出。它将源图像和指定的高斯核函数做卷积运算,并且支持就地过滤(In-placefiltering)。 CV_EXPORTS_W void GaussianBlur( InputArray src,OutputArray dst, Size ksize,double sigmaX, double sigmaY=0,int borderType=BORDER_DEFAULT ); 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。它可以是单独的任意通道数的图片,但需要注意,图片深度应该为CV_8U,CV_16U, CV_16S, CV_32F 以及 CV_64F之一。 非线性滤波之前我们所考虑的滤波器都是线性的,即两个信号之和的响应和他们各自响应之和相等。换句话说,每个像素的输出值是一些输入像素的加权和,线性滤波器易于构造,并且易于从频率响应角度来进行分析。其实在很多情况下,使用邻域像素的非线性滤波也许会得到更好的效果。比如在噪声是散粒噪声而不是高斯噪声,即图像偶尔会出现很大的值的时候。在这种情况下,用高斯滤波器对图像进行模糊的话,噪声像素是不会被去除的,它们只是转换为更为柔和但仍然可见的散粒。 中值滤波——medianBlur()中值滤波(Median filter)是一种典型的非线性滤波技术,基本思想是用像素点邻域灰度值的中值来代替该像素点的灰度值,该方法在去除脉冲噪声、椒盐噪声的同时又能保留图像边缘细节,中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,其基本原理是把数字图像或数字序列中一点的值用该点的一个邻域中各点值的中值代替,让周围的像素值接近的真实值,从而消除孤立的噪声点,对于斑点噪声(speckle noise)和椒盐噪声(salt-and-pepper noise)来说尤其有用,因为它不依赖于邻域内那些与典型值差别很大的值。中值滤波器在处理连续图像窗函数时与线性滤波器的工作方式类似,但滤波过程却不再是加权运算。 中值滤波在一定的条件下可以克服常见线性滤波器如最小均方滤波、方框滤波器、均值滤波等带来的图像细节模糊,而且对滤除脉冲干扰及图像扫描噪声非常有效,也常用于保护边缘信息, 保存边缘的特性使它在不希望出现边缘模糊的场合也很有用,是非常经典的平滑噪声处理方法。 CV_EXPORTS_W void medianBlur( InputArray src, OutputArray dst, int ksize ); 第一个参数,InputArray类型的src,函数的输入参数,填1、3或者4通道的Mat类型的图像;当ksize为3或者5的时候,图像深度需为CV_8U,CV_16U,或CV_32F其中之一,而对于较大孔径尺寸的图片,它只能是CV_8U。 第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。我们可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。 第三个参数,int类型的ksize,孔径的线性尺寸(aperture linear size),注意这个参数必须是大于1的奇数,比如:3,5,7,9 顾名思义,中值滤波选择每个像素的邻域像素中的中值作为输出,或者说中值滤波将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值。 例如,取3 x 3的函数窗,计算以点[i,j]为中心的函数窗像素中值步骤如下: (1) 按强度值大小排列像素点. (2) 选择排序像素集的中间值作为点[i,j]的新值. 这一过程如图下图所示: 一般采用奇数点的邻域来计算中值,但如果像素点数为偶数时,中值就取排序像素中间两点的平均值 中值滤波与均值滤波器比较 中值滤波器的优势: 在均值滤波器中,由于噪声成分被放入平均计算中,所以输出受到了噪声的影响,但在中值滤波器中,由于噪声成分很难选上,所以几乎不会影响到输出。因此同样用3x3区域进行处理,中值滤波消除的噪声能力更胜一筹。中值滤波无论是在消除噪声还是保存边缘方面都是一个不错的方法。 中值滤波器的劣势: 中值滤波花费的时间是均值滤波的5倍以上。 双边滤波——bilateralFilter()双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、非迭代、局部的特点。双边滤波器的好处是可以做边缘保存(edge preserving),一般过去用的维纳滤波或者高斯滤波去降噪,都会较明显地模糊边缘,对于高频细节的保护效果并不明显。 双边滤波方法,主要是针对Gauss 滤波中将Gauss 权系数直接与图像信息作卷积运算进行图像滤波的原理,将滤波权系数优化成Gauss 函数和图像亮度信息的乘积,优化后的权系数再与图像信息作卷积运算,这样就能在滤波的同时考虑到图像信息中的图像边缘信息,使图像在正常Gauss 滤波后很模糊的边缘信息得以保持清晰,并且图像边缘更加平滑。此方法对于彩色和灰度图像的滤波均适用,具有很强的实用性。但是由于保存了过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤波。 在双边滤波器中,输出像素的值依赖于邻域像素值的加权值组合: 公式右边就是中心像素点邻域内像素亮度值的加权平均。加权系数 其中d表示如下: 空间邻近度因子滤波对应图示: 亮度相似度因子r表示为: 亮度相似度因子: 两者相乘后,就会产生依赖于数据的双边滤波权重函数: 函数原型: CV_EXPORTS_W void bilateralFilter( InputArray src, OutputArray dst, int d,double sigmaColor, double sigmaSpace,int borderType=BORDER_DEFAULT );CV_EXPORTS_W void adaptiveBilateralFilter( InputArray src, OutputArray dst, Size ksize,double sigmaSpace, double maxSigmaColor = 20.0,Point anchor=Point(-1, -1),int borderType=BORDER_DEFAULT ); InputArray src: 输入图像,可以是Mat类型,图像必须是8位或浮点型单通道、三通道的图像。 int borderType=BORDER_DEFAULT: 用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT. ksize为滤波内核的大小; sigmaSpace为距离权值公式中的方差; maxSigmaColor为相似度权值公式中的方差的最大值,自适应双边滤波的相似度方差的结果太大,超过了该值,则以该值为准; anchor为内核锚点,默认中心点; borderType表示用什么方式来处理加宽后的图像四周边界。 这里还需要说明的是自适应双边滤波adaptiveBilateralFilter要比双边滤波bilareralFilter运行时间更长,而且从源码来看,明显感觉到两个函数不是一个人写的。更重要的是adaptiveBilateralFilter有bug,当滤波内核尺寸取得更大一些的话,比如Size(10,10),会出现“The application has requested the Runtime toterminate in an unusual way,……”的错误对话框 实例:#include<iostream>#include<opencv2\opencv.hpp>#include<opencv2\imgproc\imgproc.hpp>using namespace std;using namespace cv;int main(){Mat src, dst, dst1, dst2, dst3,dst31;Mat img = imread("111.jpg", 1);img.copyTo(src);//深拷贝double sigma1 = 10.0;double sigma2 = 20.0;boxFilter(src, dst, -1, Size(5, 5));blur(src, dst1, Size(5, 5));GaussianBlur(src, dst2, Size(9, 9), sigma1, sigma2);//高斯滤波medianBlur(src, dst3, 7);//第三个参数表示孔径的线性尺寸,它的值必须是大于1的奇数bilateralFilter(src, dst31, 25, 25 * 2, 25 / 2);imshow("src", src);imshow("方框", dst);imshow("均值", dst1);imshow("高斯", dst2);imshow("中值", dst3);imshow("双边", dst31); 结果: |
|