空域線性濾波:輸出像素 = Σ (鄰域像素 × 核權重) / 除數 + 偏移,再鉗制 [0,255]。
void __fastcall ApplyConvolution3x3(Graphics::TBitmap* Src, Graphics::TBitmap* Dst,
const int Kernel[3][3], int Divisor, int Offset = 0)
{
if (!Src || !Dst || Src->PixelFormat != pf24bit) return;
Dst->Assign(Src); // 複製尺寸/格式
int W = Src->Width, H = Src->Height;
for (int y = 1; y < H - 1; ++y) {
BYTE* dstRow = (BYTE*)Dst->ScanLine[y];
BYTE* srcRow = (BYTE*)Src->ScanLine[y];
BYTE* upRow = (BYTE*)Src->ScanLine[y-1];
BYTE* downRow = (BYTE*)Src->ScanLine[y+1];
for (int x = 3; x < (W - 1) * 3; x += 3) { // 跳過邊緣 1 像素
int sumB = 0, sumG = 0, sumR = 0;
// 3x3 鄰域加權
for (int ky = -1; ky <= 1; ++ky) {
BYTE* row = (ky == -1) ? upRow : (ky == 0 ? srcRow : downRow);
for (int kx = -1; kx <= 1; ++kx) {
int w = Kernel[ky+1][kx+1];
int idx = x + kx * 3;
sumB += row[idx + 0] * w;
sumG += row[idx + 1] * w;
sumR += row[idx + 2] * w;
}
}
int b = sumB / Divisor + Offset;
int g = sumG / Divisor + Offset;
int r = sumR / Divisor + Offset;
// 鉗制
b = (b < 0) ? 0 : (b > 255 ? 255 : b);
g = (g < 0) ? 0 : (g > 255 ? 255 : g);
r = (r < 0) ? 0 : (r > 255 ? 255 : r);
dstRow[x + 0] = (BYTE)b;
dstRow[x + 1] = (BYTE)g;
dstRow[x + 2] = (BYTE)r;
}
}
}
| 效果 | Kernel[3][3] | Divisor | Offset |
|---|---|---|---|
| 模糊 | {{1,1,1},{1,2,1},{1,1,1}} | 10 | 0 |
| 銳化 | {{0,-1,0},{-1,5,-1},{0,-1,0}} | 1 | 0 |
| 浮雕 | {{-2,-1,0},{-1,1,1},{0,1,2}} | 1 | 128 |
| 邊緣偵測 | {{-1,-1,-1},{-1,8,-1},{-1,-1,-1}} | 1 | 0 |
| 高斯模糊近似 | {{1,2,1},{2,4,2},{1,2,1}} | 16 | 0 |
| 拉普拉斯銳化 | {{0,-1,0},{-1,4,-1},{0,-1,0}} | 1 | 0 |
void __fastcall TForm1::btnBlurClick(TObject *Sender) {
int K[3][3] = {{1,1,1},{1,2,1},{1,1,1}};
ApplyConvolution3x3(Image1->Picture->Bitmap, bmpWork, K, 10);
Image1->Picture->Bitmap->Assign(bmpWork);
}
void __fastcall TForm1::btnSharpenClick(TObject *Sender) {
int K[3][3] = {{0,-1,0},{-1,5,-1},{0,-1,0}};
ApplyConvolution3x3(Image1->Picture->Bitmap, bmpWork, K, 1);
Image1->Picture->Bitmap->Assign(bmpWork);
}
void __fastcall TForm1::btnEmbossClick(TObject *Sender) {
int K[3][3] = {{-2,-1,0},{-1,1,1},{0,1,2}};
ApplyConvolution3x3(Image1->Picture->Bitmap, bmpWork, K, 1, 128);
Image1->Picture->Bitmap->Assign(bmpWork);
}
_mm_madd_epi16 等指令。