Sobel 邊緣檢測法(Ref. from Matlab IP toolbox) |
|
arisaka_matsuri
高階會員 發表:25 回覆:205 積分:231 註冊:2003-10-19 發送簡訊給我 |
受不了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 發送簡訊給我 |
|
overgod
一般會員 發表:5 回覆:5 積分:2 註冊:2004-12-30 發送簡訊給我 |
|
arisaka_matsuri
高階會員 發表:25 回覆:205 積分:231 註冊:2003-10-19 發送簡訊給我 |
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 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |