用Python如何找到沃利(Wally)?

85

我不要脸地跟风 :-)

受到如何使用Mathematica找到Waldo和后续如何使用R找到Waldo的启发,作为一个新的Python用户,我想看看这个怎么做。似乎Python比R更适合这个任务,并且我们不必担心像Mathematica或Matlab那样的许可证问题。

在下面的示例中,显然仅使用条纹是行不通的。如果可以制定一个简单的基于规则的方法来处理这种困难的示例,那将会很有趣。

At the beach

我已添加了 [机器学习] 标签,因为我认为正确的答案将需要使用 ML 技术,例如 Gregory Klopper 在原始线程中提倡的受限玻尔兹曼机(RBM)方法。Python 中有一些 RBM 代码可用,这可能是一个不错的起点,但显然需要训练数据来进行该方法。

2009 IEEE国际机器学习信号处理研讨会(MLSP 2009)上,他们进行了一个数据分析竞赛:沃利在哪里?。培训数据以matlab格式提供。请注意,该网站上的链接已失效,但可以在此处找到数据(以及肖恩·麦克卢恩和同事采取的方法的源代码链接)。看起来是一个开始的地方。


7
抱歉...是否有任何一个程序能够成功在这张照片中找到沃尔多?看起来没有任何与“真实”的沃尔多有关的显著特征。我曾经有过那本相同的沃尔多书,根据我的记忆,必须使用一些自然语言线索,例如真正的沃尔多没有拿手杖之类的东西。我不明白在没有让程序理解自然语言提示的情况下,如何通过编程找到沃尔多。 - AdamKG
是的,你说得对,抱歉...不过那也会是个有趣的任务!我已经把图片切换成了旧版的“在海滩上”那张,它也有条纹...(选择这张图片还有另一个原因!) - tdc
虽然这个问题很有趣,但你所要求的并不清楚。是要实现一个解决方案吗?还是给出使用哪个Python的机器学习库的提示? - Simon Bergot
@Simon 完整的实现可能有些过于苛求,但是一个框架性答案(即一些功能缺少定义)会很好。我甚至不确定是否需要加载图像(尽管我看到了这个链接:https://dev59.com/pHVD5IYBdhLWcg3wE3bz)。 - tdc
1
https://github.com/jacobsevart/waldo_uchicago - jfs
@J.F.Sebastian很酷...发表一个答案吗? - tdc
7个回答

66

这里有一个使用 mahotas 的实现。

from pylab import imshow
import numpy as np
import mahotas
wally = mahotas.imread('DepartmentStore.jpg')

wfloat = wally.astype(float)
r,g,b = wfloat.transpose((2,0,1))

将图像拆分为红色、绿色和蓝色通道。在下面最好使用浮点算术,因此我们在顶部进行转换。

w = wfloat.mean(2)

w 是白色通道。

pattern = np.ones((24,16), float)
for i in xrange(2):
    pattern[i::4] = -1

在垂直轴上建立+1、+1、-1、-1的一种图案。这就是沃利的衬衫。

v = mahotas.convolve(r-w, pattern)

使用红色减去白色进行卷积。这将在衬衫所处的位置得到强烈的响应。

mask = (v == v.max())
mask = mahotas.dilate(mask, np.ones((48,24)))

寻找最大值并膨胀以使其可见。现在,我们降低整个图像的色调,除了感兴趣的区域:

wally -= .8*wally * ~mask[:,:,None]
imshow(wally)

然后我们找到 waldo


3
我尝试了海滩图像,但效果不太好 :( Wally 出现在前六或七个搜索结果中,但匹配度并不是最高的。处理确实有帮助,因为我自己(用眼睛)无法找到他,而当我只有一堆小区域时,很容易找到他。 - luispedro
你有这个程序的完整源代码吗?我得到了“np未定义”的错误。 - encodes

2
你可以尝试使用模板匹配,然后记录产生最高相似度的模板,并使用机器学习进一步缩小范围。这也非常困难,而且由于模板匹配的准确性,它可能只返回每个脸部或类似脸部的图像。我认为如果你希望始终如一地完成这项任务,需要不止机器学习的帮助。

2

也许你应该先将问题分成两个较小的问题:

  1. 创建一个算法来将人与背景分离。
  2. 使用尽可能多的正面和负面例子来训练神经网络分类器。

这些仍然是需要解决的两个非常大的问题...

顺便提一下,我会选择c++和open CV,因为它似乎更适合这个问题。


2
如果您使用C++和OpenCV,那么Python的解决方案也同样可行。OpenCV可以在Python下使用。 - Unapiedra

2

这里是一个使用神经网络的解决方案,效果很好。

神经网络训练时使用多个已解决示例,这些示例都标有边界框,指示Wally出现在图片中的位置。该网络的目标是尽量减小与训练/验证数据中实际边界框相比的预测边界框的误差。

上述网络使用Tensorflow Object Detection API进行训练和预测。


1

我认为几乎总是可以看到两个主要特征:

  1. 红白条纹衬衫
  2. 华丽帽子下的深棕色头发

所以我会按照以下方式操作:

搜索条纹衬衫:

  • 过滤掉红色和白色(通过HSV转换图像上的阈值)。这样就可以得到两个掩码图像。
  • 将它们加在一起-> 这就是搜索条纹衬衫的主要掩码。
  • 创建一个新图像,将所有被过滤掉的红色转换为纯红色(#FF0000),将所有被过滤掉的白色转换为纯白色(#FFFFFF)。
  • 现在将这个纯红白图像与条纹图案图像相关联(我认为所有沃尔多都有相当完美的水平条纹,因此不需要旋转模式)。仅在上述主要掩码内执行相关性操作。
  • 尝试将可能是一个衬衫产生的集群组合在一起。

如果有超过一个“衬衫”,也就是说,存在多个正相关的集群,则搜索其他功能,如深棕色头发:

搜索棕色头发

  • 使用HSV转换图像和一些阈值来过滤特定的棕色头发颜色。
  • 在这个掩蔽图像中搜索一个特定区域 - 不要太大也不要太小。
  • 现在搜索一个“头发区域”,它位于之前检测到的条纹衬衫上方,并且与衬衫中心有一定的距离。

1

这并非不可能,但非常困难,因为您没有成功匹配的示例。通常有多个状态(在这种情况下,更多的找到墙壁图纸示例),然后可以将多个图片输入图像识别程序,并将其视为隐马尔可夫模型,并使用类似维特比算法的推理方法(http://en.wikipedia.org/wiki/Viterbi_algorithm)。

这是我处理它的方式,但假设您有多个图像,可以给它正确答案的示例,以便它可以学习。如果您只有一张图片,那么很抱歉,您可能需要采取另一种方法。


1

嗨,如果你需要完全可用的源代码,请过来。

import numpy as np
from pylab import imshow, show
import mahotas
import mahotas.demos
wally = mahotas.demos.load('Wally')
wfloat = wally.astype(float)
r,g,b = wfloat.transpose((2,0,1))
w = wfloat.mean(2)
pattern = np.ones((24,16), float)
for i in range(2):
    pattern[i::4] = -1
v = mahotas.convolve(r-w, pattern)
mask = (v == v.max())
mask = mahotas.dilate(mask, np.ones((48,24)))
np.subtract(wally, .8*wally * ~mask[:,:,None], out=wally, casting='unsafe')
imshow(wally)
show()

希望能对你有所帮助


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