图像模糊优化

 

#include <windows.h>

HANDLE WINAPI BIPImgSoften(HANDLE hDib, long soften = 8) {
    if (!hDib || soften <= -8) return NULL;

    // 锁定 DIB 句柄,获取 BITMAPINFOHEADER
    BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*)GlobalLock(hDib);
    if (!pBIH) return NULL;

    int width = pBIH->biWidth;
    int height = abs(pBIH->biHeight);
    int bitCount = pBIH->biBitCount;
    int bytesPerPixel = bitCount / 8;  // 每像素字节数(一般 3 或 4)
    int rowSize = ((width * bitCount + 31) / 32) * 4;
    int imageSize = rowSize * height;

    // 创建新的 DIB 内存
    HANDLE hNewDib = GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER) + imageSize);
    if (!hNewDib) {
        GlobalUnlock(hDib);
        return NULL;
    }

    // 锁定新 DIB,获取 BITMAPINFOHEADER
    BITMAPINFOHEADER* pNewBIH = (BITMAPINFOHEADER*)GlobalLock(hNewDib);
    if (!pNewBIH) {
        GlobalFree(hNewDib);
        GlobalUnlock(hDib);
        return NULL;
    }

    // 复制头部信息
    *pNewBIH = *pBIH;

    BYTE* pSrcData = (BYTE*)(pBIH + 1);
    BYTE* pDstData = (BYTE*)(pNewBIH + 1);

    // 计算模糊核的权重
    int kernelSize = 3;
    int kernelSum = (soften + 9);  // 核的归一化系数
    int kernel[3][3] = {
        { 1,  1,  1 },
        { 1,  soften,  1 },
        { 1,  1,  1 }
    };

    // 遍历图像像素(忽略边界)
    for (int y = 1; y < height - 1; y++) {
        for (int x = 1; x < width - 1; x++) {
            for (int c = 0; c < bytesPerPixel; c++) {
                int sum = 0;

                // 计算 3×3 卷积区域
                for (int ky = -1; ky <= 1; ky++) {
                    for (int kx = -1; kx <= 1; kx++) {
                        int pixelOffset = ((y + ky) * rowSize) + ((x + kx) * bytesPerPixel) + c;
                        sum += pSrcData[pixelOffset] * kernel[ky + 1][kx + 1];
                    }
                }

                // 归一化处理,防止像素值溢出
                int pixelOffset = (y * rowSize) + (x * bytesPerPixel) + c;
                pDstData[pixelOffset] = min(255, max(0, sum / kernelSum));
            }
        }
    }

    // 处理边界(简单复制原图像)
    memcpy(pDstData, pSrcData, rowSize);  // 复制第一行
    memcpy(pDstData + (height - 1) * rowSize, pSrcData + (height - 1) * rowSize, rowSize); // 复制最后一行
    for (int y = 0; y < height; y++) {
        int rowOffset = y * rowSize;
        memcpy(pDstData + rowOffset, pSrcData + rowOffset, bytesPerPixel);                // 复制左侧像素
        memcpy(pDstData + rowOffset + (width - 1) * bytesPerPixel, 
               pSrcData + rowOffset + (width - 1) * bytesPerPixel, bytesPerPixel);       // 复制右侧像素
    }

    // 解锁 DIB
    GlobalUnlock(hDib);
    GlobalUnlock(hNewDib);

    return hNewDib;
}

  

 

你是对的,在上面的代码中,soften 变量没有真正影响模糊效果。我们可以使用 soften 值来调整模糊核的权重,使其产生不同程度的模糊效果。以下是修正后的代码:


📌 关键修改

  1. 调整模糊核的强度

    • 之前的 3×3 均值滤波器使用的是固定的均值 1/9
    • 现在 soften 变量用于调整核的强度: 1(soften+9)[1111soften1111]\frac{1}{(soften + 9)} \begin{bmatrix} 1 & 1 & 1 \\ 1 & soften & 1 \\ 1 & 1 & 1 \end{bmatrix}(soften+9)11111soften1111
    • soften 取值范围 > -8,当 soften = 8 时,中心权重大,边缘影响较小,减少模糊程度。
    • soften 越小(接近 -8),则所有像素更平均参与计算,使图像更加模糊。
  2. 优化循环计算

    • 直接在 for 循环中应用 soften 控制模糊权重,而不是固定的均值滤波。

