2009-07-23 54 views
1

我有幾個圖像,我想放在窗體中。圖像本身是85 x 85.每個圖像都有一個白色背景,其中包含一個可以位於圖像任意位置的大小不等的圓柱體對象。.NET圖像圖像

例如:

圖片1:85瓦特X 85H具有在氣缸圖像:從左上角
圖像2(25,35):85瓦特X 85H具有在氣缸圖像:(28, 42)從左上角

我想知道是否有可能以編程方式確定與.NET圖形庫的位置(25,35)或(28,42)。

基本上我想要做的是將圓柱體重新定位到一個固定的座標,從左上角說(10,10)。

回答

1

Bitmap類包含一個GetPixel方法,該方法根據其X和Y座標返回位圖中像素的顏色。一種技術可能是遍歷數據的行和列以確定存在非白色像素的最低X和Y座標。如果圖像較小和/或性能不是主要考慮因素,則此技術已足夠,因爲調用GetPixel相當慢。

另一種方法是將位圖圖像數據轉換爲字節[],然後遍歷數組中的字節以確定非白色像素的位置。這種方法需要了解給定位圖類型(例如32位,24位,1位等)字節佈局方式的一些知識。

要獲取位圖的字節,可以調用位圖上的LockBits方法來鎖定位圖的區域並獲取BitmapData對象。然後使用BitmapData對象的Stride和Height屬性來確定包含位圖所需的字節數組的大小。

我鞭打併測試了下面的方法,它似乎在我創建的幾個測試圖像上快速地工作以檢測橢圓的位置。

private Point DetectLocation(Bitmap original) 
{ 
    Bitmap source = null; 

    // If original bitmap is not already in 32 BPP, ARGB format, then convert 
    if (original.PixelFormat != PixelFormat.Format32bppArgb) 
    { 
     source = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb); 
     source.SetResolution(original.HorizontalResolution, original.VerticalResolution); 
     using (Graphics g = Graphics.FromImage(source)) 
     { 
      g.DrawImageUnscaled(original, 0, 0); 
     } 
    } 
    else 
    { 
     source = original; 
    } 

    // Lock source bitmap in memory 
    BitmapData sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 

    // Copy image data to binary array 
    int imageSize = sourceData.Stride * sourceData.Height; 
    byte[] sourceBuffer = new byte[imageSize]; 
    Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize); 

    // Unlock source bitmap 
    source.UnlockBits(sourceData); 

    int sourceIndex = 0; 
    int pixelTotal = 0; 
    int height = source.Height; 
    int width = source.Width; 
    int threshold = 255 * 3; 

    int minX = width; 
    int minY = height; 

    // Iterate lines 
    for (int y = 0; y < height; y++) 
    { 
     sourceIndex = y * sourceData.Stride; 

     // Iterate pixels 
     for (int x = 0; x < width; x++) 
     { 
      // Compute pixel brightness (i.e. total of Red, Green, and Blue values) 
      pixelTotal = sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2] + sourceBuffer[sourceIndex + 3]; 
      if (pixelTotal < threshold) 
      { 
       minX = Math.Min(minX, x); 
       minY = Math.Min(minY, y); 
      } 
      sourceIndex += 4; 
     } 
    } 

    return new Point(minX, minY); 
} 
1

我不知道這個圓柱體是多麼複雜(作爲一個形狀),但是你可以穿過所有的像素,檢查哪個行和列可以找到第一個非白色像素。

+0

AFAIK,圓柱體已經平坦地下到圖形大概由一些Photoshop應用程序。 – coson 2009-07-23 18:31:52

+0

好吧,無論如何,通過掃描行/列,找到第一行和最後一行/列,然後只是複製這樣的矩形應該給你你需要的位置左,右,上,下。此外,您可以獲取BitmapData並在不安全的上下文中對其進行掃描(通過操作指向原始位圖數據的指針),這將比使用GetPixel()更快。 – 2009-07-23 18:47:58