2009-07-23 70 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