图像处理:“可口可乐” 识别的算法改进

我过去几年中最有趣的项目之一是关于图像处理的项目。目的是开发一个能够识别可口可乐“罐头” 的系统 (请注意,我强调的是 “罐头” 一词,稍后您会看到原因)。您可以在下面看到一个示例,该示例在带有刻度和旋转的绿色矩形中可以识别。

模板匹配

对项目的一些限制:

  • 背景可能非常嘈杂。
  • 可以有任何比例旋转或什至取向(在合理范围内)。
  • 图像可能有一定程度的模糊性(轮廓可能不完全笔直)。
  • 图像中可能有可口可乐瓶,该算法只能检测到罐头
  • 图像的亮度可能相差很大(因此您不能过多地依赖颜色检测)。
  • 可以部分地隐藏在两侧或中间,可能部分地隐藏了一瓶后面。
  • 有可能是在所有的图像中没有就可以了 ,在这种情况下,你必须找到什么,写一条消息这样说。

因此,您可能会遇到诸如此类的棘手事情(在这种情况下,我的算法完全失败了):

总失败

我前一段时间做了这个项目,并且做得很有趣,并且实现得很好。以下是有关我的实现的一些详细信息:

语言 :使用OpenCV库在 C ++ 中完成。

预处理 :对于图像预处理,即将图像转换为更原始的形式以提供给算法,我使用了 2 种方法:

  1. 将颜色域从 RGB 更改为HSV,并基于 “红色” 色调进行过滤,饱和度高于特定阈值以避免产生类似橙色的颜色,而对低值进行过滤以避免产生深色。最终结果是一个二进制的黑白图像,其中所有白色像素将代表与该阈值匹配的像素。显然,图像中仍然有很多废话,但这减少了必须处理的尺寸数。 二值化图像
  2. 使用中值滤波进行噪声滤波(获取所有邻居的中值像素值,然后用该值替换像素)以减少噪声。
  3. 经过 2 个先验步骤后,使用Canny Edge Detection 滤镜获取所有项目的轮廓。 轮廓检测

算法 :我为此任务选择的算法本身取自于这本很棒的书中有关特征提取的书,并称为通用霍夫变换 (与常规霍夫变换完全不同)。它基本上说了几件事:

  • 您可以在不知道其解析方程的情况下描述空间物体(此处就是这种情况)。
  • 它可以抵抗诸如缩放和旋转之类的图像变形,因为它将基本上测试图像的缩放因子和旋转因子的每种组合。
  • 它使用算法将 “学习” 的基本模型(模板)。
  • 轮廓图像中剩余的每个像素将投票给另一个像素,该像素根据其从模型中学到的内容,应该是对象的中心(就重力而言)。

最后,您将获得投票的热图,例如,此处罐轮廓的所有像素都将为其重力中心投票,因此在与像素相对应的同一像素中将有很多投票居中,并会在热图中看到一个峰值,如下所示:

GHT

有了这些功能后,您就可以使用简单的基于阈值的启发式方法来确定中心像素的位置,从中可以得出比例尺和旋转角度,然后在其周围绘制一个小矩形(最终比例尺和旋转系数显然相对于您的原始模板)。理论上至少...

结果 :现在,尽管此方法在基本情况下可行,但在某些领域却严重缺乏:

  • 太慢了 !我的压力还不够。处理这 30 张测试图像几乎需要整整一天的时间,这显然是因为我对旋转和平移具有非常高的缩放系数,因为某些罐非常小。
  • 当瓶子出现在图像中时,它完全丢失了,并且出于某种原因几乎总是找到瓶子而不是罐子(也许是因为瓶子更大,所以像素更多,因此票数更多)
  • 模糊图像也不是很好,因为投票最终以像素为中心围绕中心的随机位置,从而以非常嘈杂的热图结束。
  • 实现了平移和旋转的不变性,但没有实现定向,这意味着未识别未直接面对相机物镜的罐子。

您能否使用专有的 OpenCV功能帮助我改善特定算法,以解决上述四个特定问题?

我希望有些人也能从中学到一些东西,毕竟我认为不仅提出问题的人也应该学习。 :)

答案

另一种方法是使用尺度不变特征变换 (SIFT)或加速鲁棒特征 (SURF)提取特征(关键点)。

它在OpenCV 2.3.1 中实现。

您可以使用Feature2D + Homography中的功能找到一个不错的代码示例, 以查找已知对象

两种算法对于缩放和旋转都是不变的。由于它们可以使用功能,因此您也可以处理遮挡 (只要可见足够的关键点)。

在此处输入图片说明

图片来源:教程示例

SIFT 的处理过程需要几百毫秒,SURF 速度更快,但是不适用于实时应用。 ORB 使用的 FAST 在旋转不变性方面较弱。

原始论文

