8

在图形屏幕上寻找东西,我目前不知道如何在图像中找到给定的形状。图像中的形状可能具有不同的比例,并且当然会有一些未知的 x,y 偏移。

除了不同尺度导致的像素伪影之外,两张图像中也有一点噪音,所以我需要一个稍微宽容的搜索。

这是我正在寻找的图像。

农夫框架

它应该出现在我的(双)屏幕缓冲区的屏幕转储中,大小约为 3300 x 1200 像素。我当然希望在浏览器窗口中找到它,但这些信息不应该是必需的。

这个练习的目的(到目前为止)是想出一个结果:

  • 是的,在我的屏幕上(或没有)找到了木制框架(颜色近似,形状可能略有截断);和
  • 游戏的客户区(框架内的黑色区域)占据了从(x1,y1)到的矩形(x2,y2)

我希望对缩放和抖动可能引入的噪声具有鲁棒性。另一方面,我可以排除一些常见的 CV 挑战,例如旋转或非刚性。这种框架形状对于人脑来说非常容易辨别,对于专用软件来说有多难?这是一个 Adob​​e Flash 应用程序,直到最近我还认为从游戏 GUI 中感知图像应该很容易。

我正在寻找一种算法,该算法能够找到针和干草堆之间发生最大可能重叠的 x、y 平移,并且如果可能的话,无需通过一系列可能的比例因子进行迭代。理想情况下,该算法可以以一种独立于比例的方式抽象出图像的“形状”。

我读过一些关于傅立叶变换的有趣的东西来完成类似的事情:给定一个相同比例的目标图像,FFT 和一些矩阵数学在更大的图像中产生了与搜索模式相对应的点。但我没有将其付诸实践的理论背景,也不知道这种方法是否能优雅地处理规模问题。帮助将不胜感激!

技术:我正在使用 Clojure/Java 编程,但可以适应其他语言的算法。我认为我应该能够与遵循 C 调用约定的库进行交互,但我更喜欢纯 Java 解决方案。


您可能会理解为什么我回避展示实际图像。这只是一个愚蠢的游戏,但事实证明,屏幕阅读的任务比我想象的更具挑战性。

我显然能够对我的屏幕缓冲区进行详尽的搜索,以查找构成我的图像的像素(不包括黑色),甚至可以在一分钟内运行。但我的目标是找到使用一种与形状相匹配的技术的木制框架,而不管缩放和抖动可能产生的差异。

事实上,抖动是我在这个项目中遇到的许多挫折之一。我一直致力于通过边缘提取来提取一些有用的向量,但是边缘非常难以捉摸,因为任何给定区域的像素具有广泛不一致的颜色 - 所以很难从局部抖动伪影中分辨出真正的边缘。我不知道如此简单的游戏会产生软件难以感知的图形。

在我开始寻找特征之前,我应该从局部平均像素开始吗?我应该通过丢弃像素颜色值的最低有效位来减少颜色深度吗?

我正在尝试一个纯 Java 解决方案(实际上是在 Clojure/Java 混合中编程),所以我对 opencv(它使用 C 代码安装 .DLL 或 .so)并不感兴趣。请不要担心我的语言选择,学习体验对我来说比表演更有趣。

4

3 回答 3

11

作为一名计算机视觉专家,我通常会指出特征提取和匹配(SIFT、SURF、LBP 等),但这几乎可以肯定是矫枉过正,因为这些方法中的大多数都提供了更多的不变性(= 对转换的容忍度)比你实际需要的(例如反对旋转,亮度变化,......)。此外,使用功能将涉及 OpenCV 或大量编程。

所以这是我对一个简单解决方案的建议——你判断它是否通过了智能阈值:

看起来您正在寻找的图像具有一些非常独特的结构(字母、徽标等)。我建议您对每种可能的翻译以及许多不同的比例进行像素到像素匹配(我假设比例范围是有限的) - 但仅适用于您正在寻找的图像的一小块独特的补丁(例如,黄色文本的正方形部分)。这比匹配整个事情要快得多。如果您想要一个花哨的名称:在图像处理中,它被称为相关性模板匹配。“模板”是您正在寻找的东西。

一旦你为你的小独特补丁找到了几个候选位置,你可以通过测试整个图像或更有效地测试图像的其他几个独特补丁来验证你是否命中(当然,使用翻译/你找到的规模)。这使您的搜索对原始补丁的意外匹配具有鲁棒性,而不会窃取太多性能。

关于抖动容限,我将对两个图像(您正在寻找的模板和作为您的搜索空间的图像)进行简单的预过滤。根据抖动的属性,您可以开始尝试简单的框模糊,如果不起作用,可能会继续使用小内核 (3 x 3) 的中值滤波器。这不会让您在模板和搜索图像之间获得 100% 的同一性,但您可以比较可靠的数字分数。

根据评论编辑

我知道 (1) 您想要更强大、更“类似 CV”并且更花哨的解决方案,并且 (2) 您对通过简单地扫描一大堆不同的尺度来实现尺度不变性持怀疑态度。

