快速高斯滤波

高斯滤波器是图像处理中经常用到的滤波器,其滤波核函数为:

为简单起见,这里省略了归一化因子。

的可分离特性:

得:

其中为输入图像,为输出图像,为滤波模板半径。根据准则,通常使

由上式可见,我们可以将二维高斯滤波分解为两次一维高斯滤波。

对于二维高斯滤波,设图像大小,高斯模板大小,处理每个像素点需要次操作,则算法复杂度。若使用一维高斯核先对图像逐行滤波,再对中间结果逐列滤波,则处理每个像素需要次操作,算法复杂度,随着滤波模板尺寸的增大,算法优势越明显。

程序:

#include "stdafx.h"
#include<stdlib.h>
#include<math.h>
//边界处理
int Edge(int i,int x,int Max)
{
    int k=i+x;
    if(k<0)k=-i;
    else if(k>=Max) k=Max-i-1;
    else k=x;
    return k;
}

//二维高斯处理灰度图像
extern "C" _declspec(dllexport) void GaussFilterGray(unsigned char *A, int nWidth, int nHeight, int Stride,double dSigma)
{
    unsigned char *buffer=(unsigned char*)malloc(Stride*nHeight);
    memcpy(buffer,A,Stride*nHeight);
    int nWindowSize = (int)(1+2*ceil(3*dSigma));
    int nCenter = (nWindowSize)/2;
    double* pdKernel = new double[nWindowSize*nWindowSize];
    double  dSum = 0.0;
    double scale2X = 0.5/(dSigma*dSigma);
    double dFilter=0.0;
    double ImageData=0.0;
    //生成二维高斯滤波核
    for(int i=0; i<nWindowSize; i++)
    {
        for(int j=0; j<nWindowSize; j++)
        {
            int nDis_x = i-nCenter;
            int nDis_y = j-nCenter;
            pdKernel[j+i*nWindowSize]=exp(-(nDis_x*nDis_x+nDis_y*nDis_y)*scale2X);
            dSum += pdKernel[i*nWindowSize+j];
        }
    }
    //归一化
    for(int i=0; i<nWindowSize; i++)
    {
        for(int j=0; j<nWindowSize; j++)
        {
            pdKernel[i*nWindowSize+j] /= dSum;
        }
    }
    //逐像素处理
    for(int inx=0,i=0; i<nHeight; i++)
    {
        for(int j=0; j<nWidth; j++,inx++)
        {
            dFilter=0;
            //邻域内加权平均
            for(int n=0,x=-nCenter; x<=nCenter; x++)
            {
                int i_x=Edge(i,x,nHeight);
                for(int y=-nCenter; y<=nCenter; y++,n++)
                {
                    int j_y=Edge(j,y,nWidth);
                    int index=(i+i_x)*Stride+j+j_y;//邻域内像素在内存中的下标
                    ImageData=buffer[index];
                    dFilter+=ImageData*pdKernel[n];
                }
            }
            A[inx]= max(min(255,dFilter),0);
        }
    }
    delete[]pdKernel;
    delete[]buffer;
}

//一维高斯处理灰度图像
extern "C" _declspec(dllexport) void GaussFilterGray1D(unsigned char *A, int nWidth, int nHeight, int Stride,double dSigma)
{
    unsigned char *buffer=(unsigned char*)malloc(Stride*nHeight);
    memcpy(buffer,A,Stride*nHeight);
    int nWindowSize = (int)(1+2*ceil(3*dSigma));
    int nCenter = (nWindowSize)/2;
    double* pdKernel = new double[nWindowSize];
    double  dSum = 0.0;
    double scale2X = 0.5/(dSigma*dSigma);
    double dFilter=0.0;
    double ImageData=0.0;
    //生成一维高斯核
    for(int i=0; i<nWindowSize; i++)
    {
        int nDis_x = i-nCenter;
        pdKernel[i]=exp(-(nDis_x*nDis_x)*scale2X);
        dSum += pdKernel[i];
    }
    //归一化
    for(int i=0; i<nWindowSize; i++)
    {
        pdKernel[i] /= dSum;
    }
    //横向滤波
    for(int inx=0,i=0; i<nHeight; i++)
    {
        for(int j=0; j<nWidth; j++,inx++)
        {
            dFilter=0;
            for(int n=0,x=-nCenter; x<=nCenter; x++,n++)
            {
                int j_x=Edge(j,x,nWidth);
                int index=inx+j_x;
                ImageData=A[index];//从原图像A中取值
                dFilter+=ImageData*pdKernel[n];
            }
            buffer[inx]= max(min(255,dFilter),0);//中间结果放在buffer中
        }
    }

    //纵向滤波
    for(int i=0;i<nWidth;i++)
    {
        for(int j=0;j<nHeight;j++)
        {
            dFilter=0;
            for(int n=0,x=-nCenter; x<=nCenter; x++,n++)
            {
                int j_x=Edge(j,x,nHeight);
                int index=(j+j_x)*Stride+i;
                ImageData=buffer[index];//从中间图像buffer中取值
                dFilter+=ImageData*pdKernel[n];
            }
            A[j*Stride+i]= max(min(255,dFilter),0);
        }
    }
    delete[]pdKernel;
    delete[]buffer;
}

//二维高斯处理彩色图像
extern "C" _declspec(dllexport) void GaussFilterColor(unsigned char *A, int nWidth, int nHeight, int Stride,double dSigma)
{
    int Step=3;
    if(Stride==4*nWidth)Step=4;//四通道图像
    unsigned char *buffer=(unsigned char*)malloc(Stride*nHeight);
    memcpy(buffer,A,Stride*nHeight);
    int nWindowSize = (int)(1+2*ceil(3*dSigma));
    int nCenter = (nWindowSize)/2;
    double* pdKernel = new double[nWindowSize*nWindowSize];
    double  dSum = 0.0;
    double scale2X = 0.5/(dSigma*dSigma);
    double dFilterB=0.0;
    double dFilterG=0.0;
    double dFilterR=0.0;
    int index;
    double ImageData;
    //生成二维高斯滤波核
    for(int i=0; i<nWindowSize; i++)
    {
        for(int j=0; j<nWindowSize; j++)
        {
            int nDis_x = i-nCenter;
            int nDis_y = j-nCenter;
            pdKernel[j+i*nWindowSize]=exp(-(nDis_x*nDis_x+nDis_y*nDis_y)*scale2X);
            dSum += pdKernel[i*nWindowSize+j];
        }
    }
    //归一化
    for(int i=0; i<nWindowSize; i++)
    {
        for(int j=0; j<nWindowSize; j++)
        {
            pdKernel[i*nWindowSize+j] /= dSum;
        }
    }
    for(int i=0; i<nHeight; i++)
    {
        for(int j=0; j<nWidth;j++)
        {
            dFilterB=0;
            dFilterG=0;
            dFilterR=0;
            for(int n=0,x=-nCenter; x<=nCenter; x++)
            {
                int i_x=Edge(i,x,nHeight);
                for(int y=-nCenter; y<=nCenter; y++,n++)
                {
                    int j_y=Edge(j,y,nWidth);
                    index=(i+i_x)*Stride+(j+j_y)*Step;
                    //三通道BGR,四通道BGRA
                    ImageData=buffer[index];
                    dFilterB+=ImageData * pdKernel[n];
                    index+=1;
                    ImageData=buffer[index];
                    dFilterG+=ImageData * pdKernel[n];
                    index+=1;
                    ImageData=buffer[index];
                    dFilterR+=ImageData * pdKernel[n];
                }
            }
            index=i*Stride+j*Step;
            A[index]=max(min(dFilterB,255),0);
            A[index+1]=max(min(dFilterG,255),0);
            A[index+2]=max(min(dFilterR,255),0);
        }
    }
    delete[]pdKernel;
    delete[]buffer;
}

