高斯滤波是图像平滑的一种重要的方式,能有效地消除和抑制噪声,达到图像平滑的效果。同时,相比于平均模板而言,效果更加自然。更加自然的意思,实际上说相对于就是适当地降低平滑后的模糊程度。平均模板对四周像素的使用是一视同仁的,这样的话整幅图处理后看上去就会非常的模糊;然而高斯滤波打破了这样的局限,分配以不同的权重,随着距离中心距离的增大,权重将迅速减小,从而确保中心的像素点看起来更像是接近与它更近的像素点,这样图像的连续性得到了保证!
那么问题来了,什么是高斯滤波?
首先,它引入了数学中的高斯函数(正态分布函数)(对于平面图像来说,往往用到的是二维函数)
(式1-1)
高斯滤波的思路就是:对高斯函数进行离散化,以离散点上的高斯函数值为权值,对我们采集到的灰度矩阵的每个像素点做一定范围邻域内的加权平均,即可有效消除高斯噪声。
离散的高斯卷积核H: (2k+1)×(2k+1)维,其元素计算方法为:
其中Sigma为方差,k确定核矩阵的维数。
通过上述公式,我们可以方便地求出高斯模板,从而进行编程滤波处理。这里不得不提高斯滤波有两种实现方式,其一是离散化窗口滑窗卷积,另一种则是通过傅里叶变化实现。本文只介绍前者,实际上前者运用也是最多的。那什么叫离散化窗口滑窗处理呢?我们把这个方法分成四个关键词:“离散化”“窗口”“滑窗”“卷积”,接下来一一解释这些名词:
“离散化”:上文中已经提到了离散的高斯卷积核(式1-2),实际上就是将高斯函数进行离散化,方便程序计算高斯模板;
“窗口”:这个窗口比喻得很形象,实际上我的理解就是M*N维的高斯模板;
“滑窗”:有了这个高斯模板,接下来是结合我们待处理的灰度数据,处理一个接着一个的像素点,比如说处理完(1,1)这个点之后,接下来要处理(1,2)这个数据点,那么模板相当于右移了一个像素点,那么我们可以把这个过程形象地看作是滑窗。在碰上待处理图像的边缘时,往往处理不了,此时要进行特殊处理,比如说在检测到边缘时,复制原来的灰度数据,即不处理;
“卷积”:在高数里有过这个概念,然而在这个地方,卷积远远没有书上的那么复杂,实际上就是待处理图像的各像素灰度数据与模板对应元素的数值的加权和的运算过程,就称之为卷积。
有了以上解释之后,我们可以把“离散化”和“窗口”看成是第一个步骤,可以称之为预处理,通过对高斯函数离散化得到的函数来编程得到你所需要的高斯模板,也就是窗口;把“滑窗”和“卷积”看作是第二个步骤,可以称之为处理过程,通过“滑窗”的方式来进行“卷积”过程。
上述两个过程在下一次笔记中我将详细论述。本文重点介绍openCV自带的高斯函数的运用。
void cvSmooth(const CvArr* src, CvArr* dst,
int smoothtype=CV_GAUSSIAN,
int param1=3, int param2=0,double param3=0, double param4=0 );
1
) 如果指定param1和param2,则代表核函数的行列,即为滤波窗口的宽度和高度;2) Param3:高斯卷积的Sigma值
3) 如果用户希望采用非对称的高斯核,则引入param4,最后两个参数分别代表水平核以及垂直核维数;
4) 如果param3没有给出,则有前两个参数param1和param2计算出Sigma。这里的根据是高斯分布的特点(如图所示,数值分布在(μ—3σ,μ+3σ)中的概率为0.9974),如果核矩阵更大,那么相应的Sigma也更大,相反,如果Sigma更大,那么核矩阵覆盖范围也更大。具体到OpenCv下,用如下公式进行计算(根据其源代码显示)。
处理代码如下:
#include<iostream>
#include"cv.h"
#include"highgui.h"
#include"cxcore.h"
using namespace std;
int main()
{
//载入一张待处理的图片
IplImage* img = cvLoadImage("10.png");
//创建一张自定义大小的图像,从而调整载入图像的大小
IplImage* myimg = cvCreateImage(cvSize(400,400),8,3);
//彩色图像转变灰度图像
IplImage* lastimg = cvCreateImage(cvSize(400, 400), 8, 1);
//*********************************************
//创建输出图像
IplImage* dst = cvCreateImage(cvSize(myimg->width,myimg->height),8,1);
//重新调整图像大小
cvResize(img, myimg);
//RGB图像转换成灰度图像
cvCvtColor(myimg, lastimg,CV_BGR2GRAY);
cvNamedWindow("scr");
cvNamedWindow("Guase Filter");
//用3*3的高斯模板,sigma=2进行高斯滤波
cvSmooth(lastimg,dst, CV_GAUSSIAN,3,3,2);
cvShowImage("scr", lastimg);
cvShowImage("Guase Filter", dst);
cvWaitKey(50000);
system("pause");
cvReleaseImage(&img);
cvReleaseImage(&dst);
cvReleaseImage(&myimg);
cvReleaseImage(&lastimg);
cvDestroyAllWindows();
return 0;
}
1.对彩色图像的处理
2.对灰度图像的处理
3.sigma不同的比较
先来看不同sigma取值时输出图像的不同效果:
(1)sigma=0.1
(2)sigma=0.5
(3)sigma=0.8
以上几组数据的比较,请读者仔细观察(一定要仔细观察,一开始粗略地看是看不出来很明显的差别,具体原因是素材的选择问题,抱歉),可以发现,当sigma=0.1时,实际上和原图效果并无很大差别,而反观sigma=2时,较原图来说,开始有些模糊的效果。实际上,仔细想想并不难理解,sigma表示的是标准差,如果标准差比较小,这是就相当于图像点运算,则平滑效果不明显;反之,标准差比较大,则相当于平均模板,比较模糊。故一般情况下3*3模板选择0.8标准差即可(该部分后面还会进一步阐述比较说明)。