4. ORB-SLAM3_V1 源码阅读笔记 -Tracking类

主要参考:https://zhuanlan.zhihu.com/p/349770246,在此基础上对1.0版本源码进行解读

Tracking.cc文件的主要内容有:

  1. 在构造函数中读取配置文件中的参数。
  2. 处理图像和imu数据,进行位姿跟踪,最主要的是track( )函数。

1、Tracking构造函数

在实例化system类时,调用Tracking构造函数。

   mpTracker = new Tracking(this, mpVocabulary, mpFrameDrawer, mpMapDrawer,
                             mpAtlas, mpKeyFrameDatabase, strSettingsFile, mSensor, settings_, strSequence);

主要作用:读取相机参数、ORB特征点参数、惯导参数

Tracking::Tracking(System *pSys, ORBVocabulary* pVoc, FrameDrawer *pFrameDrawer, MapDrawer *pMapDrawer,
    Atlas *pAtlas, KeyFrameDatabase* pKFDB, const string &strSettingPath, const int sensor, Settings* settings, const string &_nameSeq)
    : mState(NO_IMAGES_YET), mSensor(sensor), mTrackedFr(0), mbStep(false),
    mbOnlyTracking(false), mbMapUpdated(false), mbVO(false), mpORBVocabulary(pVoc), mpKeyFrameDB(pKFDB),
    mbReadyToInitializate(false), mpSystem(pSys), mpViewer(NULL), bStepByStep(false),
    mpFrameDrawer(pFrameDrawer), mpMapDrawer(pMapDrawer), mpAtlas(pAtlas), mnLastRelocFrameId(0), time_recently_lost(5.0),
    mnInitialFrameId(0), mbCreatedMap(false), mnFirstFrameId(0), mpCamera2(nullptr), mpLastKeyFrame(static_cast<KeyFrame*>(NULL))
{
    // Load camera parameters from settings file
    // Step 1 从配置文件中加载相机参数
    if(settings){
        newParameterLoader(settings);
    }
    else{
        cv::FileStorage fSettings(strSettingPath, cv::FileStorage::READ);
        
         //读取相机参数
          //如果是ROS,DepthMapFactor应该设为1,即深度不进行缩放
        bool b_parse_cam = ParseCamParamFile(fSettings);
        if(!b_parse_cam)
        {
            std::cout << "*Error with the camera parameters in the config file*" << std::endl;
        }

        // Load ORB parameters
        //读取ORB特征提取的相关参数,该函数中还会
        //根据参数构造ORB提取器mpORBextractorLeft(左目)、mpORBextractorRight(右目)、mpIniORBextractor(初始化用)
        bool b_parse_orb = ParseORBParamFile(fSettings);
        if(!b_parse_orb)
        {
            std::cout << "*Error with the ORB parameters in the config file*" << std::endl;
        }
        
        //读取imu参数,该函数中还会
        //根据参数构建预积分处理器mpImuPreintegratedFromLastKF
        bool b_parse_imu = true;
        if(sensor==System::IMU_MONOCULAR || sensor==System::IMU_STEREO || sensor==System::IMU_RGBD)
        {
            b_parse_imu = ParseIMUParamFile(fSettings);
            if(!b_parse_imu)
            {
                std::cout << "*Error with the IMU parameters in the config file*" << std::endl;
            }

            mnFramesToResetIMU = mMaxFrames;
        }

        if(!b_parse_cam || !b_parse_orb || !b_parse_imu)
        {
            std::cerr << "**ERROR in the config file, the format is not correct**" << std::endl;
            try
            {
                throw -1;
            }
            catch(exception &e)
            {

            }
        }
    }

    initID = 0; lastID = 0;
    mbInitWith3KFs = false;
    mnNumDataset = 0;

    // 遍历下地图中的相机,然后打印出来了
    vector<GeometricCamera*> vpCams = mpAtlas->GetAllCameras();
    std::cout << "There are " << vpCams.size() << " cameras in the atlas" << std::endl;
    for(GeometricCamera* pCam : vpCams)
    {
        std::cout << "Camera " << pCam->GetId();
        if(pCam->GetType() == GeometricCamera::CAM_PINHOLE)
        {
            std::cout << " is pinhole" << std::endl;
        }
        else if(pCam->GetType() == GeometricCamera::CAM_FISHEYE)
        {
            std::cout << " is fisheye" << std::endl;
        }
        else
        {
            std::cout << " is unknown" << std::endl;
        }
    }

#ifdef REGISTER_TIMES
    vdRectStereo_ms.clear();
    vdResizeImage_ms.clear();
    vdORBExtract_ms.clear();
    vdStereoMatch_ms.clear();
    vdIMUInteg_ms.clear();
    vdPosePred_ms.clear();
    vdLMTrack_ms.clear();
    vdNewKF_ms.clear();
    vdTrackTotal_ms.clear();
#endif
}

2、开始跟踪

以下是双目情况。单目和RGBD同理

//开启追踪,进行必要的设置和数据处理,随后在GrabImageStereo()内进行位置姿态计算。
  mpSLAM->TrackStereo(imLeft,imRight,tImLeft,vImuMeas);
         // 计算相机位姿
        Sophus::SE3f Tcw = mpTracker->GrabImageStereo(imLeftToFeed,imRightToFeed,timestamp,filename);

GrabImageStereo(imLeftToFeed,imRightToFeed,timestamp,filename)函数
主要作用:
(1) 将彩色图转为灰度图
(2)构造Frame类
(3)跟踪:函数track()

/**
 * @brief 输入左右目图像,可以为RGB、BGR、RGBA、GRAY
 * 1、将图像转为mImGray和imGrayRight并初始化mCurrentFrame
 * 2、进行tracking过程
 * 输出世界坐标系到该帧相机坐标系的变换矩阵
 * @param imRectLeft 左图
 * @param imRectRight 右图
 * @param timestamp 时间戳
 * @param filename 文件名字,貌似调试用的
 */
Sophus::SE3f Tracking::GrabImageStereo(const cv::Mat &imRectLeft, const cv::Mat &imRectRight, const double &timestamp, string filename)
{
    //cout << "GrabImageStereo" << endl;

    mImGray = imRectLeft;
    cv::Mat imGrayRight = imRectRight;
    mImRight = imRectRight;

    // step 1 :将RGB或RGBA图像转为单通道灰度图像
    if(mImGray.channels()==3)
    {
        //cout << "Image with 3 channels" << endl;
        if(mbRGB)
        {
            cvtColor(mImGray,mImGray,cv::COLOR_RGB2GRAY);
            cvtColor(imGrayRight,imGrayRight,cv::COLOR_RGB2GRAY);
        }
        else
        {
            cvtColor(mImGray,mImGray,cv::COLOR_BGR2GRAY);
            cvtColor(imGrayRight,imGrayRight,cv::COLOR_BGR2GRAY);
        }
    }
    // 这里考虑得十分周全,甚至连四通道的图像都考虑到了
    else if(mImGray.channels()==4)
    {
        //cout << "Image with 4 channels" << endl;
        if(mbRGB)
        {
            cvtColor(mImGray,mImGray,cv::COLOR_RGBA2GRAY);
            cvtColor(imGrayRight,imGrayRight,cv::COLOR_RGBA2GRAY);
        }
        else
        {
            cvtColor(mImGray,mImGray,cv::COLOR_BGRA2GRAY);
            cvtColor(imGrayRight,imGrayRight,cv::COLOR_BGRA2GRAY);
        }
    }

    //cout << "Incoming frame creation" << endl;
    // Step 2 :构造Frame类
    if (mSensor == System::STEREO && !mpCamera2)
        mCurrentFrame = Frame(
            mImGray,                // 左目图像
            imGrayRight,            // 右目图像
            timestamp,              // 时间戳
            mpORBextractorLeft,     // 左目特征提取器
            mpORBextractorRight,    // 右目特征提取器
            mpORBVocabulary,        // 字典
            mK,                     // 内参矩阵
            mDistCoef,              // 去畸变参数
            mbf,                    // 基线长度
            mThDepth,				// 远点,近点的区分阈值
            mpCamera);				// 相机模型
    else if(mSensor == System::STEREO && mpCamera2)
        mCurrentFrame = Frame(mImGray,imGrayRight,timestamp,mpORBextractorLeft,mpORBextractorRight,mpORBVocabulary,mK,mDistCoef,mbf,mThDepth,mpCamera,mpCamera2,mTlr);
    else if(mSensor == System::IMU_STEREO && !mpCamera2)
        mCurrentFrame = Frame(mImGray,imGrayRight,timestamp,mpORBextractorLeft,mpORBextractorRight,mpORBVocabulary,mK,mDistCoef,mbf,mThDepth,mpCamera,&mLastFrame,*mpImuCalib);
    else if(mSensor == System::IMU_STEREO && mpCamera2)
        mCurrentFrame = Frame(mImGray,imGrayRight,timestamp,mpORBextractorLeft,mpORBextractorRight,mpORBVocabulary,mK,mDistCoef,mbf,mThDepth,mpCamera,mpCamera2,mTlr,&mLastFrame,*mpImuCalib);

    //cout << "Incoming frame ended" << endl;

    mCurrentFrame.mNameFile = filename;
    mCurrentFrame.mnDataset = mnNumDataset;

#ifdef REGISTER_TIMES
    vdORBExtract_ms.push_back(mCurrentFrame.mTimeORB_Ext);
    vdStereoMatch_ms.push_back(mCurrentFrame.mTimeStereoMatch);
#endif

    //cout << "Tracking start" << endl;
    // Step  3 :跟踪
    Track();
    //cout << "Tracking end" << endl;

    // 返回位姿
    return mCurrentFrame.GetPose();
}

3.Track( )函数

Track( )函数的流程图如下:
在这里插入图片描述错误修正:
处理IMU时间戳异常情况:

  • 当前图像时间 < 上一帧图像时间,说明出错了,清楚imu数据新建新的子地图
  • 如果当前帧时间 >上一帧时间 +1 ,说明时间发生了跳变,没有imu直接重置地图,有imu处理方式如下:
    (1)imu完成了第三次初始化,新建地图
    (2)没有完成第三次初始化,重置地图。
    重置地图和新建地图的区别,新建是把当前地图保存,在重新弄一个地图,重置是当前地图不要了,重新弄一个地图。

4、利用IMU计算位姿 PredictStateIMU()

有两种情况会用到此函数:
(a)视觉跟丢时用imu预测位姿。
(b)imu模式下,恒速模型跟踪时提供位姿初始值。

注意:

(1)此函数不会直接设置当前帧的位姿,而是记录当前帧的imu到世界坐标系的平移、旋转和速度。在后面TrackLocalMap( )中对位姿优化后才设置当前帧的位姿Tcw。
(2)地图更新(回环、融合、局部BA、IMU初始化时地图会调整)时,利用上一关键帧和距离上一关键帧的预积分,计算当前帧imu的位姿,因为此时关键帧经过了优化调整,认为更准。
(3)地图未更新时,利用前一帧和距离前一帧的预积分,计算当前帧imu的位姿,因为此时关键帧没有做优化调整,而前一帧距离更近,认为更准。
(4)用到的公式为forster预积分论文中的公式(26),需要做移项。

5、预积分 PreintegrateIMU()

算法流程:

(1) 如果上一帧不存在,则不进行预积分;如果没有imu数据,也不进行预积分,直接返回保存时间戳在两帧之间的imu数据至mvImuFromLastFrame
(2)构造预积分器pImuPreintegratedFromLastFrame(这个是上一帧到当前帧的预积分)对于n个imu数据,要进行n-1次计算得到两帧之间的预积分量。首先利用中值积分,得到每次计算预积分的加速度和角速度。对于头和尾的Imu数据,由于不能严格地和图像时间戳对齐,需要进行适当的补偿。
(3)开始计算预积分 IntegrateNewMeasurement( )(这个函数在我的另一篇文章中有说明:ORB-SLAM3源码阅读笔记(4)-ImuTypes),这里需要计算上一帧到当前帧的预积分pImuPreintegratedFromLastFrame,和上一关键帧到当前帧的预积分mpImuPreintegratedFromLastKF(在初始化帧和插入关键帧时会新建一个,地图更新时,PredictStateIMU需要相对于上一关键帧计算位姿)
(4)所有imu数据计算完成之后,记录两个预积分值,并设置当前帧为已预积分状态

6、恒速模型跟踪 TrackWithMotionModel()

算法流程:

(1) 构建ORB匹配器 ORBmatcher。
(2)更新上一帧的位姿和地图点(UpdateLastFrame()),这个函数主要是根据上一帧与它的参考关键帧的相对位姿,乘上它参考关键帧的位姿,来更新上一帧的位姿,即认为相对位姿是准的,而参考关键帧的位姿可能在优化时被调整过了。如果是双目或RGBD模式,还会产生临时地图点,增加匹配,跟踪结束后会删除。
(3)如果是imu模式,则调用PredictStateIMU( )来提供位姿估计的初始值。如果是纯视觉,则用上上帧到上一帧的相对位姿mVelocity,作为上一帧到当前帧的相对位姿,提供位姿估计初始值。
(4)通过将上一帧的地图点投影到当前帧,寻找匹配 matcher.SearchByProjection( )
(5)根据获得的匹配点进行位姿优化,Optimizer::PoseOptimization(&mCurrentFrame)
(6)去除外点,根据内点数判断是否跟踪成功,其中,imu模式总是返回true。

7、跟踪参考关键帧 TrackReferenceKeyFrame( )

有两种情况会用到此函数:

(a)刚刚进行了重定位,则跟踪参考关键帧。

(b)恒速模型为空或恒速跟踪失败。

bool Tracking::TrackReferenceKeyFrame()
{
    // Compute Bag of Words vector
    mCurrentFrame.ComputeBoW();//计算词袋向量mBowVec和特征向量mFeatVec
    // We perform first an ORB matching with the reference keyframe
    ORBmatcher matcher(0.7,true);
    vector<MapPoint*> vpMapPointMatches;
    //通过BoW加速匹配。用到了mFeatVec,两个关键帧中 只有节点相同的特征点才会被比较,相同节点中的特征点采用暴力搜索,并且需要检查方向性,
    //并且最优的要明显好于次优的。
    int nmatches = matcher.SearchByBoW(mpReferenceKF,mCurrentFrame,vpMapPointMatches);
    if(nmatches<15)
    {
        cout << "TRACK_REF_KF: Less than 15 matches!!\n";
        return false;
    }
    mCurrentFrame.mvpMapPoints = vpMapPointMatches;
    mCurrentFrame.SetPose(mLastFrame.mTcw);//用上一帧的位姿作为初始值
    //mCurrentFrame.PrintPointDistribution();
    // cout << " TrackReferenceKeyFrame mLastFrame.mTcw:  " << mLastFrame.mTcw << endl;
    Optimizer::PoseOptimization(&mCurrentFrame);//位姿优化
    // Discard outliers
    int nmatchesMap = 0;
    //删除外点,统计内点
    for(int i =0; i<mCurrentFrame.N; i++)
    {
        //if(i >= mCurrentFrame.Nleft) break;
        if(mCurrentFrame.mvpMapPoints[i])
        {
            if(mCurrentFrame.mvbOutlier[i])
            {
                MapPoint* pMP = mCurrentFrame.mvpMapPoints[i];
                mCurrentFrame.mvpMapPoints[i]=static_cast<MapPoint*>(NULL);
                mCurrentFrame.mvbOutlier[i]=false;
                if(i < mCurrentFrame.Nleft){
                    pMP->mbTrackInView = false;
                }
                else{
                    pMP->mbTrackInViewR = false;
                }
                pMP->mbTrackInView = false;
                pMP->mnLastFrameSeen = mCurrentFrame.mnId;
                nmatches--;
            }
            else if(mCurrentFrame.mvpMapPoints[i]->Observations()>0)
                nmatchesMap++;
        }
    }
    if (mSensor == System::IMU_MONOCULAR || mSensor == System::IMU_STEREO)
        return true;
    else
        return nmatchesMap>=10;
}

8、重定位 Relocalization( )

算法流程:

(1) 计算当前帧的BoW
( 2)利用反向索引在关键帧数据库中找到候选关键帧DetectRelocalizationCandidates()
(3)逐一与候选关键帧进行BoW加速匹配 SearchByBoW(),丢弃匹配点数小于15的候选帧,为剩下的候选帧构建MLPnPsolver
(4)对匹配数大于15的候选帧求解MLPnP,得到位姿之后进行位姿优化,如果优化内点数足够(大于50),直接退出循环,返回true
(5)如果优化内点数不够,则进行投影匹配,找到更多的匹配点,再进行位姿优化,如此抢救两次之后优化内点数还是不够的话,该候选帧求解失败,继续下一候选帧,直到所有候选帧求解都失败或有一个候选帧求解成功。

9、跟踪局部地图 TrackLocalMap( )

这个函数主要是利用局部窗口的关键帧和地图点,为当前帧找到更多的匹配地图点,再进行位姿优化,使得位姿更加准确。
算法流程:

(1)首先更新局部关键帧和局部地图点。找到与当前帧共视程度最高的关键帧pKFmax,放入mvpLocalKeyFrames中,将pKFmax的父子关键帧、共视程度最高的10帧关键帧也放入mvpLocalKeyFrames中,如果是ium模式还要将当前帧之前连续的20放入mvpLocalKeyFrames中。
(2)将mvpLocalKeyFrames中关键帧对应的地图点都放入mvpLocalMapPoints中。
(3)通过投影匹配找到与当前帧匹配的局部地图点 SearchByProjection()
(4)进行位姿优化。imu模式下地图更新时PoseInertialOptimizationLastKeyFrame()地图未更新时用PoseInertialOptimizationLastFrame()。
(5)删除无效地图点,根据内点数判断是否跟踪成功

10、关键帧选取策略 NeedNewKeyFrame( )

关键帧插入主要考虑以下几个因素:
(a)程序运行的模式(是否纯定位)、LocalMapping线程的状态等,限制了不能插入关键帧
(b)距离上一次插入关键帧的时间。imu模式有固定的最长插入间隔
(c)跟踪的好坏。跟踪得不好时需要快点插入关键帧。
(d)传感器的类型。单目插入关键帧最频繁。

