【发布时间】:2012-04-27 11:05:06
【问题描述】:
过去几年我参与的最有趣的项目之一是关于image processing 的项目。目标是开发一个能够识别可口可乐'cans'的系统(注意我强调的是'cans'这个词,你马上就会明白为什么)。您可以在下面看到一个示例,在 绿色矩形 中识别出罐头,并带有缩放和旋转。
项目的一些限制:
- 背景可能非常嘈杂。
- can 可以有任何比例 或旋转 甚至方向(在合理范围内)。
- 图像可能有一定程度的模糊(轮廓可能不完全笔直)。
- 图像中可能有可口可乐瓶,算法应该只检测到罐!
- 图像的亮度可能会有很大差异(因此您不能“过多地”依赖颜色检测)。
- 罐可以部分隐藏在侧面或中间,也可能部分隐藏在瓶子后面。
- 图像中可能根本没有 can,在这种情况下,您必须什么都找不到并写一条消息说。
所以你最终可能会遇到这样棘手的事情(在这种情况下,我的算法完全失败了):
我前段时间做过这个项目,做起来很有趣,而且我的实现也不错。以下是关于我的实现的一些细节:
语言:使用 OpenCV 库在 C++ 中完成。
预处理:对于图像预处理,即将图像转换为更原始的形式以提供给算法,我使用了两种方法:
- 将颜色域从 RGB 更改为HSV 并基于“红色”色调进行过滤,饱和度高于某个阈值以避免类似橙色的颜色,并过滤低值以避免暗色调。最终结果是二值黑白图像,其中所有白色像素都代表与此阈值匹配的像素。显然,图像中仍然有很多废话,但这减少了您必须处理的维度数量。
- 噪声过滤使用中值滤波(取所有邻居的中值像素值并以此值替换像素)来降低噪声。
- 使用Canny Edge Detection Filter 获取前两步后所有项目的轮廓。
算法:我为这项任务选择的算法本身取自this 很棒的关于特征提取的书,称为Generalized Hough Transform(与常规的霍夫变换完全不同)。它基本上说了几件事:
- 您可以在不知道其解析方程的情况下描述空间中的对象(这里就是这种情况)。
- 它可以抵抗缩放和旋转等图像变形,因为它基本上会针对缩放因子和旋转因子的每种组合测试您的图像。
- 它使用算法将“学习”的基本模型(模板)。
- 根据从模型中学到的信息,轮廓图像中剩余的每个像素都会投票给另一个像素,该像素应该是对象的中心(就重力而言)。
最后,你会得到一张投票的热图,例如这里的罐子轮廓的所有像素都会投票给它的重心,所以你会在同一个像素中有很多票对应于中心,并且会在热图中看到一个峰值,如下所示:
一旦你有了这个,一个简单的基于阈值的启发式可以给你中心像素的位置,你可以从中得出比例和旋转,然后在它周围绘制你的小矩形(最终的比例和旋转因子显然是相对于您的原始模板)。理论上至少...
结果:现在,虽然这种方法在基本情况下有效,但在某些方面严重不足:
- 它非常慢!我没有足够强调这一点。处理这 30 张测试图像几乎需要一整天的时间,显然是因为我有一个非常高的旋转和平移比例因子,因为有些罐子非常小。
- 当瓶子出现在图像中时它完全丢失了,并且由于某种原因几乎总是找到瓶子而不是罐子(可能是因为瓶子更大,因此像素更多,因此投票更多)
- 模糊图像也不好,因为投票在中心周围的随机位置以像素形式结束,因此以非常嘈杂的热图结束。
- 实现了平移和旋转不变,但方向不变,这意味着无法识别未直接面对相机目标的罐头。
您能帮我改进我的特定算法,使用OpenCV功能解决上述四个特定问题吗?
我希望有些人也能从中学到一些东西,毕竟我认为不仅仅是提问的人应该学习。 :)
【问题讨论】:
-
可能会说这个问题在 dsp.stackexchange.com 或 stats.stackexchange.com 上更合适,您当然也应该考虑在这些网站上重新提问。
-
@stacker 提出了一个很好的观点。为了速度,您希望获得计算成本低廉的功能,例如定向梯度的直方图。一个非常幼稚的第一种方法是在一些训练图像中手动标记一堆罐头矩形,并使用这些加上随机负样本来训练 SVM 或决策树分类器。训练将花费更长的时间,但对新图像的执行会快得多。当我有更多空闲时间来包含正确的参考时,我计划编写此方法。
-
类似reCAPTCHA的方法怎么样? ;)
-
为什么从dsp.stackexchange.com 移出?似乎该站点比stackoverflow更适合o_O
标签: c++ algorithm image-processing opencv