全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:5728
推到 Plurk!
推到 Facebook!

Sobel 邊緣檢測法(Ref. from Matlab IP toolbox)

 
arisaka_matsuri
高階會員


發表:25
回覆:205
積分:231
註冊:2003-10-19

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-11-26 00:27:45 IP:218.166.xxx.xxx 未訂閱
受不了taishyang版主的熱情邀約,PO出來給大家參考 程式內容參考MATLAB Image Processing Toolbox的edge.m    寫法還可以最佳化,希望先進們不吝賜教 ------------------------------------------------------------------- 參考資料: "edge", MATLAB Image Processing Toolbox ------------------------------------------------------------------- 函數說明:Sobel 邊緣檢測 參數傳入:TBitmap* 物件指標(其PixelFormat = pf8bit) 參數傳回:void -------------------------------------------------------------------     
// ImageSobelEdgeDetect FUNCTION
void __fastcall TFormMain::ImageSobelEdgeDetect(Graphics::TBitmap *pRefBitmap)
{      // 檢查是否為8bpp影像
  if(pRefBitmap->PixelFormat == pf8bit)
  {
    int row, col;
    int r, c;
    int ImageWidth  = pRefBitmap->Width;
    int ImageHeight = pRefBitmap->Height;        // 建立DestBitmap物件
    Graphics::TBitmap *pDestBitmap = new Graphics::TBitmap();
    pDestBitmap->Assign(pRefBitmap);
    // 填底色=>黑色(0)
    pDestBitmap->Canvas->Brush->Color = clBlack;
    pDestBitmap->Canvas->FillRect(Rect(0, 0, ImageWidth, ImageHeight));        // 建立暫存用記憶體
    double *MemoryBuff   = new double[ImageWidth * ImageHeight];
    double *MemoryBuffGX = new double[ImageWidth * ImageHeight];
    double *MemoryBuffGY = new double[ImageWidth * ImageHeight];        // 定義Sobel Operator的MaskArray
    double Scale     = 1.0 / 8.0;
    double SobelGY[] = { -1, -2, -1,
                          0,  0,  0,
                          1,  2,  1};
    double SobelGX[] = { -1,  0,  1,
                         -2,  0,  2,
                         -1,  0,  1};
    for(int i = 0; i < 9; i  )
    {
      SobelGY[i] = Scale * SobelGY[i];
      SobelGX[i] = Scale * SobelGX[i];
    }        // CALL: ImagePadding FUNCTION
    // NOTE: pRefBitmap的寬、高改變了
    ImagePadding(pRefBitmap, 1);
    // 指向pRefBitmap像素記憶體的指標
    Byte **ptrRef = new Byte *[pRefBitmap->Height];
    for(row = 0; row < pRefBitmap->Height; row  )
      ptrRef[row] = (Byte *)pRefBitmap->ScanLine[row];        // 計算梯度值
    double SX, SY;
    double SumOfImage = 0;
    int    index;
    for(row = 1; row < pRefBitmap->Height - 1; row  )
    {
      for(col = 1; col < pRefBitmap->Width - 1; col  )
      {
        // Convolution計算
        SX    = 0;
        SY    = 0;
        index = 0;
        for(r = -1; r <= 1; r  )
        {
          for(c = -1; c <= 1; c  )
          {
            SY  = (double)ptrRef[row - r][col - c] * SobelGY[index];
            SX  = (double)ptrRef[row - r][col - c] * SobelGX[index];
            index  ;
          }
        }
        MemoryBuff[(row - 1) * ImageWidth   (col - 1)]   = SX * SX   SY * SY;
        MemoryBuffGX[(row - 1) * ImageWidth   (col - 1)] = fabs(SX);
        MemoryBuffGY[(row - 1) * ImageWidth   (col - 1)] = fabs(SY);            if(   row > 2 && row < pRefBitmap->Height - 2
           && col > 2 && col < pRefBitmap->Width  - 2)
          SumOfImage  = MemoryBuff[(row - 1) * ImageWidth   (col - 1)];
      } // end of for(col)
    } // end of for(row)        // 計算cutoff
    double CutOff = 4 * SumOfImage / ((ImageWidth - 1) * (ImageHeight - 1));        // 填入
    Byte *ptrDest;
    for(row = 1; row < ImageHeight - 1; row  )
    {
      ptrDest = (Byte *)pDestBitmap->ScanLine[row];
      for(col = 1; col < ImageWidth - 1; col  )
      {
        if(
            (MemoryBuff[row * ImageWidth   col] > CutOff) &&
            (
              (
                MemoryBuffGX[row * ImageWidth   col] >= MemoryBuffGY[row * ImageWidth   col] &&
                MemoryBuff[row * ImageWidth   (col - 1)] <= MemoryBuff[row * ImageWidth   col] &&
                MemoryBuff[row * ImageWidth   col] > MemoryBuff[row * ImageWidth   (col   1)]
              )
              ||
              (
                MemoryBuffGY[row * ImageWidth   col] >= MemoryBuffGX[row * ImageWidth   col] &&
                MemoryBuff[(row - 1) * ImageWidth   col] <= MemoryBuff[row * ImageWidth   col] &&
                MemoryBuff[row * ImageWidth   col] > MemoryBuff[(row   1) * ImageWidth   col]
              )
            )
          )
          ptrDest[col] = 255;
      }
    }        // 拷貝pDestBitmap到pRefBitmap
    pRefBitmap->Assign(pDestBitmap);        delete [] ptrRef;
    delete MemoryBuff;
    delete MemoryBuffGX;
    delete MemoryBuffGY;
    delete pDestBitmap;
  } // end of if(pRefBitmap->PixelFormat == pf8bit)
  else
    ShowMessage("非Graylevel 8bits影像格式,無法進行邊緣檢測");
}
//--------------------------------------------------------------------------- 
其中的ImagePadding為
// ImagePadding FUNCTION
void __fastcall TFormMain::ImagePadding(Graphics::TBitmap *pRefBitmap, int PadSize)
{
  int row, col;
  
  // 建立PadBitmap物件
  Graphics::TBitmap *pPadBitmap = new Graphics::TBitmap();
  pPadBitmap->PixelFormat = pf8bit;
  pPadBitmap->Palette     = CreatePalette(&GrayPalette.lpal);
  pPadBitmap->Width       = pRefBitmap->Width    PadSize * 2;
  pPadBitmap->Height      = pRefBitmap->Height   PadSize * 2;      // 準備指向pPadBitmap像素記憶體的指標
  Byte **ptrPad = new Byte *[pPadBitmap->Height];
  for(row = 0; row < pPadBitmap->Height; row  )
    ptrPad[row] = (Byte *)pPadBitmap->ScanLine[row];      // 準備指向pRefBitmap像素記憶體的指標
  Byte **ptrRef = new Byte *[pRefBitmap->Height];
  for(row = 0; row < pRefBitmap->Height; row  )
    ptrRef[row] = (Byte *)pRefBitmap->ScanLine[row];          // Column Padding
  for(row = PadSize; row < pPadBitmap->Height - PadSize; row  )
  {
    // copy a 'line' of memory of pRefBitmap
    CopyMemory(&ptrPad[row][PadSize], ptrRef[row - PadSize], pRefBitmap->Width);        // copy border of SourceBitmap
    for(col = 0; col < PadSize; col  )
      ptrPad[row][col] = ptrRef[row - PadSize][0];
    for(col = pPadBitmap->Width - PadSize; col < pPadBitmap->Width; col  )
      ptrPad[row][col] = ptrRef[row - PadSize][pRefBitmap->Width - 1];
  }
  // Row Padding
  for(row = 0; row < PadSize; row  )
    CopyMemory(ptrPad[row], ptrPad[PadSize], pPadBitmap->Width);
  for(row = pPadBitmap->Height - PadSize; row < pPadBitmap->Height; row  )
    CopyMemory(ptrPad[row], ptrPad[pPadBitmap->Height - PadSize - 1], pPadBitmap->Width);      // 拷貝pPadBitmap到pRefBitmap
  pRefBitmap->Assign(pPadBitmap);      delete [] ptrPad;
  delete [] ptrRef;
  delete pPadBitmap;
}
//--------------------------------------------------------------------------- 
我不回答這兩個函數的相關問題,有興趣的讀者自行研究一下吧,謝謝~^^
taishyang
站務副站長


