0

假设我有这个图像:
http
://srv2.jpg.co.il/9/51c614f7c280e.png 我想得到白球的位置(x,y),
这是一个非常大的图像,
然后我剪掉了矩形图像
(因为当图像较小时,一切都更快),
结果:
http
: //srv2.jpg.co.il/1/51c616787a3fa.png 现在我想通过他的颜色来跟踪白球的位置(white=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)吗?

4

1 回答 1

2

最后,我给你一个解决方案。调用GetPixel是一个代价高昂的过程,但您使用 Bitmap.LockBits 并从指针操作/访问图像数据。我LockBitmap这篇文章中上了一堂课。

我检查了我之前得到的性能,这和你提到的完全一样,大约 200 毫秒~。

这是使用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;
        }
    }
}
于 2013-06-23T01:43:09.240 回答