高斯滤波

高斯滤波核函数满足如下分布:

一维核函数:

二维核函数:

通过核函数可以计算K*K的高斯平滑模板:(貌似opencv 和matlab 中都有封装好的函数)

sigma需要自己设定,根据生成的模板大小,x和y表示当前元素距模板中心的距离。可以由opencv直接调用求模板,也可以分别通过一维/二维自己代码求模板。【注意,一维滤波的时候需要对x和y方向分别滤波】

//通用变量定义
double nSigma = 0.4;                            //定义高斯函数的标准差  
int nWidowSize = 1+2*ceil(3*nSigma);            //定义滤波窗口的大小  
int nCenter = (nWidowSize)/2;                   //定义滤波窗口中心的索引  
double nSigma = 0.4;                            //定义高斯函数的标准差  
int nWidowSize = 1+2*ceil(3*nSigma);            //定义滤波窗口的大小  
int nCenter = (nWidowSize)/2;                   //定义滤波窗口中心的索引  
//////////////////////生成一维高斯滤波系数,高斯模板也可以是非对称的/////////////////////////////  
double* pdKernal_1 = new double[nWidowSize];    //定义一维高斯核数组  
double  dSum_1 = 0.0;                           //求和,用于进行归一化          
////////////////////////一维高斯函数公式//////////////////////////////       
////                   x*x                           /////////////////  
////          -1*----------------                    /////////////////  
////         1     2*Sigma*Sigma                     /////////////////  
////   ------------ e                                /////////////////  
////                                                 /////////////////  
////   \/2*pi*Sigma                                  /////////////////  
//////////////////////////////////////////////////////////////////////  
for(int i=0; i<nWidowSize; i++)  
{  
        double nDis = (double)(i-nCenter);  
    pdKernal_1[i] = exp(-(0.5)*nDis*nDis/(nSigma*nSigma))/(sqrt(2*3.14159)*nSigma);  
    dSum_1 += pdKernal_1[i];  
}  
for(i=0; i<nWidowSize; i++)  
{  
    pdKernal_1[i] /= dSum_1;                 //进行归一化  
}  
//////////////////////生成二维高斯滤波系数//////////////////////////////////    
double* pdKernal_2 = new double[nWidowSize*nWidowSize]; //定义一维高斯核数组  
double  dSum_2 = 0.0;                                   //求和,进行归一化        
///////////////////////二维高斯函数公式////////////////////////////////////      
////                         x*x+y*y                        ///////////////  
////                   -1*--------------                ///////////////  
////         1             2*Sigma*Sigma                ///////////////  
////   ---------------- e                                   ///////////////  
////   2*pi*Sigma*Sigma                                     ///////////////  
///////////////////////////////////////////////////////////////////////////  
for(i=0; i<nWidowSize; i++)  
{  
    for(int j=0; j<nWidowSize; j++)  
    {  
        int nDis_x = i-nCenter;  
        int nDis_y = j-nCenter;  
        pdKernal_2[i+j*nWidowSize]=exp(-(1/2)*(nDis_x*nDis_x+nDis_y*nDis_y)  
            /(nSigma*nSigma))/(2*3.1415926*nSigma*nSigma);  
        dSum_2 += pdKernal_2[i+j*nWidowSize];  
    }  
}  
for(i=0; i<nWidowSize; i++)  
{  
    for(int j=0; j<nWidowSize; j++)                 //进行归一化  
        {  
        pdKernal_2[i+j*nWidowSize] /= dSum_2;  
    }  
}  

========================================================

高斯平滑:

//一维核函数生成的模板平滑
for(i=0; i<nHeight; i++)                               //进行x向的高斯滤波(加权平均)  
{  
    for(j=0; j<nWidth; j++)  
    {  
        double dSum = 0;  
        double dFilter=0;                                       //滤波中间值  
        for(int nLimit=(-nCenter); nLimit<=nCenter; nLimit++)  
        {  
            if((j+nLimit)>=0 && (j+nLimit) < nWidth )       //图像不能超出边界  
            {  
                dFilter += (double)nImageData[i*nWidth+j+nLimit] * pdKernal_1[nCenter+nLimit];  
                dSum += pdKernal_1[nCenter+nLimit];  
            }  
        }  
        nData[i*nWidth+j] = dFilter/dSum;  
    }  
}  
  
for(i=0; i<nWidth; i++)                                //进行y向的高斯滤波(加权平均)  
{  
    for(j=0; j<nHeight; j++)  
    {  
        double dSum = 0.0;  
        double dFilter=0;  
        for(int nLimit=(-nCenter); nLimit<=nCenter; nLimit++)  
        {  
            if((j+nLimit)>=0 && (j+nLimit) < nHeight)       //图像不能超出边界  
            {  
                dFilter += (double)nData[(j+nLimit)*nWidth+i] * pdKernal_1[nCenter+nLimit];  
                dSum += pdKernal_1[nCenter+nLimit];  
            }  
        }  
        pCanny[j*nWidth+i] = (unsigned char)(int)dFilter/dSum;  
    }  
}  
//二维核函数平滑
int x;  
int y;  
for(i=0; i<nHeight; i++)  
{  
    for(j=0; j<nWidth; j++)  
    {  
        double dFilter=0.0;  
        double dSum = 0.0;  
        for(x=(-nCenter); x<=nCenter; x++)                     //
        {  
                        for(y=(-nCenter); y<=nCenter; y++)             //
            {  
                if( (j+x)>=0 && (j+x)<nWidth && (i+y)>=0 && (i+y)<nHeight) //判断边缘  
                {  
                    dFilter += (double)nImageData [(i+y)*nWidth + (j+x)]  
                        * pdKernal_2[(y+nCenter)*nWidowSize+(x+nCenter)];  
                    dSum += pdKernal_2[(y+nCenter)*nWidowSize+(x+nCenter)];  
                }  
            }  
        }  
        pCanny[i*nWidth+j] = (unsigned char)dFilter/dSum;  
    }  
}  

在选择Sigma时要注意,如果选的过大,那么会加深滤波程度,这样会导致图像边缘模糊,不利于下一步的边缘检测,如果过小,则滤波效果不佳,

 

参考:

http://blog.csdn.net/likezhaobin/article/details/6892176(整个canny总览)

http://blog.csdn.net/likezhaobin/article/details/6892629(整个canny算法步骤的细致讲解+代码)

http://blog.csdn.net/xiaojiegege123456/article/details/7714897

http://blog.csdn.net/likezhaobin/article/details/6835049(对opencv参数和sigma的讲解)

 

posted @ 2015-05-21 15:24  Daringoo  阅读(900)  评论(0编辑  收藏  举报