为了加快处理速度,我会利用这样一个事实,即不要求您查找任意图像 / 对象,而是要查找带有可口可乐徽标的对象。这很重要,因为该徽标非常有特色,并且在频域中,尤其是在 RGB 的红色通道中,应具有特征性的,比例不变的签名。也就是说,水平扫描线(在水平对齐的徽标上训练)遇到的红色到白色到红色的交替图案在穿过徽标的中心轴时将具有独特的 “节奏”。该节奏将以不同的比例和方向 “加速” 或 “减速”,但将保持成比例的相等。您可以通过星标模式在徽标的水平和垂直方向以及对角线中识别或定义数十条这样的扫描线。称这些为 “签名扫描线”。

签名扫描线

在目标图像中搜索此签名很简单,只需扫描水平条中的图像即可。在红色通道中寻找一个高频(指示从红色区域移到白色区域),一旦找到,请查看其是否跟随训练中确定的频率节律之一。一旦找到匹配项,您将立即知道扫描线在徽标中的方向和位置(如果您在训练期间跟踪这些内容),因此从那里识别徽标的边界很简单。

如果这不是线性高效算法,或者几乎不是线性高效算法,我会感到惊讶。它显然不能解决您的水壶歧视问题,但至少您会拥有徽标。

(更新:对瓶承认我会找焦(棕色液体)相邻的标志 - 那就是, 瓶内或者说,在一个空瓶子的情况下,我会找一个上限 ,这将始终有基本形状,大小和与徽标的距离相同,通常为白色或红色。搜索相对于徽标应有帽子的纯色椭圆形。当然,这并非万无一失,但您的目标是快速找到简单的对象。)

(距离我的图像处理工作已经过去了几年,所以我将建议从总体上讲是概念性的。我认为这可能与人眼的操作方式略有相似,或者至少是我的大脑的操作方式!)

有趣的问题:当我瞥了一眼您的酒瓶图像时,我认为它也是一个罐头。但是,作为一个人类,我所做的与众不同之处在于我后来发现它也是一个瓶子……

因此,要区分罐头和瓶子,首先简单地扫描瓶子怎么样?如果找到一个,在寻找罐子之前先将标签遮盖。

如果您已经在做罐头,则实施起来并不难。真正的缺点是它将处理时间加倍。 (但是考虑到现实世界的应用程序,您最终还是想做瓶子;-)

即使人类在第二个图像中区分瓶子和罐头也不难(前提是瓶子的透明区域被隐藏了)?

除了很小的区域外,它们几乎是相同的(也就是说,罐头顶部的宽度略小,而瓶子的包装纸的宽度在整个宽度上都是相同的,但是有小的变化吗?)

我想到的第一件事是检查瓶子的红顶。但是,如果瓶子没有顶部,或者部分隐藏(如上所述),仍然是一个问题。

我想到的第二件事是关于瓶子的透明度。 OpenCV 在查找图像中的透明对象方面有一些工作。检查以下链接。

特别要看一下,以了解他们检测玻璃的准确性:

查看其执行结果:

在此处输入图片说明

他们说这是K. McHenry 和 J. Ponce 在 CVPR 2006 上发表的“用于寻找玻璃的测地线主动轮廓框架”的实现。

这可能对您的情况有所帮助, 但是如果装满瓶子问题就会再次出现。

因此,我认为在这里,您可以先搜索瓶子的透明主体,或者搜索横向连接到两个透明对象(显然是瓶子)的红色区域。 (理想工作时,图像如下)。

在此处输入图片说明

现在,您可以删除黄色区域,也就是瓶子的标签,然后运行算法以查找罐头。

无论如何,该解决方案也有其他解决方案中存在的其他问题。

  1. 仅在您的瓶子为空时才起作用。在这种情况下,您将必须搜索两种黑色之间的红色区域(如果可口可乐液体为黑色)。
  2. 如果覆盖了透明部分,则是另一个问题。

但是无论如何,如果图片中没有上述问题,那似乎是更好的方法。

我真的很喜欢Darren Cook堆垛机对这个问题的回答 。我当时正对这些想法发表评论,但我相信我的方法太过具有答案性,无法离开这里。

简而言之,您已经确定了一种算法,该算法可确定在空间的特定位置是否存在可口可乐徽标。您现在正在尝试针对任意方向和任意缩放比例确定一种启发式方法,以区分可口可乐与其他对象,包括:与该标志性徽标相关联的瓶子广告牌广告可口可乐用具 。您没有在问题陈述中提到很多其他情况,但我认为它们对于算法的成功至关重要。

这里的秘诀之一就是确定视觉特征一罐含有,或者通过负空间,特点是本作中不存在对罐外焦产品是什么。为此, 当前的最高答案勾勒出了一种基本方法,即当且仅当通过瓶盖,液体或其他类似的视觉启发法未识别出 “瓶” 时,才选择 “罐”。

问题是这崩溃了。例如,瓶子可能是空的,并且没有瓶盖,导致误报。或者,它可能是带有其他特征的不完整瓶子 ,从而再次导致错误检测。不用说,这不是很优雅,也不符合我们的目的。

