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


在过去的几年里,我参与过的最有趣的项目之一就是一个项目 图像处理。目标是开发一个能够识别可口可乐的系统 “易拉罐” (请注意,我强调'罐头'这个词,你会在一分钟内看到原因)。您可以在下面看到一个示例,其中可以识别出 绿色矩形 具有比例和旋转。

Template matching

对项目的一些限制:

  • 背景可能非常嘈杂。
  • 能够 可以有任何 规模 要么 回转 甚至是方向(在合理的范围内)。
  • 图像可能有一定程度的模糊(轮廓可能不完全笔直)。
  • 图像中可能有可口可乐瓶,算法应该只能检测到 能够
  • 图像的亮度可能会有很大差异(因此您不能过多依赖颜色检测)。
  • 能够 可以部分隐藏在侧面或中间,可能部分隐藏在瓶子后面。
  • 可能没有 能够 完全在图像中,在这种情况下,你不得不找到任何东西并写一条消息说这样。

所以你最终可能会遇到这样棘手的事情(在这种情况下我的算法完全失败):

Total fail

我不久前做了这个项目,并且做了很多乐趣,我有一个不错的实现。以下是有关我的实施的一些细节:

语言:使用C ++完成 OpenCV的 图书馆。

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

  1. 将颜色域从RGB更改为 HSV 并基于“红色”色调进行过滤,饱和度超过一定阈值以避免橙色样色,并过滤低值以避免暗色调。最终结果是二进制黑白图像,其中所有白色像素将表示与该阈值匹配的像素。显然,图像中仍然存在大量垃圾,但这会减少您必须使用的维度数量。 Binarized image 
  2. 使用中值滤波进行噪声滤波(取所有邻居的中值像素值并用该值替换像素)以减少噪声。
  3. 运用 Canny边缘检测滤波器 在2个先例步骤之后获得所有项目的轮廓。 Contour detection

算法:我为此任务选择的算法本身取自 这个 关于特征提取和调用的精彩书籍 广义Hough变换 (与常规Hough变换完全不同)。它基本上说了几件事:

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

最后,你得到了一张投票的热图,例如这里所有罐子轮廓的像素都会投票给它的引力中心,所以你会在同一个像素对应的投票中得到很多票。中心,并将在热图中看到如下峰值:

GHT

一旦你有了这个,一个简单的基于阈值的启发式可以给你中心像素的位置,你可以从中获得比例和旋转,然后围绕它绘制你的小矩形(最终的比例和旋转因子显然将相对于你原始模板)。理论上至少......

结果:现在,虽然这种方法在基本情况下有效,但在某些方面却严重缺乏:

  • 它是 非常慢!我并没有强调这一点。处理30个测试图像需要将近一整天,显然是因为我有一个非常高的旋转和平移比例因子,因为一些罐子非常小。
  • 当瓶子出现在图像中时,它完全丢失了,由于某种原因,几乎总是发现瓶子而不是罐头(也许是因为瓶子更大,因此有更多的像素,因此更多的选票)
  • 模糊图像也不好,因为投票在中心周围的随机位置以像素结束,因此以非常嘈杂的热图结束。
  • 实现了平移和旋转的方差,但没有取向,这意味着没有直接面对相机物镜的罐子被识别出来。

你能帮我改进吗? 具体 算法,使用 专门的OpenCV 功能,解决了 四具体 提到的问题?

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


1392
2018-04-16 04:23


起源


可以说这个问题在dsp.stackexchange.com或stats.stackexchange.com上更合适,你当然也应该考虑在这些网站上重新询问。 - ely
这里要做的第一件事就是分析 为什么 不同的失败案件正在发生。例如,隔离瓶子获胜的地方的例子,图像模糊的地方等,并进行一些统计分析以了解他们的霍夫表示与你希望它会检测到的那些之间的差异。一些了解替代方法的好地方是 这里 和 这里 - ely
@stacker说得好。对于速度,您希望获得便宜的计算功能,例如定向梯度的直方图。一个非常天真的第一种方法是在一些训练图像中手动标记一堆can矩形,并使用这些加上随机负面示例来训练SVM或决策树分类器。培训需要更长时间,但新图像的执行速度会快得多。当我有更多的空闲时间来包含正确的引用时,我打算写这个方法。 - ely
类似的方法怎么样? 验证码? ;) - George Duckett
为什么会这样 dsp.stackexchange.com?看起来该站点比stackoverflow o_O更合适 - BlueRaja - Danny Pflughoeft


答案:


另一种方法是使用。提取特征(关键点) 尺度不变特征变换 (SIFT)或 加快了强大的功能 (冲浪)。

它是在实施的 OpenCV的 2.3.1。

您可以使用中的功能找到一个很好的代码示例 Features2D + Homography找到一个已知对象

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

Enter image description here

图片来源:教程示例

对于SIFT,处理需要几百ms,SURF的速度要快一些,但它不适合实时应用。 ORB使用FAST,其在旋转不变性方面较弱。

原始论文


563
2018-04-16 05:17



我同意@stacker - SIFT是一个很好的选择。它对比例和旋转操作非常强大。它对透视变形有一定的鲁棒性(这可以通过堆栈器建议来改进:具有所需对象的不同透视图的模板数据库)。根据我的经验,它的致命弱点是强烈的照明变化和非常昂贵的计算。我不知道任何Java实现。我知道OpenCV实现并使用了GPU c ++ / Windows(SiftGPU)实现适合实时性能。
警告提示:尽管我喜欢SIFT / SURF以及他们对我做了什么,但他们受到了专利保护。这个 威力 是一个问题,取决于许多条件,包括地理位置AFAIK。 - Agos
因此,尝试OpenCV的ORB或FREAK,它们没有专利问题。 ORB比SIFT快得多。 ORB它的体积和光线变化有点差,但我自己测试一下。 - Rui Marques
你怎么能接受这个答案......没有一个特征描述符可以区分瓶子和罐头......它们都只是查看不变的局部模式描述符。我同意SIFT,SURF,ORB,FREAK等可以帮助你进行功能匹配,但是..你的问题的其他部分如闭塞,瓶与罐等等。我希望这不是一个完整的解决方案,如果你愿意的话有可能第一个结果只是这个答案。 - G453
@ G453你是绝对正确的!可能他对SHIFT的性能很着迷,忘记了特征提取和匹配不是问题...... - sepdek


为了加快速度,我会利用这样一个事实:你不会被要求找到任意图像/物体,特别是有可口可乐标志的图像/物体。这很重要,因为这个标识非常独特,它应该在频域中具有特征性的,尺度不变的特征,特别是在RGB的红色通道中。也就是说,水平扫描线(在水平对齐的徽标上训练)遇到的红色到白色到红色的交替图案在通过徽标的中心轴时将具有独特的“节奏”。这种节奏将在不同的尺度和方向上“加速”或“减速”,但仍将按比例保持相同。您可以通过徽标识别/定义几十条这样的扫描线,水平和垂直扫描线以及几个对角线的扫描线,采用星爆图案。将这些称为“签名扫描线”。

Signature scan line

在目标图像中搜索此签名是一个简单的问题,即以水平条带扫描图像。寻找红色通道中的高频(指示从红色区域移动到白色区域),并且一旦找到,查看它是否跟随训练期间识别的频率节奏之一。找到匹配后,您将立即知道扫描线在徽标中的方向和位置(如果您在训练期间跟踪这些内容),那么从那里识别徽标的边界是微不足道的。

如果这不是一个线性有效的算法,或者几乎如此,我会感到惊讶。它显然没有解决你的罐装歧视,但至少你会有你的标志。

(更新:对于瓶子识别,我会寻找与徽标相邻的焦炭(棕色液体) - 也就是说,  瓶子。或者,如果是空瓶子,我会寻找一个  它总是具有与徽标相同的基本形状,大小和距离,通常都是白色或红色。寻找带帽的纯色椭圆形状 应该 是,相对于徽标。当然不是万无一失,但你的目标应该是找到 简单 那些 快速。)

(自我的图像处理时间已经过去几年了,所以我将这个建议保持在高水平和概念上。我认为它可能略微接近人眼的操作方式 - 或者至少我的大脑是如何操作的!)


331
2018-04-17 21:06



这是一个很好的建议,我特别喜欢这个算法应该非常快的事实,即使它可能会有很多漏报。我隐藏的目标之一是对机器人技术实时使用这种检测,这可能是一个很好的妥协! - Charles Menguy
是的,它经常被遗忘(在一个精确的领域) 近似 算法对于大多数实时,实际建模任务至关重要。 (我的基础是我的 论文 关于这个概念。)为有限的区域保存您需要时间的算法(修剪误报)。请记住:在机器人技术中,您通常不限于单个图像。假设一个移动机器人,一个快速的alg可以在更短的时间内搜索来自不同角度的数十个图像,而不是复杂的algs花费在一个上,从而显着减少假阴性。 - kmote
我喜欢使用相当于条形码扫描仪的想法 非常快 检测可口可乐标识。 +1! - Li-aung Yip
在这种情况下寻找签名的问题在于,如果我们将罐子转到另一侧,即隐藏签名,算法将无法检测罐头。 - karlphillip
@karlphillip:如果你隐藏签名,即徽标,那么 任何 基于寻找徽标的方法将失败。 - Li-aung Yip


