首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

數位影像邊緣偵測演算法在 VC++ 中的實作:Sobel、Roberts 與 Laplacian 算子

     編輯:VC 教學

理論基礎

邊緣對應影像局部亮度劇烈變化區域。對數位影像,一階微分近似為差分,梯度幅值表示邊緣強度。常用算子:

1. Roberts 算子 (2×2)

G[i,j] = |f[i,j] - f[i+1,j+1]| + |f[i+1,j] - f[i,j+1]|

對角線方向敏感,計算快但雜訊敏感。

2. Sobel 算子 (3×3 加權)

水平梯度:
Δx = f(x-1,y+1) + 2f(x,y+1) + f(x+1,y+1) - f(x-1,y-1) - 2f(x,y-1) - f(x+1,y-1)

垂直梯度:
Δy = f(x-1,y-1) + 2f(x-1,y) + f(x-1,y+1) - f(x+1,y-1) - 2f(x+1,y) - f(x+1,y+1)

梯度幅值:G = |Δx| + |Δy| (近似 L1 範數,避免開根號)。

3. Laplacian 算子 (二階微分)

G[i,j] = |f[i+1,j] + f[i-1,j] + f[i,j+1] + f[i,j-1] - 4f[i,j]|

零交越點對應邊緣,對雜訊極敏感,通常配合高斯平滑 (LoG)。

VC++ 實作範例 (Sobel)

假設 CDibView 已取得灰階影像指標 hData、寬高 biWidth/biHeight、位元組寬 WIDTHBYTES。


void CDibView::OnMenuSobel()
{
    CDibDoc* pDoc = GetDocument();
    HDIB hDib = pDoc->m_hDIB;
    LPBITMAPINFOHEADER lpBi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
    BYTE* hData = (BYTE*)lpBi + lpBi->biSize + 256*sizeof(RGBQUAD);

    HANDLE hBuf = GlobalAlloc(GMEM_FIXED, WIDTHBYTES(lpBi->biWidth*8) * lpBi->biHeight);
    BYTE* data = (BYTE*)GlobalLock(hBuf);

    BeginWaitCursor();
    for (int y=1; y < lpBi->biHeight-1; y++)
    for (int x=1; x < lpBi->biWidth-1; x++)
    {
        int idx = y * WIDTHBYTES(lpBi->biWidth*8) + x;
        int idxUp   = idx - WIDTHBYTES(lpBi->biWidth*8);
        int idxDown = idx + WIDTHBYTES(lpBi->biWidth*8);

        // Δx (水平)
        int gx = (hData[idxUp+1] + 2*hData[idx+1] + hData[idxDown+1])
               - (hData[idxUp-1] + 2*hData[idx-1] + hData[idxDown-1]);
        // Δy (垂直)
        int gy = (hData[idxUp-1] + 2*hData[idxUp] + hData[idxUp+1])
               - (hData[idxDown-1] + 2*hData[idxDown] + hData[idxDown+1]);

        int g = abs(gx) + abs(gy);
        if (g > 255) g = 255;
        data[idx] = (BYTE)g;
    }

    // 複製回原緩衝區並更新視圖
    memcpy(hData, data, WIDTHBYTES(lpBi->biWidth*8) * lpBi->biHeight);
    GlobalUnlock(hBuf); GlobalFree(hBuf);
    GlobalUnlock(hDib);
    EndWaitCursor();
    Invalidate(TRUE);
}

優化建議

  • 查表法:預計算 3×3 社區所有 512 種組合的梯度值,查表替代運算。
  • SIMD 指令集:使用 MMX/SSE 並行處理 8/16 像素。
  • 雜訊預處理:先執行 3×3 高斯模糊再偵測邊緣。
  • 非極大值抑制:細化邊緣至單像素寬度。
  • 雙閾值滯後:Canny 邊緣偵測完整流程。

其他算子程式碼片段


// Roberts (邊界需特殊處理)
int g = abs(hData[idx] - hData[idx+W+1]) + abs(hData[idx+1] - hData[idx+W]);

// Laplacian
int g = abs(hData[idx-W] + hData[idx+W] + hData[idx-1] + hData[idx+1] - 4*hData[idx]);
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved