如何检测屏幕上是否存在图像?

4

这是我需要检测的图像:http://s13.postimg.org/wt8qxoco3/image.png

这是base64编码表示:http://pastebin.com/raw.php?i=TZQUieWe

之所以请求您的帮助,是因为这是一个复杂的问题,我没有足够的能力来解决它。如果只靠我自己完成,可能需要一周的时间。

一些我想到的伪代码:

1)截取应用程序的屏幕并将其存储为图像对象。

2)将我的图像的base64编码表示转换为图像对象。

3)使用某种算法/函数来比较两个图像对象。

当我说“在屏幕上”时,我的意思是在应用程序中。我有应用程序的窗口名称和PID。

要100%清楚,我需要检测的实质是图像1是否在图像2内。 图像1是我在OP中提供的图像,而图像2是窗口的屏幕截图。


1
屏幕上,哪里?在浏览器中,桌面上,还是在应用程序中? - sberry
SURF检测器非常适合您的需求。这里有一个示例 - Igonato
你需要检测图像的每个像素点是否完全一致吗?如果不是,那么这将会更加困难。 - abarnert
@abarnert:不幸的是,我需要基本上检测image1是否在image2内部。 image1是我在 OP 中提供的图像。 image2是窗口的屏幕截图。 - user1251385
是的,但是你所说的“在内部”,是指“图像1的每个像素都有一个完全相同的副本在图像2中的某个地方”,对吗? - abarnert
显示剩余2条评论
3个回答

3

如果你把它分解成几个部分,它们都非常简单。

首先,您需要将应用程序窗口的屏幕截图作为像素的2D数组。有许多不同的平台特定方法来实现这一点,但您没有提到您使用的平台,所以……让我们使用 PIL 抓取整个屏幕:

screenshot = ImageGrab.grab()
haystack = screenshot.load()

现在,您需要将base64转换为图像。快速查看一下,它显然是一个经过编码的PNG文件。所以:
decoded = data.decode('base64')
f = cStringIO.StringIO(decoded)
image = Image.open(f)
needle = image.load()

现在你有一个二维像素数组,想要查看它是否存在于另一个二维数组中。有更快的方法可以做到这一点,使用 numpy 可能是最好的方式,但也有一种愚蠢的蛮力方式,它更容易理解:只需迭代 haystack 的行;对于每一行,迭代列,并查看是否找到与 needle 的第一行匹配的字节串。如果是这样,请继续遍历其余的行,直到您完成了所有的needle,在这种情况下返回True,或者找到了不匹配的情况,在这种情况下您可以continue并重新开始下一行。


哇,谢谢!非常棒的“针/干草堆”比喻。我本应该自己想到的。我提问得不太好。 - user1251385
哦,data是你从任何地方读取的base64数据。如果它是一个本地文件,只需使用with open('data.b64') as f: data = f.read()。如果它在网络上,使用urllib2requests等库。诸如此类。 - abarnert
顺便说一句,"needle/haystack" 这个术语不是我想出来的。我不确定是谁想出来的,但是相当多的编程语言文档——比如 Smalltalk、PHP、Haskell 等——都使用它们作为查找/搜索函数的参数名称。 - abarnert
同时,你确定需要导入的所有内容都弄清楚了吗?应该只需要import cStringIOfrom PIL import Imagefrom PIL import ImageGrab...但是PIL的包/模块结构有点奇怪,如果这样不行,请告诉我。 - abarnert
所以我正在使用这段代码:http://pastebin.com/0q7C9XZM 但是我得到了这个错误 TypeError: 'PixelAccess' 对象不可迭代,位于第3行。顺便说一下,我正在使用的图像总像素数为980。 - user1251385
显示剩余2条评论

1
这可能是开始的最佳位置:

http://effbot.org/imagingbook/image.htm

如果您没有访问图像元数据、文件名、类型等的权限,那么您试图做的事情就非常困难,但您的伪代码听起来很准确。基本上,您将不得不创建一个基于照片的形状、线条、大小、颜色等的算法模型。然后,您必须将该模型与已经制作并索引在某个数据库中的模型进行匹配。希望这能有所帮助。

事实上,如果您对他的Base64进行解码,它只是一个完整的PNG文件,因此他可以访问他需要使用PIL将其转换为像素数组的所有内容。所以这个方法可以用。 - abarnert
如果我可以访问图像的元数据,那么为什么会更容易呢?为了100%清楚,我需要基本上检测image1是否在image2内。 image1是我在OP中提供的图像。 image2是窗口的屏幕截图。 image2不会有任何元数据,因为它只是一个屏幕截图。 - user1251385
@user1251385:我认为他的意思是说,你需要元数据来确定如何将位映射到像素上。(换句话说,你需要PNG头文件,而你已经有了。) - abarnert
abarnert,确切地说。由于某种原因,我认为这是用于随机图像的。听起来你可能不需要图像检测来完成你所说的事情。例如,您可以设置一个函数来注册是否已经拍摄了屏幕截图。再次强调,我不确定您想要做什么。 - terra823

0

最好使用注释来回答这样的问题。如果您想将它们作为答案添加,请包含完全回答问题所需的相关细节。谢谢,祝您有美好的一天。 - Bhargav Rao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接