ORB-SLAM2学习简单记录
简要说明
由于12月末的时候掏钱买了个orbslam2源码讲解的视频,虽然每一天也有陆陆续续看一点,但是越到后面看的越懵,因为orbslam2的代码还是比较复杂的。于是我打算简单记录一个代码框架,就是文件结构、伪代码和思路之类的,不涉及具体细节,旨在对整个slam框架的思路有个了解。而且网上对orbslam2的好的解说有太多了,我也就不班门弄斧了。这篇博文也就相当于一个学习笔记,比较粗糙,但对照着这个结构去看相关视频和博客以及源码,我觉得让我的思绪更加有条理,希望对大家有用。而且这个应该一直在更,取决于我视频看到哪。
----------------------------------手动分割线-------------------------------------
- main -------- 1
- System -------- 11
- SLAM.TrackMonocular -------- 12
main{
LoadImages();
ORB_SLAM2::System SLAM();
for each in images{
SLAM.TrackMonocular(each);
}
}
System(){
Load_OrbVocabulary();
new KeyFrameDatabase;
new Map;
// new thread
new Tracking();
new LocalMapping();
new LoopClosing();
}
Tracking(){
Load_CameraIntrincs();
new ORBextractor();
}
LocalMapping::Run(){
while(1){
if(CheckNewKeyFrames()){
ProcessNBewKeyFrame();
MapPointCulling();
CreateNewMapPoints();
if(!CheckNewKeyFrame() &&!stopRequested()){
// local BA
Optimizer::LocalBundleAdjustment();
KeyFrameCulling();
}
}
}
}
ORBextractor(){
初始化图像金字塔(尺度、方差、特征点数分配);
// for orientation
求umax;
}
LoopClosing::Run(){
while(1){
if(CheckNewKeyFrames()){
if(DetectLoop()){
if(ComputeSim3()){
CorrectLoop();
}
}
}
}
}
SLAM.TrackMonocular(){
// calculate Tcw
GrabImageMonocular();
}
GrabImageMonocular(){
if(not initialized)
Frame(init_ORBextractor);
else
Frame(ORBextractor);
Track();
}
Frame(){
ExtractORB();
AssignFeaturesToGrid();
}
ExtractORB(){
// extract orb features
(*xxx)();
}
ORBextractor::operator()(){
// 构建图像金字塔
ComputePyramid(image);
ComputeKeyPointsOctTree();
for each levels{
GaussianBlur();
computeDescriptors();
}
}
ComputeKeyPointsOctTree(){
for each levels{
for each grids{
Fast();
}
DistributeOctTree();
}
for each levels{
computeOrientation();
}
}
// 四叉树平均分配特征点
DistrbuteOctTree(){
1. 按照图像大小初始化节点
2. 节点分裂为4个节点,每个节点占母节点区域的1/4,也就是上下左右格子,并删除母节点。
3. 如果该节点特征点多于阈值,重复2。
4. 最后只取所有节点中响应值最大的特征点。
}
// 这里用到了umax
computeOrientation(){
for each keypoints{
keypoint->angle = IC_Angle();
}
}
// 这里顺带看IC_Angle, 不分级了
static float IC_Angle(){
// 使用灰度质心法计算特征点方向
for v = 1:r { // r半径
for u = -umax ~ umax {
// 计算m_10
// 计算m_01
}
}
return fastAtan2(m_01, m_10);
}
computeDescriptors(){
for i = 1:keypoints.size(){
computeOrbDescriptor();
}
}
computeOrbDescriptor(){
for (i = 0; i < 32; i++){ // 32位 brief描述子
// 描述子旋转
// 比大小构成二进制描述子
}
}
Track(){
if(not initialized)
MonocularInitialization();
else{
if(state == OK)
{
// replace map points
CheckReplacedInLastFrame();
if(no motion model || not long after initialization)
TrackReferenceKeyFrame();
else{
if(! TrackWithMotionModel)
TrackReferenceKeyFrame();
}
}else
Relocalization();
if(TrackLocalMap()){
// if tracking was good, check if insert a keyframe
if(NeedNewKeyFrame())
CreateNewKeyFrame();
}
}
}
MonocularInitalization(){
ORBmatcher matcher();
matcher.SearchForInitialization();
// initialize via F or H
mpInitializer->Initialize();
// initial monocular map
CreateInitMapMonocular();
}