2009-02-01 10 views
7

Szukam rozwiązania dla wykrywanie krawędzi białych znaków z C# bitmap, z C# zarządzanej biblioteki GDI +.C# GDI Edge Algorytm wykrywania spacji

ilustracje byłoby albo przejrzysty lub biały większość 400X zdjęć są 8000x8000px z około 2000px spacji wokół krawędzi.

Jaki byłby najskuteczniejszy sposób sprawdzenia krawędzi, x, y, wysokość i szerokość współrzędnych? Próbowałem przejść piksel po pikselu, ale znajdowałem go bardzo wolno.

Aktualizacja do rozwiązania --Added lewo/prawo/góra/dolne granice

Problemy z obrazami center zdjęć szczegół, teraz crops dowolny przezroczysty (0%) lub kolor biały (#ffffff) pikseli.

var top = bitmap.Height; 
var left = bitmap.Width; 
var right = 0; 
var bottom = 0; 

...

var pData = pData0 + (y * data.Stride) + (x * 4); 
var xyAlpha = pData[3]; 
var xyBlue = pData[0]; 
var xyGreen = pData[1]; 
var xyRed = pData[2]; 
if ((xyAlpha > 0) || (xyRed != 255 && xyGreen != 255 && xyBlue != 255)) { 
    if (y < top) 
     top = y; 
    if (y > bottom) 
     bottom = y; 
    if (x < left) 
     left = x; 
    if (x > right) 
     right = x; 
} 

...

var cropWidth = right - left; 
var cropHeight = bottom - top; 
var cropX = top; 
var cropY = left; 

var cacheBitmap = new Bitmap(cropWidth, cropHeight, PixelFormat.Format32bppArgb); 
using (var cacheGraphics = Graphics.FromImage(cacheBitmap)) { 
    cacheGraphics.DrawImage(context.Image, new Rectangle(0, 0, cropWidth, cropHeight), cropX, cropY, cropWidth, cropHeight, GraphicsUnit.Pixel); 
} 

Odpowiedz

9

Wielki GDI + zasób jest Bob Powells GDI+ FAQ!

Nie podano, w jaki sposób uzyskałeś dostęp do pikseli na obrazie, więc założę się, że korzystałeś z powolnych metod GetPixel. Można użyć wskazówki i LockBits dostęp do pikseli w szybszy sposób: see Bob Powells explanation of LockBits - Będzie to wymagało niebezpiecznego blok kodu - jeśli nie chcesz lub nie masz FullTrust można użyć trick wyjaśnione tutaj: Pointerless Image Processing in .NET by J. Dunlap

Poniższy kod wykorzystuje metodę LockBits (dla PixelFormat.Format32bppArgb) i wypełnia punkty początkowy i końcowy wartością, w której odkrywane są pierwsze i ostatnie piksele obrazu, które nie mają koloru opisanego w kolorze argumentu. Metoda ignoruje również całkowicie przezroczyste piksele, co jest przydatne, jeśli chcesz wykryć obszar obrazu, w którym zaczyna się widoczna "zawartość".

Point start = Point.Empty; 
    Point end = Point.Empty; 

    int bitmapWidth = bmp.Width; 
    int bitmapHeight = bmp.Height; 

    #region find start and end point 
    BitmapData data = bmp.LockBits(new Rectangle(0, 0, bitmapWidth, bitmapHeight), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 
    try 
    { 
     unsafe 
     { 
      byte* pData0 = (byte*)data.Scan0; 
      for (int y = 0; y < bitmapHeight; y++) 
      { 
       for (int x = 0; x < bitmapWidth; x++) 
       { 
        byte* pData = pData0 + (y * data.Stride) + (x * 4); 

        byte xyBlue = pData[0]; 
        byte xyGreen = pData[1]; 
        byte xyRed = pData[2]; 
        byte xyAlpha = pData[3]; 


        if (color.A != xyAlpha 
          || color.B != xyBlue 
          || color.R != xyRed 
          || color.G != xyGreen) 
        { 
         //ignore transparent pixels 
         if (xyAlpha == 0) 
          continue; 
         if (start.IsEmpty) 
         { 
          start = new Point(x, y); 
         } 
         else if (start.Y > y) 
         { 
          start.Y = y; 
         } 
         if (end.IsEmpty) 
         { 
          end = new Point(x, y); 
         } 
         else if (end.X < x) 
         { 
          end.X = x; 
         } 
         else if (end.Y < y) 
         { 
          end.Y = y; 
         } 
        } 
       } 
      } 
     } 
    } 
    finally 
    { 
     bmp.UnlockBits(data); 
    } 
    #endregion 
2

Najpierw upewnij się, że korzystam z metody LockBits opisanej przez Patricka. Po drugie sprawdzam piksele na środkowych liniach, aby szybko określić krawędzie. Według środkowych linii, jeśli masz na myśli obraz 2000x1000, najpierw spojrzysz wzdłuż poziomej linii 500 (na 1000), aby znaleźć lewą i prawą granicę, a następnie wzdłuż linii pionowej 1000 (z 2000) znaleźć górny i dolny limit. Powinno to być bardzo szybkie w ten sposób.