LineMod源码梳理

LineMod算法

代码来源:https://github.com/meiqua/shape_based_matching

一、总体结构说明

1、Feature结构体描述了一个特征点,即(x,y)位置,以及其量化梯度的方向(在代码中,将方向量化为8个)

2、Template结构体描述了一个模板,保存了模板的缩放大小(width,height),对应的金字塔层级(pyramid_level),以及特征序列(features)。

3、shapeInfo_producer类描述了模板的预处理,用于对模板图像进行旋转、缩放等操作,并记录每次操作的具体信息(旋转角度、缩放步长、类别等)。

4、ColorGradientPyramid类描述了制作模板的必要步骤,提供了“量化”接口、“提取模板”接口,“金字塔下采样”接口,特征点选择策略。该类分别被ColorGradientPyramid和DepthNormalPyramid继承,外部都不可见。

5、Match类描述了一个有效的模板匹配,包含了匹配的位置,类别(代码一般类别只有一个,暂时还没有多个类别的检测)、特征点相似度排序算法以及相应的模板信息(id)。

6、Detector类是最重要的类,包含添加模板、匹配等一系列操作。其中匹配函数现在底层金字塔进行全局匹配,后来在顶层金字塔局部细化匹配。即先低分辨率匹配,高分辨率局部相对精细匹配。


二、算法流程说明

模板特征点选取→保存信息→ 待测图片特征点选取→计算响应图→ 线性存储→ 与模板进行相似度计算

以scale_test为例

1、定义需要提取的特征点数量

在这里插入图片描述
2、创建Detector对象detector,输入特征点数和金字塔尺度数据,在这个例子中,只做两层
在这里插入图片描述
构造函数展开
在这里插入图片描述


Train部分

输入模板图片后生成 shapInfo_producer对象shapes,定义好旋转和缩放的范围即尺度。

调用shapes.produce_infos()来对信息进行存储。

调用shapes.src_of()来对模板进行相应的操作,并添加到detector.addTemplate()中。
在这里插入图片描述

构造函数展开
在这里插入图片描述

addTemplate()函数参数解释
在这里插入图片描述
addTemplate()函数解释:主要作用为提取模板图像的特征点,即梯度较强的点,得到 这些点的坐标和梯度方向值。

a. modality→process()构建ColorGradientPyramid对象,计算出图像的梯度信息

b. 对金字塔的每一层extractTemplate提取梯度较强的特征点

c. cropTemplate()特征点坐标调整
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
回到Train中,后续就是保存templates,将模板的信息,包括特征点的信息、图像金字塔层数、图像尺寸写在yaml格式文件中,接着保存infos(似乎没啥用,就是保存一些有效模板的旋转缩放信息),同样写在yaml中。

至此 Train结束。主要是对模板进行金字塔降采样,旋转缩放,根据策略选择特征点并保存。


Test部分

先定义标识
在这里插入图片描述

读取train阶段保存的模板信息。
在这里插入图片描述
输入待检测图像,并重新调整图像大小,应该将图像的weight和height设定为32的倍数,至少也得是16的倍数,方便做图像金字塔
在这里插入图片描述
接下来开始匹配计算,注意,阈值90是相似度评分为90
在这里插入图片描述
detector.match()函数展开解释

a. 先调用modality→process()构造一个ColorGradientPyramid对象,对图像计算量化后的梯度信息

b. 遍历图像金字塔,构建响应图(construct resopnse map),包括梯度方向扩散spread、梯度响应计算computeResponseMaps、线性化存储linearize。最终存储在LinearMemoryPyramid结构中。
在这里插入图片描述
在这里插入图片描述
在Match类中最重要的是重载了操作符号’<’。按照相似度排序,否则按照template_id(特征点的提取顺序)排序。

回到detector.match()函数中
在这里插入图片描述
类似于模板的梯度计算,计算待测图像的量化梯度方向,并保存在 std::vector<Ptr> quantizers中。
在这里插入图片描述

定义响应图大小,需要对每一层金字塔图像都进行响应图计算,一共有8个量化方向,因此每一层都需要8张响应图
在这里插入图片描述

关键函数:pyrDown(),定义了每一层金字塔的图像特征个数,调用update(),和Train过程一致,见上。
在这里插入图片描述

