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

项目的一些限制:

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

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

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

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

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

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

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

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

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

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

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

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

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

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


当前回答

我不知道OpenCV,但从逻辑上看,我认为你可以通过改变你正在寻找的形象,即可口可乐,来区分瓶子和罐头。你应该一直到罐的顶部,因为如果是罐,可口可乐顶部有银色衬里,而如果是瓶子,则没有银色衬里。

但显然,这种算法在罐头顶部隐藏的情况下会失败,但在这种情况下,即使是人类也无法区分两者(如果只有可乐瓶/罐头的可口可乐部分可见)

其他回答

我回答这个问题晚了几年。在过去的5年里,CNN将最先进的技术推向了极限,我现在不会使用OpenCV来完成这项任务了!(我知道你在这个问题中特别想要OpenCv功能)我觉得与OpenCv功能相比,更快的RCNN、YOLO、SSD等对象检测算法将以显著的优势解决这个问题。如果我现在(6年后)解决这个问题,我肯定会使用更快的RCNN。

如果您对它的实时性感兴趣,那么您需要添加一个预处理过滤器,以确定哪些内容会被重负荷扫描。一个很好的快速、非常实时的预处理过滤器,它可以让你扫描更可能是可口可乐罐的东西,然后再移动到更棘手的东西上,它是这样的:在图像中搜索与可口可乐罐sqrt(pow(红色,2)+pow(蓝色,2)+pow(绿色,2))有一定公差的最大色块。从非常严格的颜色容差开始,然后逐步降低到更宽松的颜色容差。然后,当您的机器人在处理当前帧的分配时间内用完时,它会将当前找到的瓶子用于您的目的。请注意,您必须调整sqrt中的RGB颜色(pow(红色,2)+pow(蓝色,2)+pow(绿色,2)),以使其恰到好处。

此外,这看起来真的很愚蠢,但在编译C代码时,是否确保启用了-oFast编译器优化?

MVTec有一个名为HALCON的计算机视觉软件包,它的演示可以为您提供好的算法想法。有很多与您的问题类似的示例,您可以在演示模式下运行,然后查看代码中的运算符,看看如何从现有的OpenCV运算符实现它们。

我已经使用这个软件包为类似这样的问题快速原型化复杂的算法,然后找到如何使用现有的OpenCV特性实现它们。特别是对于您的情况,您可以尝试在OpenCV中实现嵌入在运算符find_scaled_shape_model中的功能。一些运营商指出,这篇关于算法实现的科学论文有助于找出如何在OpenCV中做类似的事情。

我真的很喜欢达伦·库克和斯塔克对这个问题的回答。我当时正在对这些问题发表评论,但我认为我的方法太过简单,不能离开这里。

简而言之,您已经确定了一种算法,以确定可口可乐标志是否存在于空间中的特定位置。现在,您正在尝试确定一个适合于区分可口可乐罐和其他物体的启发式方法,包括:瓶子、广告牌、广告和可口可乐用具,所有这些都与这个标志性标志相关。在你的问题陈述中,你没有提到很多这些额外的案例,但我觉得它们对你的算法的成功至关重要。

这里的秘密是确定一个罐包含哪些视觉特征,或者通过负空间,确定其他可乐产品存在哪些不存在于罐中的特征。为此,当前的顶级答案勾勒出了一个选择“可以”的基本方法,如果且仅当“瓶子”未被识别时,可以通过瓶盖、液体或其他类似的视觉启发法进行识别。

问题是这种故障。例如,一个瓶子可能是空的,没有盖子,导致假阳性。或者,它可能是一个部分瓶子,额外的特征被破坏,再次导致错误检测。不用说,这并不优雅,也不符合我们的目的。

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

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

您的分类可能如下所示:

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

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

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

嘿,恭喜黑客新闻发布!总的来说,这是一个非常棒的问题,值得宣传

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

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

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

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