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

项目的一些限制:

背景可能非常嘈杂。罐可以有任何刻度或旋转,甚至可以有方向(在合理的范围内)。图像可能具有一定程度的模糊性(轮廓可能不完全笔直)。图像中可能有可口可乐瓶子,算法应该只检测到罐子!图像的亮度可能会有很大的变化(所以你不能“太依赖”颜色检测)。罐子可以部分隐藏在侧面或中间,也可能部分隐藏在瓶子后面。图像中可能根本就没有罐头,在这种情况下,你必须什么都找不到,然后写一条消息这样说。

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

我不久前做过这个项目,做得很开心,我有一个不错的实现。以下是关于我的实现的一些细节:

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

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

将颜色域从RGB更改为HSV,并基于“红色”色调进行过滤,饱和度高于一定阈值以避免类似橙色的颜色,低值过滤以避免暗色调。最终的结果是一个黑白二值图像,其中所有的白色像素都将表示符合此阈值的像素。显然,图像中仍然有很多垃圾,但这减少了您必须处理的维度的数量。使用中值滤波(取所有邻居的中值像素值并用该值替换像素)进行噪声滤波,以减少噪声。使用Canny边缘检测滤波器在两个前一步骤后获得所有项目的轮廓。

算法:我为这项任务选择的算法本身取自这本关于特征提取的很棒的书,称为广义霍夫变换(与常规霍夫变换截然不同)。它基本上说了几件事:

你可以在不知道其解析方程的情况下描述空间中的物体(这里就是这种情况)。它可以抵抗图像变形,例如缩放和旋转,因为它基本上会测试图像的缩放因子和旋转因子的每一种组合。它使用算法将“学习”的基础模型(模板)。轮廓图像中剩余的每个像素将根据从模型中获得的信息,投票给另一个像素,该像素可能是对象的中心(按重力计算)。

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

一旦你做到了这一点,一个简单的基于阈值的启发式方法可以为你提供中心像素的位置,你可以从中导出缩放和旋转,然后围绕它绘制你的小矩形(最终的缩放和旋转因子显然是相对于你的原始模板的)。至少在理论上。。。

结果:现在,虽然这种方法在基本案例中有效,但在某些领域严重缺乏:

它非常慢!我没有充分强调这一点。几乎需要整整一天的时间来处理30张测试图像,显然是因为我的旋转和平移比例非常高,因为有些罐子非常小。当瓶子出现在图像中时,它完全丢失了,出于某种原因,几乎总是找到瓶子而不是罐子(可能是因为瓶子更大,因此像素更多,因此投票更多)模糊图像也不好,因为投票结果以像素形式出现在中心周围的随机位置,从而以非常嘈杂的热图结束。在平移和旋转方面实现了差异,但在方向上没有,这意味着没有直接面对摄像机目标的罐子无法被识别。

你能帮我改进我的特定算法吗,专门使用OpenCV特性,来解决上面提到的四个特定问题吗?

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


当前回答

我喜欢你的问题,不管它是否离题:P

有趣的旁白;我刚刚完成了我学位上的一门课程,我们学习了机器人和计算机视觉。我们这学期的项目与你描述的非常相似。

我们不得不开发一种机器人,它使用Xbox Kinect在各种照明和环境条件下检测任何方向的可乐瓶和可乐罐。我们的解决方案包括在色调通道上使用带通滤波器,并结合霍夫圆变换。我们能够稍微限制环境(我们可以选择机器人和Kinect传感器的位置和方式),否则我们将使用SIFT或SURF变换。

您可以在我的博客文章中阅读我们的方法,主题为:)

其他回答

查看形状

看看罐子/瓶子红色部分的形状。请注意,罐的顶部略微变细,而瓶的标签是直的。您可以通过比较红色部分的宽度和长度来区分这两者。

查看亮点

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

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

我喜欢这个挑战,并想给出一个答案,这样可以解决问题。

提取标志的特征(关键点、SIFT、SURF等描述符)将点与徽标的模型图像匹配(使用Matcher,如Brute Force)估计刚体的坐标(PnP问题-SolvePnP)根据刚体估计盖的位置进行反投影并计算瓶盖的图像像素位置(ROI)(我假设你有相机的固有参数)用方法检查盖子是否存在。如果有,那么这就是瓶子

检测瓶盖是另一个问题。它可以是复杂的,也可以是简单的。如果我是你,我会简单地检查ROI中的颜色直方图,以便做出简单的决定。

如果我错了,请给出反馈。谢谢

作为所有这些好解决方案的替代方案,您可以训练自己的分类器,并使应用程序对错误具有鲁棒性。例如,您可以使用Haar Training,为目标提供大量正面和负面图像。

仅提取罐是有用的,并且可以与透明物体的检测相结合。

请看一下Zdenek Kalal的捕食者跟踪器。它需要一些训练,但它可以主动学习被跟踪对象在不同方向和尺度上的外观,并实时进行操作!

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

如果你对我的跟踪器的C#实现感兴趣,欢迎提问。

我首先要寻找的是颜色-像红色,当在图像中进行红眼检测时-有一个特定的颜色范围需要检测,考虑到周围区域,例如如果图像中确实可见,与另一只眼睛的距离。

1:第一个特点是颜色,红色非常占优势。在检测到可口可乐红之后,有几个项目值得关注1A:这个红色区域有多大(它有足够的数量来确定一个真正的罐子是否正确-10个像素可能不够),1B:它包含标签的颜色吗?“可口可乐”或波浪。1B1:是否有足够的理由认为它是一个标签。

第1项是一种捷径-如果图像中不存在,请继续。

因此,如果是这样的话,我可以利用我的图像片段,开始稍微缩小问题区域——基本上看周围区域/边缘。。。

2:给定上述图像区域ID为1-验证所讨论项目的周围点[边缘]。A: 有什么看起来像是罐顶或罐底的银吗?B: 瓶子可能看起来是透明的,但玻璃桌也可能是透明的-玻璃桌/架子或透明区域也是如此-如果是这样的话,可能会有多个出口。瓶子可能有一个红色的盖子,它可能没有,但它应该有瓶盖/螺纹螺钉的形状,或者盖子。C: 即使这失败了A和B,它仍然可以是部分的。。当它是部分的时,这会更复杂,因为部分瓶/部分罐看起来可能相同,所以需要对红色区域边缘到边缘的测量进行更多的处理。。小瓶子的大小可能差不多。。

3:经过上述分析后,也就是我会看字母和波浪标志的时候-因为我可以定位搜索单词中的一些字母,因为你可能没有所有的文字,因为没有所有的罐子,波浪将在某些点与文本对齐(距离方向),这样我就可以搜索概率,并知道在距离x处波浪的那个点应该存在哪些字母。