高斯函数(Gaussian function)的详细分析

您所在的位置:网站首页 指数方程的公式是什么 高斯函数(Gaussian function)的详细分析

高斯函数(Gaussian function)的详细分析

2024-06-30 02:45| 来源: 网络整理| 查看: 265

摘要

    论文中遇到很重要的一个元素就是高斯核函数,但是必须要分析出高斯函数的各种潜在属性,本文首先参考相关材料给出高斯核函数的基础,然后使用matlab自动保存不同参数下的高斯核函数的变化gif动图,同时分享出源代码,这样也便于后续的论文写作。

高斯函数的基础 2.1 一维高斯函数

高斯函数,Gaussian Function, 也简称为Gaussian,一维形式如下:

对于任意的实数a,b,c,是以著名数学家Carl Friedrich Gauss的名字命名的。高斯的一维图是特征对称“bell curve”形状,a是曲线尖峰的高度,b是尖峰中心的坐标,c称为标准方差,表征的是bell钟状的宽度。

高斯函数广泛应用于统计学领域,用于表述正态分布,在信号处理领域,用于定义高斯滤波器,在图像处理领域,二维高斯核函数常用于高斯模糊Gaussian Blur,在数学领域,主要是用于解决热力方程和扩散方程,以及定义Weiertrass Transform。

从上图可以看出,高斯函数是一个指数函数,其log函数是对数凹二次函数 whose logarithm a concave quadratic function。

高斯函数的积分是误差函数error function,尽管如此,其在整个实线上的反常积分能够被精确的计算出来,使用如下的高斯积分

同理可得

当且仅当

上式积分为1,在这种情况下,高斯是正态分布随机变量的概率密度函数,期望值μ=b,方差delta^2 = c^2,即

 

2.2 二维高斯函数

    二维高斯函数,形如

A是幅值,x。y。是中心点坐标,σx σy是方差,图示如下,A = 1, xo = 0, yo = 0, σx = σy = 1

 

2.3 高斯函数分析

这一节使用matlab直观的查看高斯函数,在实际编程应用中,高斯函数中的参数有

ksize 高斯函数的大小

sigma 高斯函数的方差

center 高斯函数尖峰中心点坐标

bias 高斯函数尖峰中心点的偏移量,用于控制截断高斯函数

为了方便直观的观察高斯函数参数改变而结果也不一样,下面的代码实现了参数的自动递增,并且将所有的结果图保存为gif图像,首先贴出完整代码:

 function mainfunc()   % 测试高斯函数,递增的方法实现高斯函数参数的改变对整个高斯函数的影响,   % 并自动保存为gif格式输出。   % created by zhao.buaa 2016.09.28      %% 保存gif动画   item = 10;      % 迭代次数   dt = 1;             % 步长大小   ksize =20;      % 高斯大小   sigma = 2;      % 方差大小   % filename = ['ksize-' num2str(ksize) '--' num2str(ksize+dt*item) '-sigma-' num2str(sigma) '.gif']; %必须预先建立gif文件   filename = ['ksize-' num2str(ksize)  '-sigma-' num2str(sigma) '--' num2str(sigma+dt*item) '.gif']; %必须预先建立gif文件      % main loop   for i = 1:item       center  = round(ksize/2);          % 中心点       bias       = ksize*10/10;              % 偏移中心点量       ksigma = ksigma(ksize, sigma, center, bias);    % 构建核函数       tname  = ['ksize-' num2str(ksize) '-sigma-' num2str(sigma) '-center-' num2str(center)];       figure(i), mesh(ksigma), title(tname);       %设置固定的x-y-z坐标范围,便于观察,axis([xmin xmax ymin ymax zmin zmax])       axis([0 ksize 0 ksize 0 0.008]);  view([0, 90]);% 改变可视角度          % ksize 递增   %     ksize = ksize + 10;       % sigma 递增       sigma = sigma + dt;                   % 自动保存为gif图像       frame = getframe(i);       im = frame2im(frame);       [I,map] = rgb2ind(im,256);       if i==1           imwrite(I,map,filename,'gif','Loopcount',inf, 'DelayTime',0.4);       else           imwrite(I,map,filename,'gif','WriteMode','append','DelayTime',0.4);       end   end;      close all;         %% 截断高斯核函数,截断的程度取决于参数bias   function ksigma = ksigma(ksize, sigma, center,bias)   %ksize = 80;    sigma = 15;   ksigma=fspecial('gaussian',ksize, sigma);   % 构建高斯函数   [m, n] =size(ksigma);   for i = 1:m       for j = 1:n           if(  (icenter+bias)||(jcenter+bias)  )               ksigma(i,j) = 0;           end;       end;   end;  

结果图:

固定ksize为20,sigma从1-9,固定center在高斯中间,并且bias偏移量为整个半径,即原始高斯函数。

随着sigma的增大,整个高斯函数的尖峰逐渐减小,整体也变的更加平缓,则对图像的平滑效果越来越明显。

保持参数不变,对上述高斯函数进行截断,即truncated gaussian function,bias的大小为ksize*3/10,则结果如下图:

truncated gaussian function的作用主要是对超过一定区域的原始图像信息不再考虑,这就保证在更加合理的利用靠近高斯函数中心点的周围像素,同时还可以改变高斯函数的中心坐标,如下图:

为了便于观察截断的效果,改变了可视角度。

高斯核函数卷积

    论文中使用gaussian与feature map做卷积,目前的结果来看,要做到随着到边界的距离改变高斯函数的截断参数,因为图像的边缘如果使用原始高斯函数,就会在边界地方出现特别低的一圈,原因也很简单,高斯函数在与原始图像进行高斯卷积的时候,图像边缘外为0计算的,那么如何解决边缘问题呢?