//一维高斯处理彩色图像
extern "C" _declspec(dllexport) void GaussFilterColor1D(unsigned char *A, int nWidth, int nHeight, int Stride,double dSigma)
{
    int Step=3;
    if(Stride==4*nWidth)Step=4;//四通道图像
    unsigned char *buffer=(unsigned char*)malloc(Stride*nHeight);
    memcpy(buffer,A,Stride*nHeight);
    int nWindowSize = (int)(1+2*ceil(3*dSigma));
    int nCenter = (nWindowSize)/2;
    double* pdKernel = new double[nWindowSize];
    double scale2X = 0.5/(dSigma*dSigma);
    double  dSum = 0.0;
    double dFilterB=0;
    double dFilterG=0;
    double dFilterR=0;
    double ImageData;
    int index;
    //一维高斯核
    for(int i=0; i<nWindowSize; i++)
    {
        int nDis_x = i-nCenter;
        pdKernel[i]=exp(-(nDis_x*nDis_x)*scale2X);
        dSum += pdKernel[i];
    }
    //归一化
    for(int i=0; i<nWindowSize; i++)
    {
        pdKernel[i] /= dSum;
    }
    //横向滤波
    for(int i=0; i<nHeight; i++)
    {
        for(int j=0; j<nWidth;j++)
        {
            dFilterB=0;
            dFilterG=0;
            dFilterR=0;
            for(int n=0,x=-nCenter; x<=nCenter; x++,n++)
            {
                int j_x=Edge(j,x,nWidth);
                index=i*Stride+(j+j_x)*Step;
                ImageData=A[index];//从原图像A中取值
                dFilterB+=ImageData * pdKernel[n];
                index+=1;
                ImageData=A[index];
                dFilterG+=ImageData * pdKernel[n];
                index+=1;
                ImageData=A[index];
                dFilterR+=ImageData * pdKernel[n];
             }
            index=i*Stride+j*Step;
            buffer[index]=max(min(dFilterB,255),0);//中间结果放在buffer中
            buffer[index+1]=max(min(dFilterG,255),0);
            buffer[index+2]=max(min(dFilterR,255),0);
        }
    }  

    //纵向滤波
    for(int i=0;i<nWidth;i++)
    {
        for(int j=0;j<nHeight;j++)
        {
            dFilterB=0;
            dFilterG=0;
            dFilterR=0;
            for(int n=0,x=-nCenter; x<=nCenter; x++,n++)
            {
                int j_x=Edge(j,x,nHeight);
                int index=(j+j_x)*Stride+i*Step;
                ImageData=buffer[index];//从中间图像buffer中取值
                dFilterB+=ImageData * pdKernel[n];
                index+=1;
                ImageData=buffer[index];
                dFilterG+=ImageData * pdKernel[n];
                index+=1;
                ImageData=buffer[index];
                dFilterR+=ImageData * pdKernel[n];
            }
            index=j*Stride+i*Step;
            A[index]=max(min(dFilterB,255),0);
            A[index+1]=max(min(dFilterG,255),0);
            A[index+2]=max(min(dFilterR,255),0);
        }
    }
    delete[]pdKernel;
    delete[]buffer;
}

演示结果:

上面对一幅512*512的彩色图像,基本的高斯算法耗时1469ms,而快速高斯耗时439ms。选取的,此时的滤波模板大小为

完整的工程项目下载:快速高斯滤波

参考:

http://blog.csdn.net/markl22222/article/details/10313565

http://m.blog.csdn.net/blog/zxpddfg/45912561

时间: 2024-11-05 05:07:03

快速高斯滤波的相关文章

快速高斯滤波函数[修正完善版]

原文地址:http://blog.csdn.net/markl22222/article/details/10313565 进行了修正和变量优化.原来作者的函数只支持2次方图片,这次修正了(windows的bitmap行宽是4字节对齐的). 基本完善了,但是在某些条件下,Y方向的底边还是会出现偏差,一时找不到原因,暂且发表,希望有人能提醒一下. 函数结构我规整了一下,很清晰,很好阅读. int gauss_blur( byte_t* image, //位图数据 int linebytes, //

【3.15】matlab 高斯滤波,快速滤波

