2013-05-19 2 views
2

소벨 엣지 감지를 구현하는 프로그램을 만들고 싶습니다. 이 내 코드입니다 :가장 빠른 소벨 엣지 감지 C#

private Bitmap SobelEdgeDetect(Bitmap ori) 
{ 
     Bitmap b = original; 
     Bitmap bb = original; 
     int width = b.Width; 
     int height = b.Height; 
     int[,] gx = new int[,] { { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } }; 
     int[,] gy = new int[,] { { 1, 2, 1 }, { 0, 0, 0 }, { -1, -2, -1 } }; 

     int[,] allPixR = new int[width, height]; 
     int[,] allPixG = new int[width, height]; 
     int[,] allPixB = new int[width, height]; 

     int limit = 128 * 128; 

     for (int i = 0; i < width; i++) 
     { 
      for (int j = 0; j < height; j++) 
      { 
       allPixR[i, j] = b.GetPixel(i, j).R; 
       allPixG[i, j] = b.GetPixel(i, j).G; 
       allPixB[i, j] = b.GetPixel(i, j).B; 
      } 
     } 

     int new_rx = 0, new_ry = 0; 
     int new_gx = 0, new_gy = 0; 
     int new_bx = 0, new_by = 0; 
     int rc, gc, bc; 
     for (int i = 1; i < b.Width - 1; i++) 
     { 
      for (int j = 1; j < b.Height - 1; j++) 
      { 

       new_rx = 0; 
       new_ry = 0; 
       new_gx = 0; 
       new_gy = 0; 
       new_bx = 0; 
       new_by = 0; 
       rc = 0; 
       gc = 0; 
       bc = 0; 

       for (int wi = -1; wi < 2; wi++) 
       { 
        for (int hw = -1; hw < 2; hw++) 
        { 
         rc = allPixR[i + hw, j + wi]; 
         new_rx += gx[wi + 1, hw + 1] * rc; 
         new_ry += gy[wi + 1, hw + 1] * rc; 

         gc = allPixG[i + hw, j + wi]; 
         new_gx += gx[wi + 1, hw + 1] * gc; 
         new_gy += gy[wi + 1, hw + 1] * gc; 

         bc = allPixB[i + hw, j + wi]; 
         new_bx += gx[wi + 1, hw + 1] * bc; 
         new_by += gy[wi + 1, hw + 1] * bc; 
        } 
       } 
       if (new_rx * new_rx + new_ry * new_ry > limit || new_gx * new_gx + new_gy * new_gy > limit || new_bx * new_bx + new_by * new_by > limit) 
        bb.SetPixel(i, j, Color.Black); 

       //bb.SetPixel (i, j, Color.FromArgb(allPixR[i,j],allPixG[i,j],allPixB[i,j])); 
       else 
        bb.SetPixel(i, j, Color.Transparent); 
      } 
     } 
     return bb; 

    } 

난 내 프로그램을 빠르게 실행할 수 있도록 lockbits를 사용하여 싶지만 실제로는 여전히 그것을 사용하는 방법을 이해하지. 누구나 설명이나 예제 코드를 제공 할 수 있습니까?

+0

원래 코드는 소벨 알고리즘을했지만, 느렸다 사용하여 해제해야 사용 'GetPixel'과'SetPixel' 때문에. 이제 귀하의 코드는 * 두 * 비트 맵 (입력 및 출력)에 대해 'LockBits'를 사용하고 대답에서 설명한 것처럼 픽셀에'(x, y) '로 액세스해야합니다. 당신은 지금 아주 가깝습니다 - 포기하지 마십시오. –

+0

내 코드의 어느 부분이 lockbits와 교환되어야하는지 말해 줄 수 있습니까? 나는 우울함이 매우 심하다. thx – christ2702

답변

5

GetPixelSetPixel 대신 실제로 LockBits을 사용해야합니다.

그래서 당신은 모든 픽셀 데이터가 포함 된 BitmapData 객체 생성 :

IntPtr ptr = bmpData.Scan0; 
: 다음

// lock the input bitmap's bits 
System.Drawing.Imaging.BitmapData bmpData = 
    original.LockBits(new Rectangle(0, 0, original.Width, original.Height), 
    System.Drawing.Imaging.ImageLockMode.Read, original.PixelFormat); 

를 첫 번째 스캔 라인의 주소 (픽셀 즉, 첫 번째 행)를 얻을 수 있습니다

이제 두 가지 선택 사항이 있습니다. 당신이 unsafe로 기능을 표시하는 행복 경우에 당신은 당신에게 (24bpp를 가정)의 RGB 픽셀의 첫 번째 바이트에 대한 포인터를 제공이

byte* pPixels = (byte*)ptr.ToPointer(); 

처럼 직접 포인터 연산을 사용하여 픽셀을 액세스 할 수 있습니다. 그런 다음 포인터 연산을 사용하여 (x,y)에서 개별 픽셀에 액세스 할 수 있습니다. 먼저

int nBytesPerPixel = Image.GetPixelFormatSize(original.PixelFormat)/8; 

다음이 당신에게의 픽셀에 unsafe 액세스 할 수 있습니다 당신이

byte* pPixelAtXY = pPixels + (y * bmpData.Stride) + (x * nBytesPerPixel); 

원하는 픽셀에 인덱스를 계산 (당신이 이미하지 알고있는 경우) 픽셀 당 얼마나 많은 바이트를 결정 Bitmap을 사용하면 가장 빠른 속도의 입력 및 출력 비트 맵을 처리 할 수 ​​있습니다. 안전하지 않은 코드를 사용하려면 mark your function as unsafeedit your project properties이 필요합니다.

unsafe 코드를 사용하지 않으려면 모든 픽셀 데이터를 처리하기 전에 byte 배열로 복사 한 다음 나중에 다시 복사하여 처리 속도를 높일 수 있습니다. 은 MSDN 예제

// Get the address of the first line. 
IntPtr ptr = bmpData.Scan0; 

// Declare an array to hold the bytes of the bitmap. 
int bytes = Math.Abs(bmpData.Stride) * bmp.Height; 
byte[] rgbValues = new byte[bytes]; 

// Copy the RGB values into the array. 
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes); 

// Set every third value to 255. A 24bpp bitmap will look red. 
for (int counter = 2; counter < rgbValues.Length; counter += 3) 
    rgbValues[counter] = 255; 

// Copy the RGB values back to the bitmap 
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes); 

을 가리 켰을 때, 어떤 방법 당신은 픽셀 데이터를 완료 할 때, 당신은 UnlockBits

original.UnlockBits(bmpData); 
+0

완전한 소스 코드를 제공 할 수 있습니까? 시도했지만 오류가 발생합니다. – christ2702

+0

@ user1442032 질문을 편집하여 새 코드를 표시하면 잘못된 점을 알 수 있습니다. –