我有几个图像,我想放在窗体中。图像本身是85 x 85.每个图像都有一个白色背景,其中包含一个可以位于图像任意位置的大小不等的圆柱体对象。.NET图像图像
例如:
图片1:85瓦特X 85H具有在气缸图像:从左上角
图像2(25,35):85瓦特X 85H具有在气缸图像:(28, 42)从左上角
我想知道是否有可能以编程方式确定与.NET图形库的位置(25,35)或(28,42)。
基本上我想要做的是将圆柱体重新定位到一个固定的坐标,从左上角说(10,10)。
我有几个图像,我想放在窗体中。图像本身是85 x 85.每个图像都有一个白色背景,其中包含一个可以位于图像任意位置的大小不等的圆柱体对象。.NET图像图像
例如:
图片1:85瓦特X 85H具有在气缸图像:从左上角
图像2(25,35):85瓦特X 85H具有在气缸图像:(28, 42)从左上角
我想知道是否有可能以编程方式确定与.NET图形库的位置(25,35)或(28,42)。
基本上我想要做的是将圆柱体重新定位到一个固定的坐标,从左上角说(10,10)。
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);
}
我不知道这个圆柱体是多么复杂(作为一个形状),但是你可以穿过所有的像素,检查哪个行和列可以找到第一个非白色像素。
AFAIK,圆柱体已经平坦地下到图形大概由一些Photoshop应用程序。 – coson 2009-07-23 18:31:52
好吧,无论如何,通过扫描行/列,找到第一行和最后一行/列,然后只是复制这样的矩形应该给你你需要的位置左,右,上,下。此外,您可以获取BitmapData并在不安全的上下文中对其进行扫描(通过操作指向原始位图数据的指针),这将比使用GetPixel()更快。 – 2009-07-23 18:47:58