orb_slam2源码分析与优化(1)——角点检测与描述子计算
2016-08-07 05:12
483 查看
这一部分相对比较简单,主要用到opencv的cv::FAST()函数。
文件:ORBextractor.cc
初始化过程除了必要的赋值以外,还主要做了3件事,(1)将总的特征数在不同的金字塔曾进行分配,而分配依据是尺度因子(作者默认为1.2,并不知道为什么是这个),然后层数越高特征数越少。所有层加起来就是指定的特征数。(2)将代码里面的sample复制。(3)计算patch里面的v的最大u,这里变量为umax。后两者都是为计算描述子做准备。
然后是计算金字塔,对尺度因子累乘就行了。
接下来角点检测。循环检测每一层金字塔,划分一定大小的patch,对每个patch进行角点检测,这里直接采用的cv::FAST。需要注意的是,代码里有两个FAST阈值,当大阈值检测不出来时换小阈值。其实,可以考虑自适应。
很多时候图像的容易集中在某个局部,另外有很大一部区域角点很稀疏,这样计算出来的描述子很不理想,为了让角点分布更均匀合理,这里运用四叉树算法对角点进行再分布。将图像以中点为远点划分为四个象限:
然后分别查看每个象限里面包含的特征点数,如果特征点数大于1,则在该象限继续划分,直到特征点数为1,这样自然会有很多没有特征点的叶子,直接去掉,然后将特征点重新进行分配:
当特征点全部分配之后循环结束。
当然,计算出来的特征点的位置是不准确的,因为之前为了避免计算到图像外面,做了切边保护,重新计算特征点的绝对位置:
然后是质心法计算特征点的角度,这里要用到前面初始化的umax。具体过程参考ORB算法,这里没有做任何改变。
然后是逐金字塔逐特征点地计算描述子,对于单个特征点,其32位描述子由以下计算出来:
至此,第一阶段完成。
效果:
文件:ORBextractor.cc
初始化过程除了必要的赋值以外,还主要做了3件事,(1)将总的特征数在不同的金字塔曾进行分配,而分配依据是尺度因子(作者默认为1.2,并不知道为什么是这个),然后层数越高特征数越少。所有层加起来就是指定的特征数。(2)将代码里面的sample复制。(3)计算patch里面的v的最大u,这里变量为umax。后两者都是为计算描述子做准备。
然后是计算金字塔,对尺度因子累乘就行了。
接下来角点检测。循环检测每一层金字塔,划分一定大小的patch,对每个patch进行角点检测,这里直接采用的cv::FAST。需要注意的是,代码里有两个FAST阈值,当大阈值检测不出来时换小阈值。其实,可以考虑自适应。
// 如果检测到的fast特征为空,则降低阈值再进行检测 if (vec_keys_cell.empty()) { cv::FAST(vec_image_pyramid_[level].rowRange(ini_y, max_y).colRange(ini_x, max_x), vec_keys_cell, min_fast_threshold_, true); }
很多时候图像的容易集中在某个局部,另外有很大一部区域角点很稀疏,这样计算出来的描述子很不理想,为了让角点分布更均匀合理,这里运用四叉树算法对角点进行再分布。将图像以中点为远点划分为四个象限:
ni.UL_ = cv::Point2i(interval_x*static_cast<float>(i), 0); ni.UR_ = cv::Point2i(interval_x*static_cast<float>(i + 1), 0); ni.BL_ = cv::Point2i(ni.UL_.x, max_y - min_y); ni.BR_ = cv::Point2i(ni.UR_.x, max_y - min_y);
然后分别查看每个象限里面包含的特征点数,如果特征点数大于1,则在该象限继续划分,直到特征点数为1,这样自然会有很多没有特征点的叶子,直接去掉,然后将特征点重新进行分配:
for (size_t i = 0; i < vec_keys_.size(); i++) { const cv::KeyPoint &kp = vec_keys_[i]; if (kp.pt.x < n1.UR_.x) { if (kp.pt.y < n1.BR_.y) n1.vec_keys_.push_back(kp); else n3.vec_keys_.push_back(kp); } else if (kp.pt.y < n1.BR_.y) n2.vec_keys_.push_back(kp); else n4.vec_keys_.push_back(kp); }
当特征点全部分配之后循环结束。
当然,计算出来的特征点的位置是不准确的,因为之前为了避免计算到图像外面,做了切边保护,重新计算特征点的绝对位置:
// 换算特征点真实位置(添加边界值),添加特征点的尺度信息 const int nkps = keypoints.size(); for (int i = 0; i < nkps; i++) { keypoints[i].pt.x += min_border_x; keypoints[i].pt.y += min_border_y; keypoints[i].octave = level; keypoints[i].size = scaled_patch_size; }
然后是质心法计算特征点的角度,这里要用到前面初始化的umax。具体过程参考ORB算法,这里没有做任何改变。
然后是逐金字塔逐特征点地计算描述子,对于单个特征点,其32位描述子由以下计算出来:
for (int i = 0; i < 32; ++i, pattern += 16) { int t0, t1, val; t0 = GET_VALUE(0); t1 = GET_VALUE(1); val = t0 < t1; t0 = GET_VALUE(2); t1 = GET_VALUE(3); val |= (t0 < t1) << 1; t0 = GET_VALUE(4); t1 = GET_VALUE(5); val |= (t0 < t1) << 2; t0 = GET_VALUE(6); t1 = GET_VALUE(7); val |= (t0 < t1) << 3; t0 = GET_VALUE(8); t1 = GET_VALUE(9); val |= (t0 < t1) << 4; t0 = GET_VALUE(10); t1 = GET_VALUE(11); val |= (t0 < t1) << 5; t0 = GET_VALUE(12); t1 = GET_VALUE(13); val |= (t0 < t1) << 6; t0 = GET_VALUE(14); t1 = GET_VALUE(15); val |= (t0 < t1) << 7; desc[i] = (uchar)val; }
至此,第一阶段完成。
效果:
相关文章推荐
- SLAM学习笔记3: 源码分析ORB_SLAM中后端图构建
- ORBSlam2学习研究(Code analysis)-ORBSlam2中的闭环检测和后端优化LoopClosing
- IBM将收购BLADE优化云计算及商业分析能力
- 11个源码优化和分析的Java工具
- DPM(Defomable Parts Model) 源码分析-检测(二)
- Pig源码分析: 逻辑执行计划优化
- mapreduce源码分析作业提交、初始化、分配、计算过程之提交篇
- GCC源码分析(四)——优化
- Opencv HOG行人检测 源码分析(一)
- mapreduce源码分析作业提交、初始化、分配、计算过程之初始化篇
- Spark源码分析(1) 从WordCount示例看Spark延迟计算原理
- 1stOpt——世界领先的非线性曲线拟合,综合优化分析计算软件平台
- 几个ajax js性能优化和内存泄露问题及检测分析工具
- 几个ajax js性能优化和内存泄露问题及检测分析工具
- Opencv HOG行人检测 源码分析(二)
- g723源码详细分析-8-计算冲激响应与振铃减法
- JDK源码分析——性能优化实例
- OpenCV学习笔记(29)KAZE 算法原理与源码分析(三)特征检测与描述
- 【原理】Opencv HOG行人检测 源码分析(一)
- DPM(Defomable Parts Model) 源码分析-检测(二)