opencv3之滤波

                                   1.提取对象的特征(如深度学习中的卷机神经网络CNN)

图像滤波的作用

                                   2.消除噪声(图像处理,本节特指这一概念,也是本节的要写的内容)


噪声与信号:信号或能量大部分集中在低频或者中频段,噪声则大部分集中在高频段。(所以是否可以推断出大部分过滤噪声的滤波器可能都是低通滤波器)。


本篇文章将会先重点描述opencv3中提供的5中滤波器:线性滤波器三种(boxFilter方框滤波,blur均值滤波,GaussianBlur高斯滤波);非线性滤波器两种(mediaBlur中值滤波,bilateralFilter双边滤波)。


一、方框滤波与均值滤波

方框滤波与均值滤波放在一起讲,是因为两者本质上是一样的。方框滤波相当于在求卷积核所对应视野域输入图像像素的sum;均值滤波则是求均值sum/(k_size*ke_size),其中k_size是卷积核(或者说是滤波器)边长。可以通过设置opencv中方框滤波函数是否归一化的开关参数,来达到均值滤波的效果。

void boxFilter( InputArray src, OutputArray dst, int ddepth,
                             Size ksize, Point anchor = Point(-1,-1),
                             bool normalize = true,
                             int borderType = BORDER_DEFAULT )
其中可以看到normalize参数默认就是true所以默认情况下,方波滤波就是均值滤波。其卷积过程可以用下图表示:

opencv3之滤波_第1张图片

其中src为原mat,src方框外围的元素为pad元素。这是因为我们为了保证滤波之后的图片大小与滤波之前图片大小一致。根据公式(s_in+2*pad-s_k)+1=s_out。因为s_in=s_out。所以pad=(s_k-1)/2.0。至于pad元素应该填充什么值,是根据borderType这一参数的值来决定的默认是BORDER_DEFAULT是以边界元素为对称轴对称取元素(上图中即是这样)。为了验证是否卷积过程是这样,以左上角第一个元素为例子。

int main(int argc, char *argv[])
{
     Mat srcm=Mat::eye(5,5,CV_32FC1);
     cout<<"原始矩阵内容:"<
opencv3之滤波_第2张图片

从程序运行的结果可以证明我们之前的两个推论:1.pad的大小和填充数值的方式是没有问题的,从滤波之后左上角第一个元素5和5/9可以验证得到;2.归一化的方框滤波等同于均值滤波。

二、高斯滤波

事实上,用的最多的滤波应该还是高斯滤波,比如说边缘检测中的Sobel函数,Laplacian函数,Canny函数内部都会含有滤波这一步,都是用的Gaussian滤波。

二维高斯函数

opencv3之滤波_第3张图片

当sigma=1时,二维高斯核为

opencv3之滤波_第4张图片

相信大家可能和我一样有这样的疑问,为什么之前的中值滤波和均值滤波都是通过指定卷积核的尺寸Size(w,h)来确定卷积模板,而高斯滤波则指定了标准差sigma就可以确定高斯核,自己在写程序的时候如何确定卷机核大小,sigmax和sigmay。

先给出结论,现在有三个参数,size,sigmax,sigmay我们先假定sigmax=sigmay,通常卷积核的大小默认定义为3倍或者5倍sigma。上面的卷积核显然是默认了5倍。

再解释为什么,首先看opencv中Gaussian滤波的函数声明:

void GaussianBlur( InputArray src, OutputArray dst, Size ksize,
                                double sigmaX, double sigmaY = 0,
                                int borderType = BORDER_DEFAULT );
opencv中是这样规定的:最推荐的一种方式是:用户指定ksize,sigmaX,sigmaY三个参数。

                                         但我们作为用户是懒的,而且往往高斯滤波仅仅是一个系统中的一部分,起不了那么大作用,所以我们可以只给出ksize的大小,将sigmaX和sigmaY都传入0,opendcv会根据公式sigmax=0.3*((ksize-1)*0.5-1)+0.8算出sigmax,而sigmaY=0的意思就是sigmaY的值跟随sigmaX。有兴趣的通许可以算下sigmax和ksize的关系,算出来的结果应该是两者之间的倍数是3到5之间的一个小数,这也就是为什么上文中“卷积核的大小默认定义为3倍或者5倍sigma”的来源。

代码:

int main(int argc,char* argv)
{
    Mat srcm=imread("/home/zht/Desktop/guns.jpg");
    imwrite("/home/zht/Desktop/原图.jpg",srcm);
    Mat dstm;
   // double time0=static_cast(getTickCount());
    blur(srcm,dstm,Size(5,5));
    //cout<<"当卷积核尺寸是5*5时,滤波滤波耗费时间:"<<(static_cast(getTickCount())-time0)/getTickFrequency()<<"s"<(getTickCount());
    GaussianBlur(srcm,dstm,Size(5,5),0,0);
    //cout<<"当卷积核尺寸是5*5时,滤波耗费时间:"<<(static_cast(getTickCount())-time0)/getTickFrequency()<<"s"<
效果:可以看到均值滤波之后要模糊了许多,而高斯滤波还是相对比较清晰的

原图:

opencv3之滤波_第5张图片

均值滤波:
opencv3之滤波_第6张图片
高斯滤波:

opencv3之滤波_第7张图片







你可能感兴趣的:(OPENCV)