接着调用spread进行方向扩散
在这里插入图片描述
输入参数:原始图、扩散后的存储图、金字塔缩放尺度
在这里插入图片描述
orUnaligned8U()函数展开
在这里插入图片描述
总之是一个扩散过程,虽然过程还不是很懂,但似乎不像是从中心开始扩散,更像是从左上角开始,然后mipp这个也没懂,工程中还包含了一些关于mipp的头文件,像是作者自己写的一些计算优化的东西。

接着计算响应图
在这里插入图片描述
同样内部也是用了mipp之类的东西,只能参考一下网上的理解

这个地方 把论文中的相似度 也给离散化了。
并且事先计算了 某个方向 和 某组方向的余弦值的最大值,并且离散化, (或者称为根据余弦值 实行打分制) 存储到一个数组SIMILARITY_LUT 中,即查找表。 这个查找表中针对某个方向的值有32个元素, 总共8个方向, 所以有 256个元素。 32个元素中 , 又分为两组, 前16个是8个方向中前4个方向的各种组合 与 当前32个元素针对的方向 的余弦值的最大值对应的得分。
————————————————
版权声明:本文为CSDN博主「haithink」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/haithink/article/details/88396670

将响应图进行线性存储
在这里插入图片描述
在这里插入图片描述
这个是改变存储方式,外部两层循环用于定位,内部两层循环用于替换值。先行后列, 间隔T读取,然后写入。
最后调用matchClass()函数完成匹配过程
在这里插入图片描述
首先在金字塔底层进行粗匹配。目前是最高支持8192个特征点,关键函数similarity_64()
在这里插入图片描述
在函数similarity_64()中,对底层金字塔图像进行调整,依据搜索框大小划定搜索范围。利用模板在图像上进行覆盖滑窗,所以产生了 similarity map。 每次滑动,模板和图像产生一个相似度。模板在水平和垂直方向进行滑动, 所以 产生一个 二维的相似度矩阵。这个矩阵的宽自然就是图像的宽减去模板的宽, 也就是代码中的span_x。 高的情况类似。
在这里插入图片描述

在计算时候,最好的情况是所有匹配都是最大值4,而8bit的图像最大值是255,因此只能限定63个特征点。但是现在这个版本可以支持8192个了。

但是这里并不涉及模板窗口的滑动操作,只是进行线性化寻址获得响应值。
在这里插入图片描述

展开accessLinearMemory()函数 首先是根据标签定位到是哪个线性存储结构,根据特征点坐标直接找到线性存储的值。

accesslinearmemory 输入是输入图片的最底层 ,对于一个feature(x,y,ori),找到原input图在这个位置上对于这个方向的响应。

具体操作:response图在这里已经被重新调整大小,首先通过feature的方向确定第一个子图,然后原图片相当于被划分成立H/T * W/T 个区域,每个区域的大小是TT。首先通过对T取余数,找到在区域中的位置,然后再确定是哪一个grid(x除以T取整),因为矩阵大小实际是T^2(H/T * W/T),所以只需要行指针加上列指针,便可确定位置。
在这里插入图片描述
回到similarity_64()函数。将所有区域的相似度拼接在一起,即可获得相似图。
在这里插入图片描述
得到了最底层金字塔图像的相似图之后,需要遍历所有的像素点,确定值是否大于阈值。符合要求的则进入候选特征点。
在这里插入图片描述
接着将提取的特征点进入上一层金字塔图像,进行进一步的定位计算。
在这里插入图片描述
计算局部相似度,得到局部的相似度之后不再是根据阈值筛选,而是找相似度最大的点,然后加入到候选特征点中,下一层再从这个最大点周围去算similarity。
在这里插入图片描述在这里插入图片描述
最后对候选特征点的相似度进行阈值过滤,小于阈值的直接抛弃。
在这里插入图片描述
至此,已获得所有的最佳特征点。

回到大的流程中。开始输出特征点的坐标信息,并在图中绘制出来。
在这里插入图片描述在这里插入图片描述

至此结束。

总的来说,代码的思路还是比较清晰的,有些地方可能是能力有限,理解起来比较困难。比如一些SSE计算加速过程,mipp的使用什么的,可能需要进一步的阅读。这篇文章写得还是有点乱,我的想法是遇到一个核心就先展开解释一下,但往往这个函数比较大,讲完了就很难和前面的再续起来,这个也是我以后需要改进的地方。

这个源码主要将缩放、旋转和噪声的检测分成了三块。
在这里插入图片描述

  • 8
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值