先看一段代码:

[plain] view plain copy

% 截断高斯核函数  ksize = 40; ksigma=fspecial('gaussian',  ksize, 6);  [m, n] =size(ksigma);  for i = 1:m      for j = 1:n          if( i

height; ++i)

                               {

                                       for(int m = 0; m < iSize; ++m)

                                             {

                                                         ...

                                             }

                               }

                 这样的算法复杂度为O(2*height*weigth*iSize),比一维处理要少了很多,所以时间对应来说也会快一点。

用后者,我们的关键函数如下:

/* 生成一维高斯模板,水平的和垂直方向上的模板是一样的 输入参数分别是:模板大小,sigma值 输出:一维数组(高斯模板) */ double* CreateMuban(int iSize ,double sigma) {  double *gauss = new double[iSize];//声明一维模板  int radius = (iSize - 1) / 2;//这是高斯半径  double MySigma = 2 * sigma * sigma;  double value = 0;  for (int i = 0; i < iSize; i++)  {//高斯函数前面的常数项因为在归一化的时候将会消去,故这里不重复计算   gauss[i] = exp(-(i - radius)*(i - radius)/MySigma);   value = value + gauss[i];  }  for (int i = 0; i < iSize; i++)  {//归一化   gauss[i] = gauss[i] / value;  }  return gauss; }

//对像素进行操作 IplImage*  operatorImage(IplImage* img, double* Muban, int iSize) {  //创建一张新的图片来进行滤波操作  IplImage* NewImage = cvCreateImage(cvSize(img->width, img->height), 8, 3);  int radius = (iSize - 1) / 2;  int r = 0;  int g = 0;  int b = 0;  CvScalar cs;  //复制图片  cvCopy(img, NewImage);  //先对I,也就是垂直方向进行操作  for (int j = 0; j < NewImage->width; ++j)  {   for (int i = 0; i < NewImage->height; ++i)   {    //先判断是否是边缘,不是则操作,是则跳过不处理,保持原样    if (!JudgeEdge(i, NewImage->height, radius))    {     for (int k = 0; k < iSize; ++k)     {     /* b = b + (int)((double)(NewImage->imageData + (i - radius + k) * NewImage->widthStep)[j * (int)NewImage->nChannels + 0] * Muban[k]);      g = g + (int)((double)(NewImage->imageData + (i - radius + k) * NewImage->widthStep)[j * (int)NewImage->nChannels + 1] * Muban[k]);      r = r + (int)((double)(NewImage->imageData + (i - radius + k) * NewImage->widthStep)[j * (int)NewImage->nChannels + 2] * Muban[k]); */

     cs = cvGet2D(NewImage, i - radius + k, j);   //获取像素        b = b + (int)((double)cs.val[0] * Muban[k]);      g = g + (int)((double)cs.val[1] * Muban[k]);      r = r + (int)((double)cs.val[2] * Muban[k]);

    }     /*((uchar *)(NewImage->imageData + i * NewImage->widthStep))[j * NewImage->nChannels + 0] = b;   //改变该像素B的颜色分量       ((uchar *)(NewImage->imageData + i * NewImage->widthStep))[j * NewImage->nChannels + 1] = g;   //改变该像素G的颜色分量       ((uchar *)(NewImage->imageData + i * NewImage->widthStep))[j * NewImage->nChannels + 2] = r;   //改变该像素R的颜色分量  */     cs = cvGet2D(NewImage, i, j);     cs.val[0] = b;     cs.val[1] = g;     cs.val[2] = r;     cvSet2D(NewImage, i, j, cs);     b = 0;     g = 0;     r = 0;    }   }  }  //在对J,也就是水平方向进行操作  for (int i = 0; i < NewImage->height; ++i)  {   for (int j = 0; j < NewImage->width; ++j)   {    //先判断是否是边缘,不是则操作,是则跳过不处理,保持原样    if (!JudgeEdge(j, NewImage->width, radius))    {     for (int k = 0; k < iSize; ++k)     {      /*b = b + (int)((double)(NewImage->imageData + i * NewImage->widthStep)[(j - radius + k) * (int)NewImage->nChannels + 0] * Muban[k]);      g = g + (int)((double)(NewImage->imageData + i * NewImage->widthStep)[(j - radius + k) * (int)NewImage->nChannels + 1] * Muban[k]);      r = r + (int)((double)(NewImage->imageData + i * NewImage->widthStep)[(j - radius + k) * (int)NewImage->nChannels + 2] * Muban[k]);*/

     cs = cvGet2D(NewImage, i, j - radius + k);   //获取像素        b = b + (int)((double)cs.val[0] * Muban[k]);      g = g + (int)((double)cs.val[1] * Muban[k]);      r = r + (int)((double)cs.val[2] * Muban[k]);

    }     /*((uchar *)(NewImage->imageData + i * NewImage->widthStep))[j * NewImage->nChannels + 0] = b;   //改变该像素B的颜色分量       ((uchar *)(NewImage->imageData + i * NewImage->widthStep))[j * NewImage->nChannels + 1] = g;   //改变该像素G的颜色分量       ((uchar *)(NewImage->imageData + i * NewImage->widthStep))[j * NewImage->nChannels + 2] = r;   //改变该像素R的颜色分量*/          cs = cvGet2D(NewImage, i, j);     cs.val[0] = b;     cs.val[1] = g;     cs.val[2] = r;     cvSet2D(NewImage, i, j, cs);     b = 0;     g = 0;     r = 0;     //cout



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3