关于(1),如上所述,规范方法是使用特征描述符。特征描述符不描述完整的图像(或形状),而是描述图像的一小部分,其方式对各种变换是不变的。看看SIFTSURF,以及VLFeat,它具有良好的 SIFT 实现并且还实现了MSERHOG(并且比 OpenCV 小得多)。SURF 比 SIFT 更容易实现,两者都拥有大量专利。两者都有一个“直立”版本,没有旋转不变性。这应该会增加您的情况的稳健性。

您在评论中描述的策略更多地朝着形状描述符的方向发展,而不是图像特征描述符。确保您了解它们之间的区别!2D 形状描述符针对通常由轮廓或二进制掩码描述的形状。图像特征描述符(在上述意义上使用)针对具有强度值的图像,通常是照片。一个有趣的形状描述符是形状上下文这里总结了许多其他的。我不认为你的问题最好通过形状描述符来解决,但也许我误解了一些东西。我会非常小心图像边缘的形状描述符,因为边缘是一阶导数,可以通过抖动噪声强烈改变。

关于(2):我想说服你,扫描一堆不同的尺度对于那些不了解计算机视觉的人来说不仅仅是一个愚蠢的黑客!实际上,它在视觉上做了很多,我们只是给它起了一个花哨的名字来误导外行——尺度空间搜索。这有点过于简单化了,但实际上只是一点点。在实践中使用的大多数图像特征描述符使用尺度空间来实现尺度不变性,尺度空间是不断缩小(和低通滤波)图像的堆栈。他们添加的唯一技巧是在尺度空间中寻找极值并仅在这些极值处计算描述符。但是,仍然会计算并遍历完整的尺度空间以找到那些极值。看看原始的 SIFT 论文对此有一个很好的解释。

于 2013-02-26T14:34:42.847 回答
2

好的。我曾经通过捕获屏幕在 Flash 游戏上实现了一些作弊 :)。如果您需要找到您在图像中给出的确切边框,您可以创建一个颜色过滤器,从而删除所有其余部分,最终得到一个可以用于进一步处理的二进制图像(手头的任务是找到一个具有一定边框比例的匹配矩形。此外,您可以实现四个内核,以找到几个不同比例的角。

如果您有图像流并且知道有运动,您还可以通过使用背景建模解决方案监控帧之间的差异以捕捉屏幕中的动作部分。结合这些,我猜你会走得很远,而无需诉诸更奇特的方法,比如多尺度分析之类的东西。

它的性能有问题吗?我的作弊使用了大约 20 fps,因为它需要足够快地点击一个球。

于 2013-02-25T20:23:22.210 回答
0

我正在报告我自己的问题的答案,让人们知道我最终去了哪里。


在我寻求的魔法比例不变形状描述符上没有找到或得到任何提示,我决定按照 DCS 的建议在整个屏幕上执行几乎直接的像素搜索。

首先,我搜索了 512 x 60 的徽标块。但事实证明,最终成为四嵌套循环(完整图像的行/列 x 搜索图像的行/列)将运行一个多小时,最坏的情况。不可接受。

我可以通过选择较小的搜索图像(大约 48 x 32 像素的补丁)来线性缩小问题。我认为这花了我大约 30 秒,但仍然比我希望的要慢。此外,当我后来尝试搜索其他一些功能时,时间会越来越长。

我的解决方案是只搜索我的搜索图像的单个扫描线,甚至通过代理而不是完全搜索。由于我正在搜索的图像的漫画色彩性质,我认为平均色调可以很好地代表我正在寻找的像素。我选择了搜索图像的“中间”行,提取了每个像素的色调(作为 0 到 7200 之间的整数),并计算了这些色调值的总和。在屏幕图像中,我计算了与搜索图像宽度相对应的像素数的移动总数,因此对于每个像素位置,我只需减去最旧的像素并添加一个新像素。使用 JavaColor.rgbToHSB留下了一些优化潜力,特别是考虑到转换为float并返回,但整个屏幕可以在几百毫秒内进行预采样。

因此,我为我的搜索图像中间线创建了一个屏幕色调总和之间的差异列表,找到了最佳(即最小)差异,然后对那些共享第一名以获得最佳差异的位置进行了完整的逐像素比较。这些最佳颜色总匹配通常少于 10 个,因此 10 个逐个像素的比较花费的时间可以忽略不计。

所以现在我在大约半秒内找到了我的搜索图像,还有一些优化潜力尚未开发。如果我需要“做”更多不同的比例,希望不同的分辨率能让我选择不同的搜索图像而无需反复试验,但在最坏的情况下,只需要多次运行一小部分比较工作,我预计仍会停留在一秒钟之内。

我没有达到我最初的目标,即对我所寻找的图像的不同抖动(即细节像素再现)非常有抵抗力;我的算法需要很好的颜色匹配。但考虑到这将是一个多么困难的问题,我决定如果有必要我会越过那座桥。

于 2013-03-05T16:49:18.767 回答