8位灰度图两次一维卷积高斯模糊(VC++)

本文介绍了如何利用高斯函数的可分离性,通过两次一维卷积实现8位灰度图的高斯模糊,以减少计算量。相比传统的二维高斯卷积,这种方法能显著提高效率。文章提供了实现代码,并展示了有黑边和无黑边两种处理边缘情况的效果图。

上篇文章中高斯模糊的处理方法是使用二维高斯卷积,但是这种方法是非常耗时间的,因此可以根据高斯函数的可分离性,对二维高斯模糊函数进行改进。

高斯函数的可分离性是指使用二维矩阵变换得到的效果也可以通过在水平方向进行一维高斯矩阵变换加上竖直方向的一维高斯矩阵变换得到。从计算的角度来看,这是一项有用的特性,因为这样只需要O(n*M*n)+O(m*M*N)次计算,而二维不可分的矩阵则需要O(m*n*M*n)次计算,其中,m,n为高斯矩阵的维数,M,N为二维图像的维数。

下面是两次一维卷积的实现代码:

一、使用两次一维高斯卷积处理,边缘已处理,但有黑边(效果在后面)

/*************************************************************************
*
* 函数名称:
*   GaussSmooth1D8()
*
* 参数:
*   LPSTR lpDIBBits     - 指向源DIB图像指针
*   LONG  lWidth        - 源图像宽度(象素数)
*   LONG  lHeight       - 源图像高度(象素数)
*   float fSigma        - 方差
*
* 返回值:
*   BOOL               - 成功返回TRUE,否则返回FALSE。
*
* 说明:
*   该函数对8位位图进行高斯模糊(两次1维高斯模糊)。
*
************************************************************************/

//对8位灰度图进行两次一维高斯卷积,边缘已处理,但有黑边
BOOL WINAPI GaussSmooth1D8(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, float fSigma)
{
    //指向高斯数据数组的指针
    float *fArray1D;
    //模板的长度
    int iVectorSize;
    // 数组的中心点
    int iTemplateM;
    // 数组的某一点到中心点的距离
    int iDistance;
    //π值
    double dPI = 3.1415926536;
    // 中间变量
    double  dValue;
    double  dSum = 0;
    // 数组长度,根据概率论的知识,选取[-3*sigma, 3*sigma]以内的数据。
    // 这些数据会覆盖绝大部分的滤波系数
    iVectorSize = (int)1 + 2 * ceil(3 * fSigma);   //ceil()返回大于或等于指定表达式的最小整数
    // 中心
    iTemplateM = iVectorSize / 2;
    // 分配内存
    fArray1D = new float[iVectorSize];
    for (int i = 0; i< iVectorSize; i++)
    {
        iDistance = abs((int)(i - iTemplateM));
        double aa = -0.5 / (fSigma*fSigma);
        double bb = 1 / ((sqrt(2 * dPI))*fSigma);
        //dValue = exp(-(1 / 2)*iDistance*iDistance / (dSigma*dSigma)) / (sqrt(2 * dPI) * dSigma);
        dValue = bb*exp(aa*(iDistance*iDistance));
        (fArray1D)[i] = dValue;
        dSum += dValue;
    }
    // 归一化
    for (int i = 0; i<iVectorSize; i++)
    {
        (fArray1D)[i] /= dSum;
    }

    // 指向复制图像的指针
    LPSTR   lpNewDIBBits;
    HLOCAL  hNewDIBBits;

    // 指向源图像的指针
    unsigned char*  lpSrc;

    // 指向要复制区域的指针
    unsigned char*  lpDst;

    // 计算结果
    double  fResult;

    // 图像每行的字节数
    LONG lLineBytes;

    // 计算图像每行的字节数
    lLineBytes = WIDTHBYTES(lWidth * 8);

    // 暂时分配内存,以保存新图像
    hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight);

    // 判断是否内存分配失败
    if (hNewDIBBits == NULL)
    {
        // 分配内存失败
        return FALSE;
    }

    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值