关于高斯滤波的一些理解

59 篇文章 3 订阅
13 篇文章 2 订阅

问:高斯滤波可以使图像边缘不明显,可以将不明显的边缘模糊。
(1)但为什么不直接提高边缘检测算法参数中的阈值,而要先用高斯滤波来减少?
(2)高斯滤波和边缘检测都是像素卷积计算出来的,为什么不直接将两个合并到一起?
答:边缘检测的算法有很多种,这些算法通常容受图像本身的一些噪声干扰,尤其当用偏微分方程获取图像边缘时候,如果边缘不连续,甚至导致函数水平集无法停止收敛。比如,几何活动轮廓模型,高斯滤波通过平滑,可以去除噪声等干扰,从而提高边缘检测的精准度。

     滤波算法简介

         本文主要介绍了高斯滤波器的原理及其实现过程

         高斯滤波器是一种线性滤波器,能够有效的抑制噪声,平滑图像。其作用原理和均值滤波器类似,都是取滤波器窗口内的像素的均值作为输出。其窗口模板的系数和均值滤波器不同,均值滤波器的模板系数都是相同的为1;而高斯滤波器的模板系数,则随着距离模板中心的增大而系数减小。所以,高斯滤波器相比于均值滤波器对图像的模糊程度较小。

         图像处理中,常用的滤波算法有均值滤波、中值滤波以及高斯滤波等。均值滤波使用模板内所有像素的平均值代替模板中心像素灰度值,这种方法易收到噪声的干扰,不能完全消除噪声,只能相对减弱噪声;中值滤波计算模板内所有像素中的中值,并用所计算出来的中值体改模板中心像素的灰度值,这种方法对噪声不是那么敏感,能够较好的消除椒盐噪声,但是容易导致图像的不连续性。高斯滤波对图像邻域内像素进行平滑时,邻域内不同位置的像素被赋予不同的权值,对图像进行平滑的同时,同时能够更多的保留图像的总体灰度分布特征。

     高斯滤波

        数值图像处理中,高斯滤波主要可以使用两种方法实现。一种是离散化窗口滑窗卷积,另一种方法是通过傅里叶变化。在这我主要想说说第一种方法的高斯滤波。离散化窗口滑窗卷积的时,主要利用的是高斯核,高斯核一般是一个奇数的大小的高斯模板。常用的高斯模板有如下几种形式:

       上图所示是常用的两种高斯模板, 左侧是常用的33的高斯模板,右侧是常用的55高斯模板。那么,上述高斯模板中的参数是怎么得到的呢?这是我第一次接触高斯滤波时,一直不太明白的问题。经过一段时间的学习,查阅资料。才渐渐明白高斯模板中的参数是如何得到的!

       高斯模板中的参数是通过高斯函数计算出来的。计算高斯模板参数时,通过如下公式:

    x的平方和y的平方分别表示的是邻域内其他像素与邻域内中心像素的距离,Sigmma代表的是标准差。


      如上图所示由二维高斯图像可知,标准差越小,二维高斯图像越窄小,平滑效果不明显;标准差越大,而为高斯图像越矮宽,滤波效果比较明显。

      要想得到一个高斯滤波器的模板,可以对高斯函数进行离散化,得到的高斯函数值作为模板的系数。例如:要产生一个3×3的高斯滤波器模板,以模板的中心位置为坐标原点进行取样。模板在各个位置的坐标(x轴水平向右,y轴竖直向下)如下:

这样,将各个位置的坐标带入到高斯函数中,得到的值就是模板的系数。
对于窗口模板的大小为 (2k+1)×(2k+1),模板中各个元素值的计算公式如下:
在这里插入图片描述

这样计算出来的模板有两种形式:小数和整数。

小数形式的模板,就是直接计算得到的值,没有经过任何的处理;
整数形式的,则需要进行归一化处理,将模板左上角的值归一化为1,下面会具体介绍。使用整数的模板时,需要在模板的前面加一个系数,系数为 1/∑w(i,j),也就是模板系数和的倒数。

主要代码如下

double weight;
double sum = 0;
double Sigmma = 1;

double Gaussian_Temp[SIZE][SIZE] = {0};
int i,j;

weight = 2*PI*Sigmma*Sigmma;
for(i =0;i <SIZE;i++)
{
	for(j = 0;j < SIZE;j++)
	{
		Gaussian_Temp[i][j] =exp(-((i-SIZE/2)*(i-SIZE/2)+(j-SIZE/2)*(j-SIZE/2))/(2.0*Sigmma*Sigmma));
		sum += Gaussian_Temp[i][j];
	}
}

for(i = 0; i < SIZE;i++)
{
		for(j = 0;j < SIZE;j++)
	{
		Gaussian_Temp[i][j] = Gaussian_Temp[i][j]/sum;//归一化处理
		printf("%f ",Gaussian_Temp[i][j]);
	}
		printf("\n");
}

代码2:

void generateGaussianTemplate(double window[][11], int ksize, double sigma)
{
    static const double pi = 3.1415926;
    int center = ksize / 2; // 模板的中心位置,也就是坐标的原点
    double x2, y2;
    for (int i = 0; i < ksize; i++)
    {
        x2 = pow(i - center, 2);
        for (int j = 0; j < ksize; j++)
        {
            y2 = pow(j - center, 2);
            double g = exp(-(x2 + y2) / (2 * sigma * sigma));
            g /= 2 * pi * sigma;
            window[i][j] = g;
        }
    }
    double k = 1 / window[0][0]; // 将左上角的系数归一化为1
    for (int i = 0; i < ksize; i++)
    {
        for (int j = 0; j < ksize; j++)
        {
            window[i][j] *= k;
        }
    }
}

