图像锐化原理与实现
锐化通常使用拉普拉斯算子或高通滤波器。以下代码基于 3×3 锐化核:
主要步骤:
- 获取 DIB 头部信息(如宽度、高度、位深度)。
- 复制 BITMAPINFOHEADER 并创建新 DIB 以存储处理后的图像。
- 使用卷积操作进行锐化:
- 使用 3×3 锐化核: [0−10−1S−10−10]\begin{bmatrix} 0 & -1 & 0 \\ -1 & S & -1 \\ 0 & -1 & 0 \end{bmatrix}0−10−1S−10−10 其中,
S = 4 + sharpen
,sharpen
控制锐化强度(大于 8)。
- 使用 3×3 锐化核: [0−10−1S−10−10]\begin{bmatrix} 0 & -1 & 0 \\ -1 & S & -1 \\ 0 & -1 & 0 \end{bmatrix}0−10−1S−10−10 其中,
- 边界处理(简单处理边界像素)。
- 解锁并返回新 DIB 句柄。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | HANDLE WINAPI BIPImgSharpen( HANDLE hDib, long sharpen = 15) { if (!hDib || sharpen <= 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; 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 kernel[3][3] = { { 0, -1, 0 }, { -1, 4 + sharpen, -1 }, { 0, -1, 0 } }; // 遍历图像像素(忽略边界) 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; // 计算卷积 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]; } } // 限制值域 [0, 255] int pixelOffset = (y * rowSize) + (x * bytesPerPixel) + c; pDstData[pixelOffset] = min(255, max(0, sum)); } } } // 处理边界(简单复制) 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; } |
说明:
- 卷积计算:遍历图像像素,对每个像素应用
3x3
锐化核计算加权和。 - 边界处理:避免溢出,边界像素简单复制原值(可以改进为镜像填充)。
- 性能优化:
- 可优化为多线程(如 OpenMP)。
- 通过SIMD 指令(如 SSE/AVX)加速矩阵计算。
这样就实现了一个基本的 DIB 图像锐化函数!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2023-02-01 杭州天谷信息电子章子
2023-02-01 icepdf
2022-02-01 中国红歌在线
2018-02-01 智能家居