图像锐化原理与实现

锐化通常使用拉普拉斯算子或高通滤波器。以下代码基于 3×3 锐化核:

主要步骤:

  1. 获取 DIB 头部信息(如宽度、高度、位深度)。
  2. 复制 BITMAPINFOHEADER 并创建新 DIB 以存储处理后的图像。
  3. 使用卷积操作进行锐化
    • 使用 3×3 锐化核: [0−10−1S−10−10]\begin{bmatrix} 0 & -1 & 0 \\ -1 & S & -1 \\ 0 & -1 & 0 \end{bmatrix}0101S1010 其中,S = 4 + sharpensharpen 控制锐化强度(大于 8)。
  4. 边界处理(简单处理边界像素)。
  5. 解锁并返回新 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 图像锐化函数!

posted on   lydstory  阅读(20)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2023-02-01 杭州天谷信息电子章子
2023-02-01 icepdf
2022-02-01 中国红歌在线
2018-02-01 智能家居

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示