c# - 在 C# 中识别图像中的图像

标签 c# image lockbits

我想在图像(大海捞针)中找到图像()。

为简单起见,我截取了两张桌面屏幕截图。一个全尺寸的 (haystack) 和一个小的 (needle)。然后我遍历干草堆图像并尝试找到针图像。

  1. 捕获针和大海捞针截图
  2. 遍历 haystack,寻找 haystack[i] == 针的第一个像素
  3. [如果 2. 为真:]遍历 needle 的倒数第二个像素并将其与 haystack[i] 进行比较

预期结果:在正确的位置找到了针的图像。

我已经让它适用于某些坐标/宽度/高度 (A)。

但有时位似乎“关闭”,因此找不到匹配项 (B)。

我做错了什么?欢迎提出任何建议。谢谢。


var needle_height = 25;
var needle_width = 25;
var haystack_height = 400;
var haystack_width = 500;

A.示例输入 - 匹配

var needle = screenshot(5, 3, needle_width, needle_height); 
var haystack = screenshot(0, 0, haystack_width, haystack_height);
var result = findmatch(haystack, needle);

B.输入示例 - 不匹配

var needle = screenshot(5, 5, needle_width, needle_height); 
var haystack = screenshot(0, 0, haystack_width, haystack_height);
var result = findmatch(haystack, needle);

<强>1。捕获针和干草堆图像

private int[] screenshot(int x, int y, int width, int height)
{
Bitmap bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
Graphics.FromImage(bmp).CopyFromScreen(x, y, 0, 0, bmp.Size);

var bmd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), 
  ImageLockMode.ReadOnly, bmp.PixelFormat);
var ptr = bmd.Scan0;

var bytes = bmd.Stride * bmp.Height / 4;
var result = new int[bytes];

Marshal.Copy(ptr, result, 0, bytes);
bmp.UnlockBits(bmd);

return result;
}

<强>2。尝试找到匹配项

public Point findmatch(int[] haystack, int[] needle)
{
var firstpixel = needle[0];

for (int i = 0; i < haystack.Length; i++)
{
    if (haystack[i] == firstpixel)
    {
    var y = i / haystack_height;
    var x = i % haystack_width;

    var matched = checkmatch(haystack, needle, x, y);
    if (matched)
        return (new Point(x,y));
    }
}    
return new Point();
}

<强>3。验证完全匹配

public bool checkmatch(int[] haystack, int[] needle, int startx, int starty)
{
    for (int y = starty; y < starty + needle_height; y++)
    {
        for (int x = startx; x < startx + needle_width; x++)
        {
            int haystack_index = y * haystack_width + x;
            int needle_index = (y - starty) * needle_width + x - startx;
            if (haystack[haystack_index] != needle[needle_index])
                return false;
        }
    }
    return true;
}

最佳答案

我不会截取两次桌面屏幕截图并在它们之间留出时间间隔,而是截取一次屏幕截图并从相同的位图源中剪切“针”和“干草堆”。否则,在截取屏幕截图的两个时刻之间,您的桌面内容可能会发生变化。

编辑:当你的问题在那之后仍然出现时,我会尝试将图像保存到一个文件中,然后使用你的调试器再次尝试使用该文件,给你一个可重现的情况。

关于c# - 在 C# 中识别图像中的图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7729778/

相关文章:

c# - File.AppendAllText导致程序第二次运行时抛出访问异常

c# - 为什么 CLR 通过初始化优化掉未使用的静态字段?

c# - 有什么方法可以在重定向时将 LinkBut​​ton 内容从一个传递到另一个?

PHP - 将一个图像放在另一个图像上

ios - 从 URL 下载图像并存储在设备中(可以是 iPod 中的“照片”文件夹),而不是在应用程序中

C# 在图片框中移动位图

c# - 在 Fluent NHibernate 中创建复合索引?

c# - 在 C# 中裁剪图像空白

c# - 直接读取和写入解锁位图非托管内存(Scan0)

C#:LockBits 推出了一个巨大的红色 X