Gauss滤波快速实现方法(转) 二维高斯函数具有旋转对称性,处理后不会对哪一个方向上的边缘进行了过多的滤波,因此相对其他滤波器,具有无法比拟的优越性.但是传统Gauss滤波随着图像尺寸的增加,运算复杂度呈平方上涨,因此需要对其优化改进.下面,分别介绍传统型,分解型和递归迭代型三种实现方法. 1 传统型 Gauss滤波首先需要构建一个Gauss滤波核,公式为: Matlab实现代码: dSigma =0.8; fK1=1.0/(2*dSigma*dSigma); fK2=fK1/pi; iSiz

学习 opencv---(7) 线性邻域滤波专场:方框滤波,均值滤波,高斯滤波

本篇文章中,我们一起仔细探讨了OpenCV图像处理技术中比较热门的图像滤波操作.图像滤波系列文章浅墨准备花两次更新的时间来讲,此为上篇,为大家剖析了"方框滤波","均值滤波","高斯滤波"三种常见的邻域滤波操作.而作为非线性滤波的"中值滤波"和"双边滤波",我们下次再分析. 因为文章很长,如果详细啃的话,或许会消化不良.在这里给大家一个指引,如果是单单想要掌握这篇文章中讲解的OpenCV线性滤波相关的三个函

SIFT四部曲之——高斯滤波

本文为原创作品,未经本人同意,禁止转载 欢迎关注我的博客:http://blog.csdn.net/hit2015spring和http://www.cnblogs.com/xujianqing/ 或许网络上有各位牛人已经对sift算法进行各种的详解和说明,我(小菜鸟)在翻阅各种资料和对opencv中的代码进行反推之后,终于理解该算法.并记录之,供大家一起交流学习!这个博文主要记录了我的学习历程,或许对你有帮助,或许可以启发你,或许你只是一笑而过!没关系,至少自己总结过. 这篇文章主要是对sif

灰度图像--图像增强 平滑之均值滤波、高斯滤波

学习DIP第30天 转载请标明本文出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些论坛转载后,图像无法正常显示,无法正常表达本人观点,对此表示很不满意.有些网站转载了我的博文,很开心的是自己写的东西被更多人看到了,但不开心的是这段话被去掉了,也没标明转载来源,虽然这并没有版权保护,但感觉还是不太好,出于尊重文章作者的劳动,转载请标明出处!!!! 文章代码已托管,欢迎共同开发:https://github.com/Tony-Tan/DIPpro

Opencv学习(1):高斯滤波

快乐虾@http://blog.csdn.net/lights_joy/ 欢迎转载,但请保留作者信息 本文适用于opencv3.0.0, vs2013 Opencv中提供了高斯滤波函数: /** @brief Blurs an image using a Gaussian filter. The function convolves the source image with the specified Gaussian kernel. In-place filtering is support

数学之路-python计算实战(18)-机器视觉-滤波去噪(双边滤波与高斯滤波 )

高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到.高斯滤波的具体操作是:用一个模板(或称卷积.掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值. #滤波去噪 lbimg=cv2.GaussianBlur(newimg,(3,3),1.8) cv2.imshow('src',newimg) cv2.imshow('dst',lbimg) cv2.waitKey() cv2.destroyAllW

图像滤波之高斯滤波介绍

1 高斯滤波简介 了解高斯滤波之前,我们首先熟悉一下高斯噪声.高斯噪声是指它的概率密度函数服从高斯分布(即正态分布)的一类噪声.如果一个噪声,它的幅度分布服从高斯分布,而它的功率谱密度又是均匀分布的,则称它为高斯白噪声.高斯白噪声的二阶矩不相关,一阶矩为常数,是指先后信号在时间上的相关性,高斯白噪声包括热噪声和散粒噪声. 高斯滤波器是一类根据高斯函数的形状来选择权值的线性平滑滤波器.高斯平滑滤波器对于抑制服从正态分布的噪声非常有效.一维零均值高斯函数为: g(x)=exp( -x^2/(2 si

IIR型高斯滤波的原理及实现

二.实现 GIMP中有IIR型高斯滤波的实现,代码位于contrast-retinex.c中,读者可自行查看.下面给出本人实现的核心代码: #include"stdafx.h" typedef struct { float B; float b[4]; } gauss_coefs; //参数计算 void compute_coefs3(gauss_coefs *c,float sigma) { float q, q2, q3; if (sigma >= 2.5) { q = 0.