c++ - 图像处理 : Algorithm Improvement for 'Coca-Cola Can' Recognition

标签 c++ algorithm image-processing opencv

在过去的几年里,我参与过的最有趣的项目之一是关于 image processing 的项目。 .目标是开发一个能够识别可口可乐的系统 ' jar ' (请注意,我在强调“ jar 头”这个词,稍后您就会明白为什么)。您可以在下面看到一个示例,在带有缩放和旋转的绿色矩形中识别出 jar 头。

Template matching

对项目的一些限制:

  • 背景可能非常嘈杂。
  • jar 可以有任何比例或旋转,甚至方向(在合理的范围内)。
  • 图像可能有一定程度的模糊性(轮廓可能不完全是直的)。
  • 图像中可能有可口可乐瓶,算法应该只检测 jar !
  • 图像的亮度可能会有很大差异(因此您不能“过分”依赖颜色检测)。
  • jar 可以部分隐藏在侧面或中间,也可能部分隐藏在瓶子后面。
  • 图像中可能根本没有 jar 头,在这种情况下,您必须一无所获并写下这样的消息。

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

    Total fail

    不久前我做了这个项目,并且从中获得了很多乐趣,而且我有一个不错的实现。以下是有关我的实现的一些详细信息:

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

    预处理 :对于图像预处理,即将图像转换为更原始的形式以提供给算法,我使用了两种方法:
  • 将色域从 RGB 更改为 HSV以及基于“红色”色调的过滤,高于一定阈值的饱和度以避免类似橙色的颜色,以及低值过滤以避免暗色调。最终结果是一个二进制黑白图像,其中所有白色像素将代表与此阈值匹配的像素。显然,图像中仍然有很多废话,但这减少了您必须使用的维度数量。
    Binarized image
  • 噪声过滤使用中值滤波(取所有邻居的中值像素值并用该值替换像素)来减少噪声。
  • 使用 Canny Edge Detection Filter在 2 个先行步骤后获得所有项目的轮廓。
    Contour detection

  • 算法 :我为此任务选择的算法本身取自 this关于特征提取的很棒的书,名为 Generalized Hough Transform (与常规的霍夫变换非常不同)。它基本上说了几件事:
  • 您可以在不知道解析方程的情况下描述空间中的物体(这里就是这种情况)。
  • 它可以抵抗缩放和旋转等图像变形,因为它基本上会针对缩放因子和旋转因子的每种组合测试您的图像。
  • 它使用算法将“学习”的基本模型(模板)。
  • 轮廓图像中剩余的每个像素都将根据它从模型中学到的知识为另一个像素投票,该像素应该是对象的中心(就重力而言)。

  • 最后,你会得到一张选票的热图,例如这里 jar 轮廓的所有像素都会投票给它的重心,所以你会在同一个像素对应的中心,并将在热图中看到一个峰值,如下所示:

    GHT

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

    结果 :现在,虽然这种方法在基本情况下有效,但在某些领域严重缺乏:
  • 极慢 !我强调的还不够多。处理这 30 个测试图像几乎需要一整天的时间,这显然是因为我的旋转和平移缩放因子非常高,因为有些 jar 非常小。
  • 当瓶子出现在图像中时它完全丢失了,并且由于某种原因几乎总是找到瓶子而不是 jar (可能是因为瓶子更大,因此像素更多,因此投票更多)
  • 模糊图像也不好,因为投票以中心周围随机位置的像素结束,因此以非常嘈杂的热图结束。
  • 实现了平移和旋转的不变性,但在方向上没有实现,这意味着没有识别出不直接面向相机目标的 jar 。

  • 你能帮我改进我的具体 算法,使用 独家 OpenCV 功能,解决四具体提到的问题?

    我也希望有的人也能从中学到一些东西,毕竟我觉得不是只有提问的人才会学。 :)

    最佳答案

    另一种方法是使用 scale-invariant feature transform 提取特征(关键点)。 (SIFT) 或 Speeded Up Robust Features (冲浪)。
    你可以找到一个不错的OpenCV Java 中的代码示例, C++ , 和 Python本页:Features2D + Homography to find a known object
    这两种算法对于缩放和旋转都是不变的。由于它们与功能一起使用,您还可以处理 occlusion (只要有足够多的关键点可见)。
    Enter image description here
    图片来源:教程示例
    SIFT 的处理需要几百毫秒,SURF 更快一些,但不适合实时应用。 ORB 使用 FAST,它在旋转不变性方面较弱。
    原始论文

  • SURF: Speeded Up Robust Features
  • Distinctive Image Features from Scale-Invariant Keypoints
  • ORB: an efficient alternative to SIFT or SURF
  • 关于c++ - 图像处理 : Algorithm Improvement for 'Coca-Cola Can' Recognition,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10168686/

    相关文章:

    c++ - Google 测试中的 BOOST_CHECK_EQUAL_COLLECTIONS

    python - 两种算法的效率比较 : Find the number of negative integers in a row-wise/column-wise sorted matrix

    c++ - 将 n 位从 8 位数组复制到 64 位整数?

    algorithm - 通过算法在卡坦岛游戏中寻找最长的道路

    android - 从可绘制文件夹加载图像时通用图像加载器 OOM?

    matlab - matlab 中的 3x3 平均滤波器

    c++ - 将 OpenCV 构建为项目的一部分 - 调试 (F11) 到 OpenCV 库

    c++ - 使用 cstrings 时未处理的异常

    c++ - 如何使用 Visual Studio 2012 显示构造函数声明?

    image-processing - 如何使ImageTransformation产生图像的变形版本