有趣的问题:当我瞥了一眼你的瓶子图像时,我觉得它也是可以的。但是,作为一个人,我所做的就是告诉它不同之处在于我注意到它也是一个瓶子......

那么,为了区分罐头和瓶子,如何简单地先扫描瓶子?如果找到一个,在寻找罐头之前屏蔽标签。

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


132
2018-04-16 05:03



是的,我也考虑过这个,但没有太多时间去做。你怎么会认出一个瓶子,因为它的主要部分看起来像一个缩放的罐子?我当时正在考虑寻找红色插头,看看它是否与瓶装中心对齐,但这看起来不太稳健。 - Charles Menguy
如果有一个与“可口可乐”平行的红色帽子(或环),它很可能是一个瓶子。 - Lukasz Madon
@linker你是如何训练罐的算法的?你有罐头的例子吗?如何用瓶子的例子进行训练? - siamii
这个算法的优点是你只需要 一 要训​​练的模板,然后它应用所有变换以将其与其他潜在的罐匹配。我正在使用这个模板的二值化和基于轮廓的版本进行训练,所以罐头和瓶子之间的唯一区别就是插头,但我担心它会带来更多的误报,因为重力中心会在边缘的某个地方或在瓶子外面。值得一试,我猜。但那会使我的处理时间加倍,我会哭;) - Charles Menguy
基本上这是一个合理的方向。我会说它略有不同:首先找到所有候选人,然后为每个候选人确定它是瓶子,罐头还是其他东西。 - MSalters


即使人类在第二张图片中区分瓶子和罐子也不困难(假设瓶子的透明区域是隐藏的)?

它们几乎是相同的,除了一个非常小的区域(也就是说,罐头顶部的宽度有点小,而瓶子的包装纸在整个宽度相同,但是稍微改变了吗?)

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

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

特别注意这一点,看看它们检测玻璃的准确程度如何:

查看他们的实施结果:

Enter image description here

他们说这是本文的实施 “寻找玻璃的测地学活动轮廓框架”,K。McHenry和J. Ponce,CVPR 2006

它可能对你的情况有所帮助, 但是如果瓶子装满了问题又会出现问题。

所以我想在这里,您可以首先搜索瓶子的透明体,或者是横向连接到两个透明物体的红色区域,这显然是瓶子。 (理想情况下,图像如下。)

Enter image description here

现在您可以删除黄色区域,即瓶子的标签,并运行算法以查找罐头。

无论如何,这个解决方案也有其他解决方案中的不同问题。

  1. 它只适用于您的瓶子是空的。在这种情况下,您将不得不搜索两种黑色之间的红色区域(如果可口可乐液体是黑色的)。
  2. 覆盖透明部分的另一个问题。

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


101
2018-04-18 23:02



+1我想到了这一点,并且正在以我的方式实施这种方法。但是,@ linker应该分享他的图像集,这样我们就可以尝试做更多有根据的猜测。 - karlphillip
是的..我也觉得如果有更多的图像那就好了。 - Abid Rahman K
我知道这是一个老帖子。分钟的链接似乎已经死了。有没有人提到他们? - Xocoatzin
链接再次死亡 - charlesreid1
@ charlesreid1:他们又复活了:) - Abid Rahman K


我很喜欢 达伦库克的 和 堆垛机的答案 这个问题。我正在把我的想法投入评论那些,但我相信我的方法太具有回答的形状,不能离开这里。

简而言之,您已经确定了一种算法,以确定在太空中的特定位置存在可口可乐徽标。您现在正在尝试确定适用于区分可口可乐的任意方向和任意缩放因子的启发式方法  来自其他对象,包括: 瓶子广告牌广告,和 可口可乐用具 所有与这个标志性的标志相关联。您没有在问题陈述中调出许多其他案例,但我觉得它们对算法的成功至关重要。

这里的秘诀是确定什么是视觉特征 能够 包含或通过负空间,其他可用于罐头的可乐产品具有哪些特征。为此, 目前最好的答案 当且仅当“瓶子”未被识别时,通过瓶盖,液体或其他类似的视觉启发法的存在,勾画出选择“罐头”的基本方法。

问题是这会破裂。例如,瓶子可能是空的并且没有盖子,导致假阳性。或者,它可能是 一个部分瓶子 具有额外功能损坏,再次导致错误检测。毋庸置疑,这不是优雅的,也不是对我们的目的有效。

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

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

您的分类可能如下所示:

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

这在视觉上向用户突出显示检测到的内容,强调可能正确地被检测为损坏的罐头的弱阳性。

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

