24位真彩色图高斯模糊(VC++)

本文介绍如何处理24位真彩色图的高斯模糊,区别于8位灰度图,24位图每个像素由BGR三个通道组成。文中提供了二维卷积和两次一维卷积两种高斯模糊的实现方式,均处理了边缘,避免出现黑边。附带了不同方法的效果图。
摘要由CSDN通过智能技术生成

前两篇文章处理的都是8位灰度图,这篇文章处理的是24位真彩色图(bmp),它们之间的不同主要是8位灰度图有调色板,一个像素占一个字节,而24位真彩色图是一个像素占3个字节,分别是BGR三个通道(存储的顺序为BGR),因此在将算法从8位灰度图转移到24位真彩色图时,只需要对BGR三个通道分别处理即可。

下面是实现代码:

一、24位真彩色图二维卷积高斯模糊,边缘已处理,无黑边(效果在后面)

/*************************************************************************
*
* 函数名称:
*   GaussSmooth2D24()
*
* 参数:
*   LPSTR lpDIBBits     - 指向源DIB图像指针
*   LONG  lWidth        - 源图像宽度(象素数)
*   LONG  lHeight       - 源图像高度(象素数)
*   float fSigma        - 方差
*
* 返回值:
*   BOOL               - 成功返回TRUE,否则返回FALSE。
*
* 说明:
*   该函数对24位位图进行高斯模糊(2维高斯模糊)。
*
************************************************************************/
BOOL WINAPI GaussSmooth2D24(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, float fSigma)
{
    //指向高斯数据数组的指针,用作储存一维数组首元素的地址的地址
    float *fArray2D;
    // 数组的某一点到中心点的距离
    LONG iDistanceX;
    LONG iDistanceY;
    //模板高度
    int iTempH;
    //模板宽度
    int iTempW;
    //模板的中心元素X坐标 ( < iTempW - 1)
    int iTempMX;
    //模板的中心元素Y坐标 ( < iTempY - 1)
    int iTempMY;
    //π值
    double dPI = 3.1415926536;
    // 中间变量
    double  dValue;
    double  dSum = 0;
    // 数组长度,根据概率论的知识,选取[-3*sigma, 3*sigma]以内的数据。
    // 这些数据会覆盖绝大部分的滤波系数
    iTempH = 1 + 2 * ceil(3 * fSigma);   //ceil()返回大于或等于指定表达式的最小整数
    iTempW = 1 + 2 * ceil(3 * fSigma);  //ceil()返回大于或等于指定表达式的最小整数
    iTempMX = (int)iTempW / 2;
    iTempMY = (int)iTempH / 2;
    // 分配内存
    fArray2D = new float[iTempH*iTempW];
    for (int i = 0; i < iTempH; i++)
    {
        for (int j = 0; j < iTempW; j++)
        {
            iDistanceY = abs(i - (int)(iTempH / 2));
            iDistanceX = abs(j - (int)(iTempW / 2));
            double aa = -0.5 / (fSigma*fSigma);
            double bb = -aa / dPI;
            dValue = bb*exp(aa*(iDistanceX*iDistanceX + iDistanceY*iDistanceY));
            //dValue = exp(-(1 / 2)*(iDistanceX*iDistanceX + iDistanceY*iDistanceY)/ dSigma*dSigma) / (2 * dPI*dSigma*dSigma);
            (fArray2D)[i*iTempH + j] = dValue;
            dSum += dValue;
        }
    }
    // 归一化
    for (int i = 0; i < iTempH; i++)
    {
        for (int j = 0; j < iTempW; j++)
        {
            (fArray2D)[i*iTempH + j] /= dSum;
        }
    }

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

    // 计算结果
    FLOAT   fResult1, fResult2, fResult3;

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

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

    //定义暂时存储图像数组
    int* buf;
    buf = new int[(lHeight + iTempMY * 2) * (lWidth + iTempMX * 2) * 3];

    unsigned char* lpRed;
    unsigned char* lpGreen;
    unsigned char* lpBlue;

    //把图像复制给buf数组,并且把边缘也复制给buf数组,这样buf的大小就为(lHeight + iTempMY * 2) * (lWidth + iTempMX * 2) * 3
    for (int i = 0; i < lHeight; i++)
    {
        for (int j = 0; j < lWidth * 3; j++)
        {
            //扫描方式为从左到右,从下到上方式
            lpSrc = (unsigned char*)lpDIBBits + lLineBytes*(lHeight - 1 - i) + j;
            buf[(i + iTempMY)*(lWidth + iTempMX * 2) * 3 + iTempMX * 3 + j] = *lpSrc;
        }
    }
    //复制图像上方iTempMY*3行(1)
    for (int i = 0; i < iTempMY; i++)
    {
        for (int j = 0; j < lWidth * 3; j++)
        {
            //扫描方式为从左到右,从下到上方式
            lpSrc = (unsigned char*)lpDIBBits + lLineBytes*(lHeight - 1 - i) + j;
            buf[i*(lWidth + iTempMX * 2) * 3 + iTempMX * 3 + j] = *lpSrc;
        }
    }
    //复制图像下方iTempMY*3行(2)
    for (int i = lHeight - iTempMY; i < lHeight; i++)
    {
        for (int j = 0; j < lWidth * 3; j++)
        {
            //扫描方式为从左到右,从下到上方式
            lpSrc = (unsigned char*)lpDIBBits + lLineBytes*(lHeight - 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值