让我说我有这个形象:
http://srv2.jpg.co.il/9/51c614f7c280e.png
我想获得白球位置(x,y),
这是一张verey大图像,然后我按矩形切割图像。
(因为当图像较小时,一切都更快),
结果:
http://srv2.jpg.co.il/1/51c616787a3fa.png
现在我想通过他的颜色跟踪白球位置(白色= rbg(255,255,255)),
我的代码:
Public Function GetBallPosition(ByRef HaxScreenOnly As Bitmap) As Point
For y = 0 To HaxScreenOnly.Height - 1
For x = 0 To HaxScreenOnly.Width - 1
If HaxScreenOnly.GetPixel(x, y) = Color.FromArgb(0, 0, 0) Then
If HaxScreenOnly.GetPixel(x + 8, y) = Color.FromArgb(0, 0, 0) And HaxScreenOnly.GetPixel(x + 8, y + 3) = Color.FromArgb(255, 255, 255) Then
Return New Point(x, y)
End If
End If
Next
Next
Return New Point(0, 0)
End Function
如果当前像素的颜色为黑色且当前像素的颜色(x + 8,y + 3)为白色,那么这就是球
它正在工作......但它的速度很慢,比如200毫秒来跟踪球的位置
这还不够快。
有更快的方法来跟踪白球( C#或VB.net )?
答案 0 :(得分:2)
最后,我为您提供了解决方案。调用GetPixel
是一个代价高昂的过程,但您使用Bitmap.LockBits并操纵/访问指针中的图像数据。我从 this article
LockBitmap
课程
我检查了我之前获得的表现,就像你提到的那样,大约200ms~。
以下是使用LockBitmap
的结果图片,使用优化的代码连续重新扫描图像!
static void Main(string[] args)
{
byte[] data = new WebClient().DownloadData("http://srv2.jpg.co.il/1/51c616787a3fa.png");
Image image = Image.FromStream(new MemoryStream(data));
LockBitmap bitmap = new LockBitmap(new Bitmap(image));
// this essentially copies the data into memory and copies from a pointer to an array
bitmap.LockBits();
Color black = Color.FromArgb(0, 0, 0);
Color white = Color.FromArgb(255, 255, 255);
Stopwatch stopwatch = Stopwatch.StartNew();
for (int y = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
// GetPixel is a nice abstraction the author in the Article created so we don't have to do any of the gritty stuff.
if (bitmap.GetPixel(x, y) == black)
{
if (bitmap.GetPixel(x + 8, y) == black && bitmap.GetPixel(x + 8, y + 3) == white)
{
Console.WriteLine("White Ball Found in {0}", stopwatch.Elapsed.ToString());
break;
}
}
}
}
bitmap.UnlockBits(); // copies the data from the array back to the original pointer
Console.Read();
}
希望这有帮助,对我来说这当然是一个有趣的读物。
正如King所说,我能够根据算法的改进进一步缩短你的时间。所以我们已经从O(n)变为O(n log)时间复杂度(我认为)。
for (int y = 0; y < bitmap.Height; y += 3) // As we know the radius of the ball
{
for (int x = 0; x < bitmap.Width; x += 3) // We can increase this
{
if (bitmap.GetPixel(x, y) == black && bitmap.GetPixel(x, y + 3) == white)
{
Console.WriteLine("White Ball Found ({0},{1}) in {2}", x, y, stopwatch.Elapsed.ToString());
break;
}
}
}