代码3:至于小数形式的生成也比较简单,去掉归一化的过程,并且在求解过程后,模板的每个系数要除以所有系数的和。具体代码如下:

void generateGaussianTemplate(double window[][11], int ksize, double sigma)
{
    static const double pi = 3.1415926;
    int center = ksize / 2; // 模板的中心位置,也就是坐标的原点
    double x2, y2;
    double sum = 0;
    for (int i = 0; i < ksize; i++)
    {
        x2 = pow(i - center, 2);
        for (int j = 0; j < ksize; j++)
        {
            y2 = pow(j - center, 2);
            double g = exp(-(x2 + y2) / (2 * sigma * sigma));
            g /= 2 * pi * sigma;
            sum += g;
            window[i][j] = g;
        }
    }
    //double k = 1 / window[0][0]; // 将左上角的系数归一化为1
    for (int i = 0; i < ksize; i++)
    {
        for (int j = 0; j < ksize; j++)
        {
            window[i][j] /= sum;
        }
    }
}


需要一个二维数组,存放生成的系数(这里假设模板的最大尺寸不会超过11);第二个参数是模板的大小(不要超过11);第三个参数就比较重要了,是高斯分布的标准差。生成的过程,首先根据模板的大小,找到模板的中心位置ksize/2。 然后就是遍历,根据高斯分布的函数,计算模板中每个系数的值。
需要注意的是,最后归一化的过程,使用模板左上角的系数的倒数作为归一化的系数(左上角的系数值被归一化为1),模板中的每个系数都乘以该值(左上角系数的倒数),然后将得到的值取整,就得到了整数型的高斯滤波器模板。

以55高斯模板为例,计算出来的高斯模板值为:

        计算出来的结果与上图55的高斯模板有一定差异,为什么会不一样呢?查阅资料,解释到:高斯模板实际上也就是模拟高斯函数的特征,具有对称性并且数值由中心向四周不断减小,上述图像中的55这个模板刚好符合这样的特性,并且非常简单,容易被大家接受,于是就比较经典。也就是说上述图像中55的高斯模板只是对二维高斯函数理论上计算出来的值的一种近似处理,如何从理论上的计算出来的值得到图片中5*5的高斯模板呢?我是这么理解高斯模板中各个参数得由来,如何从理论值得到高斯模板中的值还不太清楚!!

     

σ 值的意义及选取
通过上述的实现过程,不难发现,高斯滤波器模板的生成最重要的参数就是高斯分布的标准差σ。标准差代表着数据的离散程度,如果σ较小,那么生成的模板的中心系数较大,而周围的系数较小,这样对图像的平滑效果就不是很明显;反之,σ较大,则生成的模板的各个系数相差就不是很大,比较类似均值模板,对图像的平滑效果比较明显。

横轴表示可能得取值x,竖轴表示概率分布密度F(x),那么不难理解这样一个曲线与x轴围成的图形面积为1。σ(标准差)决定了这个图形的宽度,可以得出这样的结论:σ越大,则图形越宽,尖峰越小,图形较为平缓;σ越小,则图形越窄,越集中,中间部分也就越尖,图形变化比较剧烈。 这其实很好理解,如果sigma也就是标准差越大,则表示该密度分布一定比较分散,由于面积为1,于是尖峰部分减小,宽度越宽(分布越分散);同理,当σ越小时,说明密度分布较为集中,于是尖峰越尖,宽度越窄!
于是可以得到如下结论:
σ越大,分布越分散,各部分比重差别不大,于是生成的模板各元素值差别不大,类似于平均模板;
σ越小,分布越集中,中间部分所占比重远远高于其他部分,反映到高斯模板上就是中心元素值远远大于其他元素值,于是自然而然就相当于中间值得点运算。

此外,计算高斯模板参数时,需要归一化处理,为什么需要进行归一化处理呢?我的理解如下:

      这是一维高斯函数概率密度函数图像。横轴表示可能得取值x,竖轴表示概率分布密度F(x),由高斯概率密度函数可知,那么不难理解这样一个曲线与x轴围成的图形面积为1。在实际应用中,在计算离散近似的时候,在大概3σ距离之外的像素都可以看作不起作用,这些像素的计算也就可以忽略。也就是说,为了尽可能的模拟高斯函数的相关性质,计算高斯模板的时候,计算出来的高斯模板中各个数值其和必须为1,这也就是为什么需要进行归一化的原因。

    高斯函数计算出来的模板之所以归一化,另外一种解释是:归一化之后,通过卷积计算出来的模板中心像素被限制到了0-255的灰度区间中。假若某一邻域内所有像素的灰度值为255,利用该模板进行卷积之后,求得的模板中心像素灰度值仍然为255;假若计算出来的高斯模板参数之和小于1,那么通过该模板进行卷积之后,模板中心像素的灰度值将小于255,偏离了实际的灰度值,产生了误差。

参考文献:

http://lps-683.iteye.com/blog/2251180
图像处理基础(4):高斯滤波器详解





 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值