这个周末让我烦透了:解决这些问题的好方法是什么?使用Mathematica(图像处理和其他功能)的[在北美以外的地方]谜题?

这是我目前所拥有的,一个通过调暗来稍微降低视觉复杂性的功能一些非红色:

whereIsWaldo[url_] := Module[{waldo, waldo2, waldoMask},
    waldo = Import[url];
    waldo2 = Image[ImageData[
        waldo] /. {{r_, g_, b_} /;
          Not[r > .7 && g < .3 && b < .3] :> {0, 0,
          0}, {r_, g_, b_} /; (r > .7 && g < .3 && b < .3) :> {1, 1,
          1}}];
    waldoMask = Closing[waldo2, 4];
    ImageCompose[waldo, {waldoMask, .5}]
]

还有一个URL的例子,它“起作用”:

whereIsWaldo["http://www.findwaldo.com/fankit/graphics/IntlManOfLiterature/Scenes/DepartmentStore.jpg"]

(Waldo在收银台旁):


我找到瓦尔多了!

我是怎么做到的

首先,我过滤掉所有不是红色的颜色

waldo = Import["http://www.findwaldo.com/fankit/graphics/IntlManOfLiterature/Scenes/DepartmentStore.jpg"];
red = Fold[ImageSubtract, #[[1]], Rest[#]] &@ColorSeparate[waldo];

接下来,我将计算这张图像与简单的黑白图案的相关性,以找到衬衫中的红色和白色过渡。

corr = ImageCorrelate[red, 
   Image@Join[ConstantArray[1, {2, 4}], ConstantArray[0, {2, 4}]], 
   NormalizedSquaredEuclideanDistance];

我使用Binarize来挑选图像中具有足够高相关性的像素,并在它们周围绘制白色圆圈,以使用Dilation来强调它们

pos = Dilation[ColorNegate[Binarize[corr, .12]], DiskMatrix[30]];

我不得不玩一玩水平。如果级别太高,则会挑出太多的误报。

最后,我将这个结果与原始图像相结合,得到上面的结果

found = ImageMultiply[waldo, ImageAdd[ColorConvert[pos, "GrayLevel"], .5]]

我猜这是一种“防弹的方式”(想想中情局在任何时候都能在任何卫星图像中找到沃尔多,而不仅仅是一张没有竞争元素的图像,比如条纹衬衫)。。。我会用波尔兹曼机器对沃尔多的许多图像进行训练——他坐着、站着、被遮挡等的各种变化。;衬衫、帽子、照相机和所有的作品。你不需要大量的瓦尔多语集(也许3-5个就足够了),但越多越好。

这将为以任何正确排列方式出现的各种元素分配概率云,然后确定(通过分割)平均对象大小,将源图像分割成最像单个人的对象单元(考虑到可能的遮挡和姿势变化),但由于Waldo图片通常包含大量相同比例的人,这应该是一项非常简单的任务,然后将这些片段送入预先训练的玻尔兹曼机器。它会给你每个人都是瓦尔多的概率。选择概率最高的一个。

这就是OCR、邮政编码阅读器和无笔画手写识别今天的工作原理。基本上,你知道答案就在那里,你或多或少知道它应该是什么样子,其他一切都可能有共同的元素,但肯定是“不是”,所以你不必担心“不是”,你只需要看看所有可能的“你以前见过的”中“它”的可能性(例如,在邮政编码中,你只需要训练BM 1、2、3等,然后将每个数字输入到每台机器,并选择一个最有信心的数字)。这比单一的神经网络学习所有数字的功能要好得多。


我不知道Mathematica。太糟糕了。但我最喜欢上面的答案。

然而,仅依靠条纹来收集答案仍然存在一个主要缺陷(我个人对一次手动调整没有问题)。有一个例子(Brett Champion在这里列出)表明,他们有时会打破衬衫图案。因此,它变成了一个更复杂的模式。

我会尝试形状id和颜色以及空间关系的方法。就像人脸识别一样,你可以在一定的比例下寻找几何图案。需要注意的是,这些形状中的一个或多个通常被遮挡。

在图像上获得白平衡,并从图像中获得红平衡。我相信Waldo总是相同的值/色调,但图像可能来自扫描,或是坏的副本。然后总是参考Waldo实际使用的一系列颜色:红色、白色、深棕色、蓝色、桃红色、{鞋色}。

有一种衬衫图案,还有裤子、眼镜、头发、脸、鞋子和帽子,这些都定义了沃尔多。此外,相对于照片中的其他人,沃尔多是瘦骨嶙峋的。

所以,找一些随机的人来获得这张照片中的人的身高。在图像中的任意点测量一堆物体的平均高度(一个简单的轮廓将产生相当多的个体)。如果每件事都不在彼此之间的标准偏差之内,那么它们现在就被忽略了。将高度的平均值与图像的高度进行比较。如果比率太大(例如,1:2、1:4或类似接近),请重试。运行10(?)次,以确保所有样本都非常接近,排除任何超出标准偏差的平均值。在Mathematica中可能吗?

这是你的瓦尔多尺码。沃尔索很瘦,所以你在找5:1或6:1(或其他)的东西。然而,这还不够。如果Waldo部分隐藏,高度可能会改变。因此,您正在寻找一块~2:1的红白相间的块。但必须有更多的指标。

沃尔多有眼镜。搜索红白上方0.5:1的两个圆圈。蓝色裤子。在红白相间的末端和他脚的距离之间的任何距离内,任何宽度的蓝色。注意,他穿着短衬衫,所以脚不会太近。帽子。红白相间的距离是他头顶的两倍。请注意,它下面一定有黑色的头发,可能还有眼镜。长袖。与主红白呈一定角度的红白相间。黑发。运动鞋颜色。我不知道颜色。

其中任何一种都适用。这些也是对照片中类似人群的负面检查——例如,#2否定穿红白围裙(太靠近鞋子),#5消除浅色头发。此外,形状只是这些测试中的一个指标。在指定距离内单独使用颜色可以获得良好的结果。

这将缩小要处理的区域。

存储这些结果将生成一组应该包含Waldo的区域。排除所有其他区域(例如,对于每个区域,选择一个两倍于平均人大小的圆圈),然后运行@Heike布局的过程,删除除红色以外的所有区域,依此类推。

对如何编码有什么想法吗?


编辑:

关于如何编写此代码的思考。排除除Waldo红色以外的所有区域,将红色区域骨架化,并将其修剪到一个点。对Waldo棕色头发、Waldo蓝色裤子、Waldo鞋颜色也一样。对于Waldo肤色,排除,然后找到轮廓。

接下来,排除非红色,扩大(大量)所有红色区域,然后去骨和修剪。本部分将列出可能的沃尔多中心点。这将是比较所有其他Waldo颜色部分的标记。

从这里开始,使用骨骼化的红色区域(而不是扩张的区域),计算每个区域中的线条。如果有正确的数字(四,对吗?),这肯定是一个可能的区域。如果不是,我想就把它排除在外(作为沃尔多中锋……这可能还是他的帽子)。

然后检查上面是否有脸型,上面是否有头发点,下面是否有裤子点,下面有鞋子点,等等。

还没有代码——仍在阅读文档。


我同意@GregoryKlopper的观点,即解决在任意图像中查找Waldo(或任何感兴趣的对象)的一般问题的正确方法是训练一个有监督的机器学习分类器。通过使用许多正负标记的示例,可以训练诸如支持向量机、Boosted Decision Stump或Boltzmann Machine之类的算法,以实现对该问题的高精度。Mathematica甚至在其机器学习框架中包含了这些算法。

训练Waldo分类器的两个挑战是:

确定右图像特征变换。这就是@Heike的答案可能有用的地方:红色过滤器和剥离模式检测器(例如小波或DCT分解)将是将原始像素转换为分类算法可以学习的格式的好方法。还需要基于块的分解来评估图像的所有子部分。。。但由于Waldo是a)总是大致相同的大小和b)总是在每个图像中恰好出现一次,这就变得更容易了。获得足够的培训示例。SVM在每个类中至少有100个示例时效果最佳。助推的商业应用(例如,数码相机中的面部聚焦)基于数百万个正面和负面例子进行训练。

快速的谷歌图片搜索会找到一些好数据——我现在就要尝试收集一些训练示例并编写代码了!

然而,即使是机器学习方法(或@iND建议的基于规则的方法)也会为瓦尔多斯之地这样的形象而奋斗!


我有一个使用OpenCV查找Waldo的快速解决方案。

我使用OpenCV中可用的模板匹配函数来查找Waldo。

为此,需要一个模板。所以我从原始图像中裁剪了Waldo,并将其用作模板。

接下来,我调用了cv2.matchTemplate()函数以及所使用的方法的归一化相关系数。它在单个区域返回了高概率,如下图白色所示(左上方区域的某处):

使用cv2.minMaxLoc()函数找到最高可能区域的位置,然后我使用该函数绘制矩形以突出显示Waldo: