在orb slam 2的基础上,对非关键帧使用 LK 光流法 计算相机位姿

orbslam中关键帧只占所有帧中的很小一部分,提取特征点是orbslam中非常耗时的部分。
使用光流法跟踪非关键帧,不需要提取所有帧的特征点。
因为关键帧之间还是使用特征点计算相机位姿,orbslam也只会优化关键帧,这样的修改对精度影响极小,但却大大提高orbslam运行效率。

主要工作:

  1. 在include文件夹内增加LK.h文件,实现cv::Mat computeMtcwUseLK(KeyFrame
    *lastKeyFrame, Mat color, bool lastColorIsKeyFrame, Mat K, Mat mDistCoef)函数

  2. 把函数放到tracking.cpp,并修改viewer.cpp一小部分内容,使光流法跟踪特征点可视化

  3. 在orbslam计算相机位姿前,使用光流法跟踪上一关键帧的特征点,并用pnpransac计算相机位姿。

  4. 未屏蔽orbslam2自带的特征点法计算非关键帧相机位姿,两种方法同时进行

本项目已经开源到https://github.com/suffeeen/orbslam2-with-LK-optical-flow/

所有依赖和orbslam2一样

直接上代码LK.h

//
// Created by lgj on 12/31/19.
//

#ifndef ORB_SLAM2_LK_H
#define ORB_SLAM2_LK_H

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
using namespace ORB_SLAM2;


#include 
#include 
#include 
#include 
using namespace cv;

vector< cv::Point2f > keypoints;
vector mappointInCurrentFrame;
vector prev_keypoints;
cv::Mat last_color;
Mat computeMtcwUseLK(KeyFrame *lastKeyFrame, Mat color, bool lastColorIsKeyFrame, Mat K, Mat mDistCoef)
{
    if(last_color.empty())
    {
        cout<<"fill last color fist time"<mvKeysUn.size()<mvpMapPoints.size();i++)//copy point from keyframe
        {
            if(lastKeyFrame->mvpMapPoints[i]&&lastKeyFrame->mvpMapPoints[i]->nObs>1)///if the program died here, try to change 1 to 0
            {
                keypoints.push_back(lastKeyFrame->mvKeysUn[i].pt);
                cv::Point3f pt3f;
                cv::Mat temp;
                temp = lastKeyFrame->mvpMapPoints[i]->GetWorldPos();
                pt3f.x = temp.at(0);
                pt3f.y = temp.at(1);
                pt3f.z = temp.at(2);
                mappointInCurrentFrame.push_back(pt3f);
            }
        }
    }
    vector next_keypoints;
    prev_keypoints.clear();
    for ( auto kp:keypoints )
        prev_keypoints.push_back(kp);
    vector status;
    vector error;
    if(last_color.empty()||color.empty()||prev_keypoints.empty()||keypoints.empty())//error
    {
        if(last_color.empty())
            cout<<"last color empty"< time_used = chrono::duration_cast>( t2-t1 );
    cout<<"LK Flow use time:"< point3D;

    cv:Mat R_vector,T,R;
    vector ransacInlier;
    if(!(mappointInCurrentFrame.empty()||keypoints.empty()||mDistCoef.empty()))
    {
        chrono::steady_clock::time_point t3 = chrono::steady_clock::now();
        cv::solvePnPRansac(mappointInCurrentFrame, keypoints, K, mDistCoef , R_vector, T, false, 200,3.0, 0.99, ransacInlier, SOLVEPNP_ITERATIVE);
        cv::Rodrigues(R_vector, R);
        chrono::steady_clock::time_point t4 = chrono::steady_clock::now();
        chrono::duration time_used = chrono::duration_cast>( t4-t3 );
        cout<<"solve PnP RANSAC use time:"< Rt = (Mat_(4, 4) << R.at(0,0), R.at(0,1), R.at(0,2),T.at(0),
                                                            R.at(1,0), R.at(1,1), R.at(1,2),T.at(1),
                                                            R.at(2,0), R.at(2,1), R.at(2,2),T.at(2),
                                                            0, 0, 0, 1);
        cv::Mat Rt_float;
        Rt.convertTo(Rt_float,CV_32FC1);
        cout<<"LK_PNP_RANSAC pose: "<

运行效果:在orb slam 2的基础上,对非关键帧使用 LK 光流法 计算相机位姿_第1张图片
在orb slam 2的基础上,对非关键帧使用 LK 光流法 计算相机位姿_第2张图片

你可能感兴趣的:(在orb slam 2的基础上,对非关键帧使用 LK 光流法 计算相机位姿)