✅ 修正后代码

cpp
#include <windows.h> HANDLE WINAPI BIPImgSoften(HANDLE hDib, long soften = 8) { if (!hDib || soften <= -8) return NULL; // 锁定 DIB 句柄,获取 BITMAPINFOHEADER BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*)GlobalLock(hDib); if (!pBIH) return NULL; int width = pBIH->biWidth; int height = abs(pBIH->biHeight); int bitCount = pBIH->biBitCount; int bytesPerPixel = bitCount / 8; // 每像素字节数(一般 3 或 4) int rowSize = ((width * bitCount + 31) / 32) * 4; int imageSize = rowSize * height; // 创建新的 DIB 内存 HANDLE hNewDib = GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER) + imageSize); if (!hNewDib) { GlobalUnlock(hDib); return NULL; } // 锁定新 DIB,获取 BITMAPINFOHEADER BITMAPINFOHEADER* pNewBIH = (BITMAPINFOHEADER*)GlobalLock(hNewDib); if (!pNewBIH) { GlobalFree(hNewDib); GlobalUnlock(hDib); return NULL; } // 复制头部信息 *pNewBIH = *pBIH; BYTE* pSrcData = (BYTE*)(pBIH + 1); BYTE* pDstData = (BYTE*)(pNewBIH + 1); // 计算模糊核的权重 int kernelSize = 3; int kernelSum = (soften + 9); // 核的归一化系数 int kernel[3][3] = { { 1, 1, 1 }, { 1, soften, 1 }, { 1, 1, 1 } }; // 遍历图像像素(忽略边界) for (int y = 1; y < height - 1; y++) { for (int x = 1; x < width - 1; x++) { for (int c = 0; c < bytesPerPixel; c++) { int sum = 0; // 计算 3×3 卷积区域 for (int ky = -1; ky <= 1; ky++) { for (int kx = -1; kx <= 1; kx++) { int pixelOffset = ((y + ky) * rowSize) + ((x + kx) * bytesPerPixel) + c; sum += pSrcData[pixelOffset] * kernel[ky + 1][kx + 1]; } } // 归一化处理,防止像素值溢出 int pixelOffset = (y * rowSize) + (x * bytesPerPixel) + c; pDstData[pixelOffset] = min(255, max(0, sum / kernelSum)); } } } // 处理边界(简单复制原图像) memcpy(pDstData, pSrcData, rowSize); // 复制第一行 memcpy(pDstData + (height - 1) * rowSize, pSrcData + (height - 1) * rowSize, rowSize); // 复制最后一行 for (int y = 0; y < height; y++) { int rowOffset = y * rowSize; memcpy(pDstData + rowOffset, pSrcData + rowOffset, bytesPerPixel); // 复制左侧像素 memcpy(pDstData + rowOffset + (width - 1) * bytesPerPixel, pSrcData + rowOffset + (width - 1) * bytesPerPixel, bytesPerPixel); // 复制右侧像素 } // 解锁 DIB GlobalUnlock(hDib); GlobalUnlock(hNewDib); return hNewDib; }

📌 关键改进

soften 变量真正影响模糊程度

  • soften > 0:中心像素影响更大,边缘像素影响小,减少模糊感。
  • soften < 0:所有像素均匀加权,增强模糊效果。

避免固定的 1/9 平均值,可以动态控制模糊核的中心权重。

边界像素复制,防止模糊后边缘出现黑边。


🚀 进一步优化

  1. 改进 soften 取值范围

    • 目前 soften > -8,可以进一步放宽,或者动态计算更大的模糊核(如 5×5)。
  2. 高斯模糊

    • 目前是 均值模糊,可以使用 高斯核,模糊更自然: [121242121]\begin{bmatrix} 1 & 2 & 1 \\ 2 & 4 & 2 \\ 1 & 2 & 1 \end{bmatrix}121242121 归一化后除以 16,实现更平滑的模糊。
  3. SIMD 加速

    • 使用 SSE / AVX 进行 向量化计算,提高处理速度。

🎯 结果

  • 模糊效果增强soften 变量现在可以 真正影响模糊程度
  • 适用于 24-bit / 32-bit DIB,并保持 RGB 色彩信息。
  • 边界复制修复,防止边缘变黑。

posted on 2025-02-01 03:07  lydstory  阅读(32)  评论(0)    收藏  举报

导航