繁体   English   中英

我如何使用 Mathematica 找到 Waldo?

[英]How do I find Waldo with Mathematica?

这个周末一直困扰着我:有什么好方法可以解决沃尔多在哪里? [北美以外的'Wally' ] 谜题,使用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 在收银台旁边):

原图

Mathematica 图形

我找到了沃尔多!

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]]

我对“防弹方法”的猜测(想想中央情报局随时在任何卫星图像中找到沃尔多,而不仅仅是没有竞争元素的单一图像,如条纹衬衫)......我会在沃尔多的许多图像上训练玻尔兹曼机- 他坐、站、闭等的所有变化; 衬衫、帽子、相机和所有作品。 您不需要大量的 Waldos 语料库(也许 3-5 个就足够了),但越多越好。

这将为以任何正确排列发生的各种元素分配概率云,然后(通过分割)确定平均对象大小是多少,将源图像分割成最类似于个人的对象单元格(考虑可能的遮挡和姿势变化) ),但由于 Waldo 图片通常包含大量相同比例的人,这应该是一项非常容易的任务,然后将这些片段输入预训练的 Boltzmann 机器。 它会给你每个人都是 Waldo 的概率。 取一个概率最高的。

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

我同意@GregoryKlopper 的观点,即解决在任意图像中找到 Waldo(或任何感兴趣的对象)的一般问题的正确方法是训练有监督的机器学习分类器。 使用许多正标记和负标记示例,可以训练诸如支持向量机增强决策树桩或玻尔兹曼机之类的算法,以在此问题上实现高精度。 Mathematica 甚至将这些算法包含在其 机器学习框架中

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

  1. 确定正确的图像特征变换。 这是@Heike 的答案有用的地方:红色过滤器和剥离模式检测器(例如,小波或 DCT 分解)将是将原始像素转换为分类算法可以从中学习的格式的好方法。 还需要评估图像的所有子部分的基于块的分解……但是由于 Waldo a) 总是大致相同的大小并且 b) 在每个图像中总是只出现一次,这使得这变得更容易。
  2. 获得足够的训练样本。 SVM 最适合每个类的至少 100 个示例。 boosting 的商业应用(例如,数码相机中的人脸对焦)在数百万正例和反例上进行训练。

快速的谷歌图片搜索会找到一些很好的数据——我将尝试收集一些训练示例并立即对其进行编码!

然而,即使是机器学习方法(或@iND 建议的基于规则的方法)也很难获得像沃尔多斯土地这样的图像!

我不知道 Mathematica 。 . . 太糟糕了。 但在大多数情况下,我喜欢上面的答案。

还有在单独依靠搜集答案条纹的一大缺陷(我个人没有一个手动调节的一个问题)。 有一个例子(由 Brett Champion 列出, 这里)表明他们有时会破坏衬衫的图案。 那么它就变成了一个更复杂的模式。

我会尝试使用形状 ID 和颜色以及空间关系的方法。 就像人脸识别一样,您可以寻找彼此之间具有特定比例的几何图案。 需要注意的是,这些形状中的一个或多个通常会被遮挡。

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

有衬衫图案,还有定义 Waldo 的裤子、眼镜、头发、脸、鞋子和帽子。 此外,相对于图像中的其他人,Waldo 偏瘦。

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

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

  1. 沃尔多戴着眼镜。 在红白上方搜索两个 0.5:1 的圆圈。
  2. 蓝色裤子。 在红白色的末端和到他的脚的距离之间的任何距离内,具有相同宽度的任意数量的蓝色。 请注意,他的衬衫穿得很短,所以脚不会靠得太近。
  3. 帽子。 红白任意距离最多可达他头顶的两倍。 请注意,它下面必须有黑发,可能还戴着眼镜。
  4. 长袖。 红白与主红白有一定的角度。
  5. 黑发。
  6. 鞋子颜色。 我不知道颜色。

其中任何一个都可以申请。 这些也是对图片中类似人的负面检查——例如,#2 否定穿着红白色围裙(太靠近鞋子),#5 消除浅色头发。 此外,形状只是这些测试中的每一个的一个指标。 . . 在指定的距离内单独使用颜色可以产生很好的效果。

这将缩小要处理的区域。

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

关于如何编码的任何想法?


编辑:

关于如何编码的想法。 . . 排除 Waldo red 以外的所有区域,将红色区域骨架化,并将它们修剪成一个点。 对 Waldo 头发棕色、Waldo 裤子蓝色、Waldo 鞋颜色执行相同操作。 对于 Waldo 肤色,排除,然后找到轮廓。

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

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

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

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

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

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

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

在此处输入图片说明

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

在此处输入图片说明

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

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM