2D物体识别方法——LINE-2D

line-2D是line-mod中的一个子模块,把line-mod的3D模态(modality)剔除,即只用2D图像制作模板,进行物体匹配就是line-2d,该方法的基本思想是根据图像的轮廓和梯度信息,通过经典的相似度计算公式(1)计算相似度进行的模板匹配,其巧妙之处在于:1)运用2进制位表示量化的梯度方向,并分别对搜索图像计算每个量化方向的响应图像,从而将公式(1)匹配相似度的计算过程,转化成查找表的过程,大大提高了计算相似度的效率;2)通过扩散方向(spread orientation)的方法,将邻域内的不同像素位置的梯度方向都统计到锚点像素中,从而提高了匹配过程对微小位置和旋转的鲁棒性;3)通过线性存储的数据组织方式,提高匹配过程的查找速度。
这里写图片描述(1)

主要思想说明

1. 二进制化梯度方向

图像原始的梯度方向可通过sobel算法计算得到,计算后的梯度方向是0~360°范围,该方法将梯度方向离散成8个方向,并用一个字节的数据表示八个梯度方向,如下图左1所示。只保留了方位信息去除了方向信息(主要区别这里的方位和方向,解释可能有点不到位原文中是用orientation和 direction,direction在这里特指方向的正方向),这种表示梯度方位的方法,简化了梯度的表示的信息量,为后面实现查找表的方向进行匹配做准备(因为只有8个方向,使得后面对搜索图像计算对各方向的梯度相应成为可能)。量化梯度信息,导致很多细节信息的丢失,必然导致很容易出现错误识别,为了弥补这一不足,作者对一定大小的领域内的所有位置处的量化后的梯度方向进行统计,同一方位超过一定数量的才作为备选特征点。

2. 扩散方向

为了提高对小移动或者旋转的稳定,line-2d采用扩散方向的方法表示某个特征的点的方位信息,具体做法:量化图像的梯度方位后,将T领域内的周边像素点的梯度方位都统计到锚点像素中,如下图a)→b)→c)所示。从这步就可以体会到用二进制表示梯度方位的好处了,仅用一个数就表示了领域内所有像素点的梯度方位。
这里写图片描述

图1 梯度方向量化及扩散

3. 计算梯度响应

如下图所示,计算梯度响应的过程实际上就是对量化梯度方位及扩散方位后的搜索图像分别计算8个梯度方向的响应图像,这里的响应图像就是对搜索图像每个像素进行遍历,计算每个像素的方位值同8个梯度方向的相似度,计算相似度的方法如式(2)所示,并分别保存成八幅响应图像。对模板进行匹配时,只需要在对应的对应的像素位置,根据模板中的梯度方向查询对应的匹配值即可。

这里写图片描述

图2 扩散方向的过程

这里写图片描述 (2)

其中:L表示搜索图像中某个像素点中的所有梯度方位。

4. 线性存储的方法匹配相似度

计算机在访问数据时为了提高速度被设计成是批量读取的,为了较少查询过程中读取数据的次数,提高查询的速度该方法用线性存储的方式重新组织梯度响应图形的存储方式。如图3所示,对于具体的操作,我也理解得不是很透彻,这里贴个图,详细的说明可以看参考资料[1]
这里写图片描述

总结该方法的优点与不足:

优点:
1. 匹配速度快,测试中500W像素的图片,只用两层图像金字塔,360个模板的匹配速度可以达到0.3s左右(pc配置:i7/4GRAM,无GPU加速)。
2. 匹配速度基本上跟模板的数量无关。所以在作者文章中用3000个模板查找一副VGA图像差不多只要0.1s左右时间。
不足:
1. 算法对硬件及处理图片尺寸的兼容性差,主要原因是线性存储的方法,对于不同的计算机硬件和不同尺寸的图像,需要设定不同的参数,且设定值不是很直观,需要有较好的硬件基础才行。
2. 只能做到像素级的定位,定位精度不高。
3. 对梯度方向的量化成都过大(360°量化成了8个角度)导致对环境噪声的干扰的稳定较差,在环境比较混乱的情况下容易出现误识别。(这里line-mod对环境的干扰鲁棒性是很高的,因为加入了深度信息)

算法代码获取方法:

网上没找到有line-2d的现成的源码,通常给的都是line-mod的代码,line-mod方法需要图片需具备深度信息,目前我所知道的只有kinect可以获取这样的图片,这使得该方法的应用场景很有限。但其实只要稍加改造,就可以将line-mod源码移植到2D图像的物体识别和定位上。opencv中已经实现了line-mod方法,但由于该算法目前还不够稳定,还没有被编入官方的库中,但在opencv contrib的rgbd模块中实现了该方法。opencv contrib需要用cmake编译后才能用,具体的下载地址和编译方法请自行到网上自行搜索。
注:亲测源码还是有很多bug的,比如对搜索图像进行扩散方向操作时,选用的领域的大小需根据图像的大小进行调整;只能对图像进行两层金字塔操作,超过两层就会报错;用于匹配的特征最大不能超过63个等问问题。而且代码易读性不高,改造难度比较大,建议只作为辅助算法理解用。

使用说明

如果只想看看line-mod这种方法的运行效果,只需要用cmake编译下opencv,把rgbd这个模块加进去就行,但如果要对其进行改造,或者调试其内部函数的运行过程,还需要以下几步操作:
1. 将module下的rgbd文件中的所有头文件和源文件都拷贝到自己的工程目录下:
这里写图片描述
并将这些文件添加到自己的工程中。

  1. 将这些文件中的包含的rgbd.hpp和linemod.hpp的头文件都修改成自己的工程中的头文件。

  2. 配置opencv的属性表;

  3. 解决如下的错误提示
    这里写图片描述
    解决方法:private.hpp这个文件没什么用,把包含这个头文件的地方注释掉即可
    这里写图片描述
    好了,现在可以运行代码进行调试了。

2D识别改造效果

工业场景中,对物体的识别和定位,通常是将物体限定在一个平面上的,即物体的通常只有一个旋转自由度,对于这样的场景,通常的做法是通过制作物体在这个旋转自由度内360度的模板来解决匹配中的旋转问题。上述的源码中要实现对这种情况的物体的检测,需要拍摄物体在360度范围内不同角度的足够多的图片制作模板才行,但其实只要做个简单的修改就可以省掉这些繁琐的过程,只要一张图片就可以实现对360旋转的物体进行识别。方法:用单张图片提取特征后,对这些特征点和向量进行360度旋转,生成360的模板即可:
下图是亲测改造后的识别效果:

参考资料

论文:
[1] Gradient Response Maps for Real-Time Detection of Textureless Objects
[2] Multimodal Templates for Real-Time Detection of Texture-less Objects in Heavily Cluttered Scenes
[3]Model based training, detection and pose estimation of texture-less 3D objects in heavily cluttered scenes

Stefan大神的个人主页:http://campar.in.tum.de/Main/StefanHinterstoisser

写在最后

这个算法的原理并不复杂,稍加理解就能体会其思想,主要难度在于编程,要把这个算法实现出来,并且达到作者文章中提到的效果,难度很大,自己也尝试着写了下,效果很差,识别需要5、6秒的时间,真是惨不忍睹。

猜你喜欢

转载自blog.csdn.net/j_shui/article/details/77267897
2D