嘿,恭喜 黑客新闻发布! 总的来说,这是一个非常好的问题,值得它收到的宣传。 :)


41
2018-04-22 22:56



这是一个有趣的方法,至少值得一试,我真的很喜欢你对这个问题的推理 - Charles Menguy
这就是我的想法:不排除特定类型的误报。有关焦炭的更多特征的规则可以。但我想知道:你怎么做一个压扁的罐头?我的意思是,如果你踩到可乐,它仍然是可乐。但它不再具有相同的形状。或者问题AI-Complete? - Ian


看着形状

取一下罐子/瓶子红色部分的形状。注意瓶子的顶部是如何略微逐渐变细,而瓶子标签是直的。您可以通过比较红色部分的长度来区分这两者。

看着亮点

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

据我所知,这就是人类如何区分两种类型的标签。如果光照条件差,那么无论如何区分两者肯定存在一些不确定性。在这种情况下,您必须能够检测到透明/半透明瓶子本身的存在。


35
2018-04-16 08:31



我喜欢这个主意,但看起来你需要一些非常好的照明条件。例如,在罐子和瓶子中都有例子,这似乎有点难以区分。 - Charles Menguy
在你的例子中,请注意塑料标签的镜面反射是如何比罐头上的亮点更加分散?这就是你怎么说的。 - tskuzzy
我知道,在这种情况下,您将使用哪种颜色空间表示来捕获算法中的镜面反射?这似乎很难进入RGB或HSV - Charles Menguy
如果光源在罐子后面怎么办?我想你不会看到亮点。 - Rui Marques


请看看Zdenek Kalal's 捕食者跟踪器。它需要一些培训,但它可以主动了解被跟踪物体在不同方向和比例下的表现,并实时进行!

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

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


31
2018-04-17 20:56



感谢您看起来很有趣的链接。关于培训,培训组的规模是多少,以达到合理的结果是合理的?如果你在c#中实现了一个非常有用的实现! - Charles Menguy
在研究TLD时,我发现另一个用户在寻找C#实现 - 有没有理由不把你的工作放在Github上? stackoverflow.com/questions/29436719/... - spillner
注:多年以后,链接现已死亡 - G Forty


如果你不仅限于一个不在你的约束条件下的相机,也许你可以转向使用像Xbox这样的范围传感器 Kinect的。通过此功能,您可以执行基于深度和颜色的图像匹配分割。这允许更快地分离图像中的对象。然后,您可以使用ICP匹配或类似技术来匹配罐的形状,而不仅仅是其轮廓或颜色,并且假设它是圆柱形的,如果您对目标进行了先前的3D扫描,则这可能是任何方向的有效选项。这些技术通常非常快,特别是在用于解决速度问题的特定目的时。

我也可以建议,不一定是为了准确性或速度,但为了好玩,你可以在你的色调分割图像上使用训练有素的神经网络来识别罐子的形状。这些速度非常快,通常可达到80/90%的准确度。虽然您需要手动识别每个图像中的罐头,但培训将是一个漫长的过程。


25
2018-04-16 04:54



实际上我没有在帖子中解释这一点,但是对于这个任务我给了一组大约30张图像,并且必须做一个算法,在所描述的各种情况下都能匹配它们。当然,一些图像最终被用来测试算法。但我喜欢Kinect传感器的想法,我想更多地了解这个话题! - Charles Menguy
使用神经网络训练集的大小大致会产生令人满意的结果?这种方法的好处还在于我只需要一个模板来匹配几乎所有东西。 - Charles Menguy
如果您的图像集是预定义且有限的,那么只需要硬核完美的结果;) - sne11ius
是的,如果我在数据集上训练我将要运行算法,确定我会得到完美的结果:)但是例如对于这个任务,程序最终由老师在一组保持的图像上进行测试。我想做一些有力而且不适合训练数据的事情。 - Charles Menguy
这个答案充其量只是一个评论(“尝试使用Kinect”)。 - Fattie


我会检测到红色矩形:RGB - > HSV,滤红色 - >二进制图像,  (扩张然后侵蚀,被称为 imclose 在matlab中)

然后查看从大到小的矩形。在已知位置/比例下具有较小矩形的矩形都可以被移除(假设瓶子比例是恒定的,较小的矩形将是瓶盖)。

这将留下红色矩形,然后你需要以某种方式检测徽标,以告诉他们是红色矩形还是可乐。像OCR一样,但有一个已知的标志?


20
2018-04-16 06:34



像这样在DSP被移动的短时间内被讨论,一些瓶子可能没有插头;)或插头可能部分隐藏。 - Charles Menguy