有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

C++图像处理:“CyCalOLA CAN”识别算法改进

在过去的几年里,我参与的最有趣的项目之一是一个关于image processing的项目。我们的目标是开发一个能够识别可口可乐“罐头”的系统(注意,我在强调“罐头”一词,你马上就会明白原因)。您可以在下面看到一个示例,在带有缩放和旋转的绿色矩形中识别can

Template matching

对项目的一些限制:

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

因此,您可能会遇到类似这样的棘手问题(在本例中,我的算法完全失败):

Total fail

我不久前做过这个项目,做起来很有趣,我有一个不错的实现。以下是有关我的实施的一些详细信息:

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

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

  1. 将颜色域从RGB更改为HSV,并基于“红色”色调进行过滤,饱和度高于一定阈值以避免类似橙色的颜色,低值过滤以避免暗色调。最终的结果是一个二值黑白图像,其中所有白色像素将表示与该阈值匹配的像素。显然,图像中仍然有很多垃圾,但这减少了你必须处理的维度数量。 Binarized image
  2. 噪声过滤使用中值滤波(取所有邻居的中值像素值并用该值替换像素)来减少噪声
  3. 使用Canny Edge Detection Filter在两个先例步骤后获得所有项目的轮廓。 Contour detection

算法:我为这项任务选择的算法本身取自this一本关于特征提取的很棒的书,名为Generalized Hough Transform(与常规的Hough变换非常不同)。它基本上说了几件事:

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

最后,您将得到投票的热图,例如,在这里,can轮廓的所有像素将投票给其重力中心,因此您将在与中心对应的同一像素中拥有大量投票,并将在热图中看到一个峰值,如下所示:

GHT

一旦你有了这个,一个简单的基于阈值的启发式可以给你中心像素的位置,从中你可以得到缩放和旋转,然后在它周围画出你的小矩形(最终的缩放和旋转因子显然会相对于你的原始模板)。至少在理论上

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

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

您能帮助我改进我的特定的算法,使用专用OpenCV功能来解决所提到的四个特定的问题吗

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


共 (6) 个答案

  1. # 1 楼答案

    看形状

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

    查看亮点

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

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

  2. # 2 楼答案

    我真的很喜欢这个问题。我当时正在对这些问题发表评论,但我相信我的方法过于简单,不能不离开这里

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

    这里的秘密是确定包含哪些视觉特征,或者通过负空间确定罐中不存在的其他焦炭产品存在哪些特征。为此,the current top answer勾勒出了一个选择“罐头”的基本方法,当且仅当通过瓶盖、液体或其他类似的视觉启发法无法识别“瓶子”时

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

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

    • 物体轮廓的形状,如you sketched out in your question,是否正确?如果是的话,+1
    • 如果我们假设存在自然光或人造光,我们是否检测到瓶子上的铬轮廓,表明瓶子是否由铝制成?如果是的话,+1
    • 相对于我们的光源(illustrative video linklight source detection上),我们确定物体的specular properties是正确的吗?如果是的话,+1
    • 我们是否可以确定物体的任何其他属性,将其识别为罐头,包括但不限于徽标的拓扑图像倾斜、物体的方向、物体的并置(例如,在平面上,如桌子上或在其他罐头的上下文中)以及是否存在拉环?如果是,则每一个+1

    您的分类可能如下所示:

    • 对于每个候选匹配,如果检测到可口可乐徽标,则绘制灰色边框
    • 对于+2以上的每一场比赛,画一条红色边框

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

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

    嘿,祝贺你,总的来说,这是一个非常棒的问题,值得宣传

  3. # 3 楼答案

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

    Signature scan line

    在目标图像中搜索此签名是一个简单的问题,即以水平条扫描图像。在红色通道中查找高频(表示从红色区域移动到白色区域),一旦找到,查看是否跟随培训课程中确定的频率节奏。一旦找到匹配项,您将立即知道扫描线在徽标中的方向和位置(如果您在培训期间跟踪这些内容),因此从那里识别徽标的边界非常简单

    如果这不是一个线性高效的算法,或者说几乎如此,我会感到惊讶。很明显,这并不能解决你的易拉罐歧视问题,但至少你会有自己的标识

    (更新:对于瓶子识别,我会在标志旁边寻找可口可乐(棕色液体)——也就是说,瓶子内部。或者,在空瓶子的情况下,我会寻找一个瓶盖,它将始终具有相同的基本形状、大小和与徽标的距离,并且通常都是白色或红色。搜索一个纯色椭圆形状,其中相对于徽标,cap为。当然不是万无一失的,但是你在这里的目标应该是找到那些简单快速

    (我的图像处理时代已经过去几年了,所以我把这个建议保持在较高的层次和概念上。我认为它可能稍微接近人眼的运作方式——或者至少是我的大脑的运作方式!)

  4. # 4 楼答案

    另一种方法是使用scale-invariant feature transform(SIFT)或Speeded Up Robust Features(SURF)提取特征(关键点)

    您可以在本页的{}、{}和{}中找到一个不错的{}代码示例:{a3}

    这两种算法对缩放和旋转都是不变的。因为它们与功能一起工作,所以您还可以处理occlusion(只要有足够多的关键点可见)

    Enter image description here

    图片来源:教程示例

    SIFT的处理需要几百毫秒,SURF稍快一些,但不适合实时应用。ORB使用的FAST在旋转不变性方面较弱

    原始文件

  5. # 5 楼答案

    有趣的问题:当我瞥了一眼你的瓶子图像时,我还以为它也是一个罐头。但是,作为一个人类,我所做的区别是,我注意到它也是一个瓶子

    所以,要区分罐头和瓶子,先扫描瓶子怎么样?如果你找到了,在找罐头之前先把标签遮住

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

  6. # 6 楼答案

    即使人类在第二张图像中也很难区分瓶子和罐头(只要瓶子的透明区域是隐藏的)

    除了一个很小的区域外,它们几乎是一样的(也就是说,罐子顶部的宽度有点小,而瓶子的包装在整个过程中都是相同的宽度,但有一个微小的变化,对吗?)

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

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

    特别注意这一点,看看他们检测玻璃的准确度:

    见其实施结果:

    Enter image description here

    他们说这是文件的实施

    这可能对您的情况有点帮助,但如果瓶子装满了,问题又会出现

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

    Enter image description here

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

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

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

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