bool Tracking::NeedNewKeyFrame()
{
    //如果是imu模式,没初始化之前每隔0.25s就插入关键帧
    if(((mSensor == System::IMU_MONOCULAR) || (mSensor == System::IMU_STEREO)) && !mpAtlas->GetCurrentMap()->isImuInitialized())
    {
        if (mSensor == System::IMU_MONOCULAR && (mCurrentFrame.mTimeStamp-mpLastKeyFrame->mTimeStamp)>=0.25)
            return true;
        else if (mSensor == System::IMU_STEREO && (mCurrentFrame.mTimeStamp-mpLastKeyFrame->mTimeStamp)>=0.25)
            return true;
        else
            return false;
    }
    //纯定位模式不插入关键帧,因为局部建图线程不工作
    if(mbOnlyTracking)
        return false;
    // If Local Mapping is freezed by a Loop Closure do not insert keyframes
    //如果Local Mapping被Loop Closure请求停止了,则不插入关键帧
    if(mpLocalMapper->isStopped() || mpLocalMapper->stopRequested())
    {
        return false;
    }
    // Return false if IMU is initialazing
    if (mpLocalMapper->IsInitializing())
        return false;
    const int nKFs = mpAtlas->KeyFramesInMap();

    // Do not insert keyframes if not enough frames have passed from last relocalisation
    if(mCurrentFrame.mnId<mnLastRelocFrameId+mMaxFrames && nKFs>mMaxFrames)
    {
        return false;
    }
    // Tracked MapPoints in the reference keyframe
    int nMinObs = 3;
    if(nKFs<=2)
        nMinObs=2;
    //参考关键帧的地图点中,大于等于最小观测数目的地图点个数,即这些地图点被追踪到了
    int nRefMatches = mpReferenceKF->TrackedMapPoints(nMinObs);
    // Local Mapping accept keyframes?
    bool bLocalMappingIdle = mpLocalMapper->AcceptKeyFrames();
    // Check how many "close" points are being tracked and how many could be potentially created.
    //统计近点中被跟踪到的个数和未跟踪到的个数(非单目和非单目imu)
    int nNonTrackedClose = 0;
    int nTrackedClose= 0;
    if(mSensor!=System::MONOCULAR && mSensor!=System::IMU_MONOCULAR)
    {
        //特征点的个数N
        int N = (mCurrentFrame.Nleft == -1) ? mCurrentFrame.N : mCurrentFrame.Nleft;
        for(int i =0; i<N; i++)
        {   //特征点的深度大于0小于远近点阈值
            if(mCurrentFrame.mvDepth[i]>0 && mCurrentFrame.mvDepth[i]<mThDepth)
            {
                if(mCurrentFrame.mvpMapPoints[i] && !mCurrentFrame.mvbOutlier[i])
                    nTrackedClose++;//该点不是外点,则追踪到的近点加一
                else
                    nNonTrackedClose++;//是外点,未追踪到的近点加一
            }
        }
    }
    bool bNeedToInsertClose;//跟踪到的近点不多,但未跟踪到的近点很多,说明跟踪得不好
    bNeedToInsertClose = (nTrackedClose<100) && (nNonTrackedClose>70);
    //当前帧和参考关键帧跟踪到点的比例。阈值越大,越容易达到插入关键帧的条件
    float thRefRatio = 0.75f;
    if(nKFs<2)
        thRefRatio = 0.4f;
    //单目插入最频繁
    if(mSensor==System::MONOCULAR)
        thRefRatio = 0.9f;
    if(mpCamera2) thRefRatio = 0.75f;
    if(mSensor==System::IMU_MONOCULAR)
    {
        if(mnMatchesInliers>350) // Points tracked from the local map
            thRefRatio = 0.75f;
        else
            thRefRatio = 0.90f;
    }
    // Condition 1a: More than "MaxFrames" have passed from last keyframe insertion
    const bool c1a = mCurrentFrame.mnId>=mnLastKeyFrameId+mMaxFrames;//太久
    // Condition 1b: More than "MinFrames" have passed and Local Mapping is idle
    const bool c1b = ((mCurrentFrame.mnId>=mnLastKeyFrameId+mMinFrames) && bLocalMappingIdle);
    //Condition 1c: tracking is weak
    const bool c1c = mSensor!=System::MONOCULAR && mSensor!=System::IMU_MONOCULAR && mSensor!=System::IMU_STEREO && (mnMatchesInliers<nRefMatches*0.25 || bNeedToInsertClose) ;
    // Condition 2: Few tracked points compared to reference keyframe. Lots of visual odometry compared to map matches.
    const bool c2 = (((mnMatchesInliers<nRefMatches*thRefRatio || bNeedToInsertClose)) && mnMatchesInliers>15);
    // Temporal condition for Inertial cases
    bool c3 = false;
    if(mpLastKeyFrame)
    {   //imu模式下超过0.5s之后则c3为true
        if (mSensor==System::IMU_MONOCULAR)
        {
            if ((mCurrentFrame.mTimeStamp-mpLastKeyFrame->mTimeStamp)>=0.5)
                c3 = true;
        }
        else if (mSensor==System::IMU_STEREO)
        {
            if ((mCurrentFrame.mTimeStamp-mpLastKeyFrame->mTimeStamp)>=0.5)
                c3 = true;
        }
    }
    bool c4 = false;
    if ((((mnMatchesInliers<75) && (mnMatchesInliers>15)) || mState==RECENTLY_LOST) && ((mSensor == System::IMU_MONOCULAR))) // MODIFICATION_2, originally ((((mnMatchesInliers<75) && (mnMatchesInliers>15)) || mState==RECENTLY_LOST) && ((mSensor == System::IMU_MONOCULAR)))
        c4=true;
    else
        c4=false;
    if(((c1a||c1b||c1c) && c2)||c3 ||c4)
    {
        // If the mapping accepts keyframes, insert keyframe.
        // Otherwise send a signal to interrupt BA
        if(bLocalMappingIdle)
        {
            return true;
        }
        else
        {   //局部建图繁忙的话,请求停止局部BA
            mpLocalMapper->InterruptBA();
            if(mSensor!=System::MONOCULAR  && mSensor!=System::IMU_MONOCULAR)
            {   //非单目和非单目imu模式,且关键帧队列中小于3,可以插入
                if(mpLocalMapper->KeyframesInQueue()<3)
                    return true;
                else
                    return false;
            }
            else //单目和单目imu模式直接不能插入,因为单目本来就插入比较密集,这里就不需要插入了
                return false;
        }
    }
    else
        return false;
}
### 回答1: ORB-SLAM2_with_semantic_label是一种基于ORB-SLAM2的视觉SLAM系统,它使用语义标签信息来增强场景理解和地图构建。该系统通过将每个地图点与语义标签相对应,从而为地图的每个区域提供更多的上下文信息。这有助于提高系统的鲁棒性和场景理解能力,并可以在机器人导航、自动驾驶等领域得到广泛应用。 ### 回答2: ORB-SLAM2是一种视觉SLAM算法,可以实现从单个或多个摄像头的图像序列实时重建3D地图,同时在该地图定位相机。它广泛应用于机器人导航、增强现实、自动驾驶等领域。然而,在某些现实场景,例如室内场景、城市环境等,只有3D地图是不够的,需要利用语义信息来更好地理解环境。 因此,ORB-SLAM2的研究人员进行了扩展,开发了一种ORB-SLAM2_with_semantic_label算法,以结合视觉SLAM和语义信息。该算法的目标是在ORB-SLAM2增加对语义信息的支持,从而允许机器理解其所在环境的物体及其特征。该算法的一个重要应用是在机器人导航,机器人可以利用语义标签对其周围环境进行更准确、更可靠的理解,从而更好地规划路径。 该算法的关键步骤包括以下几个方面。首先,需要将语义分割模型与ORB-SLAM2进行集成,产生语义标记的地图,这可以在ORB-SLAM2映射初始化期间完成。其次,需要利用深度学习技术提取图像的语义特征,用于在传统视觉SLAM系统增加语义信息。接着,需要将ORB-SLAM2的回环检测模块改进,以考虑语义信息来消除误报。最后,需要使用机器学习算法,通过对特定环境所遇到的物体的历史观测进行学习,从而使机器人能够在不同环境尽可能准确地识别物体。 该算法的优点是可以在不增加太多计算量的情况下增加语义信息,从而使机器能够自然地与人进行交互。但是,该算法的缺点是需要对语义标注数据进行精确的手动标注,这是一项非常耗时的任务。此外,该算法对光照和尺度变化非常敏感,因此在实际应用需要特别注意。 ### 回答3: ORB-SLAM2是一种基于视觉SLAM技术的实时多目标跟踪和定位系统,它结合了ORB特征提取器和BoW词袋模型,使得系统具有高效的实时位姿估计能力。而ORB-SLAM2 with Semantic Label则是在ORB-SLAM2的基础上,加入了语义标签的支持。 语义标签是指对环境元素的分标注,例如标注图像的建筑、人、车等。加入语义标签的目的是提高系统对环境信息的理解和描述能力。在ORB-SLAM2 with Semantic Label,可以通过在输入图像标记语义标签信息,并将其存储到地图数据,从而实现地图的语义化描述。同时,语义标签可以通过深度学习等技术来实现自动分。 与传统的视觉SLAM系统相比,ORB-SLAM2 with Semantic Label可以更好地应对复杂的环境场景。在城市街道和室内场所等环境ORB-SLAM2 with Semantic Label可以对人、车辆和建筑等复杂元素进行识别,并在建立地图时,将这些语义信息一同存储在地图。这样可以提供更为精确的地图信息,使得系统的位置估计更加准确、稳定。 总之,ORB-SLAM2 with Semantic Label是一种具有语义理解能力的SLAM系统,可以为机器人的自主导航和环境理解等方面的应用提供更为准确、可靠的基础支撑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

My.科研小菜鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值