为此,罐的最正确选择标准如下:

  • 正如您在问题中所概述的那样,对象轮廓的形状是否正确?如果是这样,请 + 1。
  • 如果我们假设存在自然光或人造光,是否会在瓶子上检测到铬轮廓,以表明其是否由铝制成?如果是这样,请 + 1。
  • 我们是否确定相对于我们的光源,物体的镜面特性是正确的(关于光源检测的 说明性视频链接 )?如果是这样,请 + 1。
  • 我们是否可以确定关于对象的其他任何属性,将其标识为罐,包括但不限于徽标的拓扑图像偏斜,对象的方向,对象的并置(例如,在平面上)例如桌子或其他罐头),以及是否有拉片?如果是这样,则每个 + 1。

然后,您的分类可能如下所示:

  • 对于每个候选匹配项,如果检测到存在可口可乐徽标,则绘制灰色边框。
  • 对于每次 + 2 的比赛,请绘制红色边框。

这在视觉上向用户突出显示了检测到的内容,强调了可以正确检测为扭曲罐的弱阳性。

对每个属性的检测具有非常不同的时间和空间复杂度,对于每种方法,快速通过http://dsp.stackexchange.com来确定最正确,最有效的算法是合理的。我的意图是纯粹地和简单地强调, 通过使候选检测空间的一小部分无效检测某物是否是罐子,并不是解决此问题的最有效或最有效的解决方案,理想情况下,您应该采取适当的措施相应地。

嘿,恭喜《黑客新闻》发布!总体而言,这是一个非常棒的问题,值得其宣传。 :)

看形状

在罐子 / 瓶子红色部分的形状上 a 一口。请注意,在瓶子标签是笔直的情况下,罐子如何在顶部稍微变细。您可以通过比较红色部分的宽度和长度来区分这两个部分。

看重点

区分瓶子和罐头的一种方法是材料。瓶子是用塑料制成的,而罐子是用铝金属制成的。在光线充足的情况下,查看镜面反射性将是从罐头标签分辨瓶子标签的一种方法。

据我所知,这就是人类如何分辨两种标签之间的区别。如果照明条件较差,则无论如何将两者区分开肯定会有一些不确定性。在这种情况下,您将必须能够检测到透明 / 半透明瓶本身的存在。

请查看 Zdenek Kalal 的 “ 捕食者” 追踪器 。它需要一些培训,但是它可以主动学习被跟踪对象如何看待不同方向和比例并实时进行操作!

源代码可在他的网站上找到。它在MATLAB 中 ,但是社区成员可能已经完成了 Java 实现。我已经成功地在 C#中重新实现了 TLD 的跟踪器部分。如果我没记错的话,TLD 正在使用蕨类作为关键点检测器。我使用 SURF 或 SIFT 代替(@stacker 已经建议)以重新获取对象,如果该对象被跟踪器丢失了。跟踪器的反馈使您可以轻松地随时间构建动态的筛选 / 冲浪模板列表,这些列表可以随着时间的流逝以很高的精度重新捕获对象。

如果您对我的 C#跟踪器实现感兴趣,请随时提出。

如果您不仅仅局限于一个不受限制的相机,也许您可以转向使用 Xbox Kinect 之类的距离传感器。使用此功能,您可以对图像进行基于深度和颜色的匹配分割。这样可以更快地分离图像中的对象。然后,您可以使用 ICP 匹配或类似的技术来匹配罐的形状,而不是仅匹配罐的轮廓或颜色,并且鉴于罐是圆柱形的,如果您以前对目标进行了 3D 扫描,那么这对于任何方向都是有效的选择。这些技术通常很快,特别是在用于解决速度问题的特定目的时。

我也可以建议,不一定出于准确性或速度的考虑,而是为了娱乐,您可以在色相分割的图像上使用经过训练的神经网络来识别罐子的形状。这些速度非常快,通常可以达到 80/90%的准确度。培训将是一个漫长的过程,尽管您必须手动识别每个图像中的罐头。

我会检测到红色矩形:RGB-> HSV,过滤红色 -> 二进制图像, 关闭 (先膨胀然后腐蚀,在 matlab 中称为imclose

然后从最大到最小浏览矩形。可以删除在已知位置 / 比例下具有较小矩形的矩形(假定瓶比例是恒定的,较小的矩形将是瓶盖)。

这会使您留下红色矩形,然后您需要以某种方式检测徽标以判断它们是红色矩形还是可乐罐。类似于 OCR,但带有已知徽标?

这可能是一个非常幼稚的想法(或可能根本不起作用),但是所有可乐罐的尺寸都是固定的。因此,如果同一张图片中同时包含一个罐头和一个瓶子,那么您可以通过尺寸方面的区分来区分它们(瓶子会更大)。现在,由于缺少深度(即 3D 映射到 2D 映射),瓶子可能会缩水并且大小没有差异。您可以使用立体成像恢复一些深度信息,然后恢复原始大小。