發表:377
回覆:5490
積分:4563
註冊:2002-10-08

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-11-26 01:15:01 IP:140.135.xxx.xxx 未訂閱
引言:受不了taishyang版主的熱情邀約,PO出來給大家參考
沒那麼嚴重吧< >< > 謝謝您的分享
overgod
一般會員


發表:5
回覆:5
積分:2
註冊:2004-12-30

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-01-11 19:18:01 IP:61.30.xxx.xxx 未訂閱
請問一下 MemoryBuffGX[(row - 1) * ImageWidth (col - 1)] = fabs(SX); 這一行當中的fabs是指什麼?! 還有就是imagepadding的功能又是什麼?!
arisaka_matsuri
高階會員


發表:25
回覆:205
積分:231
註冊:2003-10-19

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-01-12 02:03:45 IP:218.168.xxx.xxx 未訂閱
dear overgod:    fabs() 取浮點數的絕對值,查BCB HELP就有了    至於ImagePadding這個函數,本來不想回答的,因為要解釋很多東西。他的作用是把原來影像四邊向外擴大PadSize個像素,並且填入邊緣的像素。舉例來說:
原始影像    1 2 3
4 5 6
7 8 9    經過padding 1個像素    1 1 2 3 3
1 1 2 3 3
4 4 5 6 6
7 7 8 9 9
7 7 8 9 9
那為什麼要做這個動作?為了解決用mask運算時碰到影像邊緣時的處理問題。好處是padding完,我做運算不用去管邊界要怎麼做,只要把回圈中的範圍指定恰當即可。缺點就是要多做padding這道手續,不過其實就簡化寫程式的複雜度來說,是有用的。原本在MATLAB中的edge.m也有呼叫padarray這個指令,所以我就按照他的意思自己寫一個(當然功能沒那麼完整)。
overgod
一般會員


發表:5
回覆:5
積分:2
註冊:2004-12-30

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-01-12 17:36:59 IP:61.222.xxx.xxx 未訂閱
呵呵!感謝解答!說也奇怪…昨天我查bcb的help結果查不到fabs,還不只查了一次 ,可是今天一查就有了!不過我昨天編譯的時候,發現不能編譯…,現在就試看看。
系統時間:2024-11-26 2:37:02
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!