高斯模糊(Gaus Blur)采用二维高斯模板对图像进行模糊处理,用于图像模糊化(去除细节和噪声),它的处理效果给人一种更佳柔和的感觉。
一维高斯和二维高斯:
一维高斯:
二维高斯:
基本上,离散化的主旨就是保留高斯函数中心能量最集中的中间部分,忽略四周能量很小的平坦区域。数值分布在(μ—3σ,μ+3σ)中的概率为0.9974。
一、高斯函数五大性质:
(1)二维高斯函数具有旋转对称性,即滤波器在各个方向上的平滑程度是相同的.一般来说,一幅图像的边缘方向是事先不知道的,因此,在滤波前是无法确定一个方向上比另一方向上需要更多的平滑.旋转对称性意味着高斯平滑滤波器在后续边缘检测中不会偏向任一方向.
(2)高斯函数是单值函数.这表明,高斯滤波器用像素邻域的加权均值来代替该点的像素值,而每一邻域像素点权值是随该点与中心点的距离单调增减的.这一性质是很重要的,因为边缘是一种图像局部特征,如果平滑运算对离算子中心很远的像素点仍然有很大作用,则平滑运算会使图像失真.
(3)高斯函数的付立叶变换频谱是单瓣的.正如下面所示,这一性质是高斯函数付立叶变换等于高斯函数本身这一事实的直接推论.图像常被不希望的高频信号所污染(噪声和细纹理).而所希望的图像特征(如边缘),既含有低频分量,又含有高频分量.高斯函数付立叶变换的单瓣意味着平滑图像不会被不需要的高频信号所污染,同时保留了大部分所需信号.
(4)高斯滤波器宽度(决定着平滑程度)是由参数σ表征的,而且σ和平滑程度的关系是非常简单的.σ越大,高斯滤波器的频带就越宽,平滑程度就越好.通过调节平滑程度参数σ,可在图像特征过分模糊(过平滑)与平滑图像中由于噪声和细纹理所引起的过多的不希望突变量(欠平滑)之间取得折衷.
(5)由于高斯函数的可分离性,大高斯滤波器可以得以有效地实现.二维高斯函数卷积可以分两步来进行,首先将图像与一维高斯函数进行卷积,然后将卷积结果与方向垂直的相同一维高斯函数卷积.因此,二维高斯滤波的计算量随滤波模板宽度成线性增长而不是成平方增长.
二、如何计算高斯核函数?
只要知道模板的大小和高斯函数的方差sigma,由二维高斯函数的表达式很容易计算出高斯核,再归一化就可以了。但是由高斯函数的分布特性可知落在u-3*sigma到u+3*sigma的概率大于百分之九九,所以模板大小的选取往往与sigma的取值是相关的。一般,取dim = 1 + 2 * ((int) (3.0 * sigma));opencv和sift中的源码也是这么做的,当然实际中可以其实没有这么严格。
sigma的取值决定了高斯函数窗口的大小。在实际中经常看到sigma取值0.8或者1。正常情况下我们由高斯函数计算得到的模板是浮点型数,即double,但是有些情况我们为了加快计算需要将模板处理成整数,对于常见的3x3或者5x5其整数模板如下:
高斯滤波(高斯平滑)是数字图像处理和计算机视觉里面最常见的操作。平时,我们都是用Matlab或者OpenCV的函数调用:imfilter或者cvSmooth,并不关心底层的实现。然而当开发者要自己实现高斯滤波的时候,往往就会很迷惘,经常会被下面几个问题所困扰:
1、给定sigma,即标准偏差,怎么确定离散化后的滤波器窗口大小?
2、给定窗口大小,怎么计算高斯核的sigma,即标准偏差?
3、怎么实现可分离滤波器?
1、给定sigma,怎么计算窗口大小?给定窗口大小,怎么计算高斯核的sigma,即标准偏差?
先看看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下,用如下公式进行计算(根据其源代码显示,OpenCV里实现,在cvFilter.cpp的init_gaussian_kernel函数中:sigmaX = sigma > 0 ? sigma : (n/2 – 1)*0.3 + 0.8; )。
5)同样的根据这个公式可知,如果param1和param2为0(或者没有给出),那么滤波窗口的尺寸由后两个参数代表的Sigma来确定。一般,取dim = 1 + 2 * ((int) (3.0 * sigma)),大概是3*sigma半径的窗口。
2、怎样实现可分离滤波?
实际上,模板运算(滑动窗口卷积)在数字图像处理中是一项非常耗时的运算。
以上图中的3*3高斯模板为例,每个像素完成一次模板操作要用9个乘法、8个加法和1个除法。对于一幅n*n的图像,大约就是9n2个乘法,8n2个加法和n2个除法,这对于比较大的图像来说,是非常可怕的。而且随着模板大小的增加,计算量是呈指数增长的。那么有没有一种办法能够减少计算量呢?答案是肯定的。由于高斯函数可以写成可分离的形式,因此可以采用可分离滤波器实现来加速。所谓的可分离滤波器,就是可以把一个多维的卷积化成多个一维的卷积。具体到二维的高斯滤波,就是指先对行做一维卷积,再对列做一维卷积。这样就可以将计算复杂度从O(M*M*N*N)降到O(2*M*M*N),M, N分别是图像和滤波器的窗口大小。问题是实现的时候怎么计算一维的卷积核呢?
其实很简单,按照前面计算出来的窗口大小,将二维的高斯模板合并成一维,计算所有离散点上一维高斯函数的权值,最后将权值之和归一化到1。
于是在高斯滤波器的设计中,二维高斯函数的卷积运算可以通过使用单个一维高斯模板,对两次卷积之间的图像和最后卷积的结果图像进行转置来完成。
c语言代码实现如下:(参考http://blog.csdn.net/crzy_sparrow/article/details/6998745)
产生一维高斯模板的函数: