ORB -SLAM2 ---- Tracking::Tracking和GrabImageStereo

一、Tracking::Tracking

1. 函数讲解,

这是Tracking中的构造函数,此函数的主要作用是为在初始化(初始化追踪线程)的时候使用,主要作用是:

  1. 获取相机的内参
  2. 初始化相机的内参矩阵
  3. 初始化畸变系数
  4. 初始化帧率
  5. 输出相机参数(RGB相机还要输出颜色通道顺序)
  6. 读取图像信息
  7. 初始化特征特取器(双目则初始化左右目)
  8. 输出图像信息

2. 函数源码

Tracking::Tracking(System *pSys, ORBVocabulary* pVoc, FrameDrawer *pFrameDrawer, MapDrawer *pMapDrawer, 
    Map *pMap, KeyFrameDatabase* pKFDB, const string &strSettingPath, const int sensor):
    mState(NO_IMAGES_YET), mSensor(sensor), mbOnlyTracking(false), mbVO(false), mpORBVocabulary(pVoc),
    mpKeyFrameDB(pKFDB), mpInitializer(static_cast<Initializer*>(NULL)), mpSystem(pSys), mpViewer(NULL),
    mpFrameDrawer(pFrameDrawer), mpMapDrawer(pMapDrawer), mpMap(pMap), mnLastRelocFrameId(0)
{
    // Load camera parameters from settings file
    // 从设置文件中读取相机参数
    cv::FileStorage fSettings(strSettingPath, cv::FileStorage::READ);
    float fx = fSettings["Camera.fx"];
    float fy = fSettings["Camera.fy"];
    float cx = fSettings["Camera.cx"];
    float cy = fSettings["Camera.cy"];

    // 初始化相机内参矩阵 K
    cv::Mat K = cv::Mat::eye(3,3,CV_32F); // 三行三列的矩阵 (row行,column列)
    K.at<float>(0,0) = fx;
    K.at<float>(1,1) = fy;
    K.at<float>(0,2) = cx;
    K.at<float>(1,2) = cy;
    //K = [ fx  0   cx]
    //    [ 0   fy  cy]
    //    [ 0   0   1 ]
    K.copyTo(mK); //将矩阵K复制到mK中

    // 初始化畸变系数
    cv::Mat DistCoef(4,1,CV_32F);
    DistCoef.at<float>(0) = fSettings["Camera.k1"];
    DistCoef.at<float>(1) = fSettings["Camera.k2"];
    DistCoef.at<float>(2) = fSettings["Camera.p1"];
    DistCoef.at<float>(3) = fSettings["Camera.p2"];
    const float k3 = fSettings["Camera.k3"];
    // 有的相机没有参数K3,如果有就重新分配空间,将k3加入DistCoef中
    if(k3!=0)
    {
        DistCoef.resize(5);
        DistCoef.at<float>(4) = k3;
    }
    // 将DistCoef中的数据深度拷贝到mDistCoef中
    DistCoef.copyTo(mDistCoef);

    // bf是b*f(基线*焦距)
    mbf = fSettings["Camera.bf"];

    // 初始化帧率
    float fps = fSettings["Camera.fps"];
    if(fps==0)
        fps=30;

    // Max/Min Frames to insert keyframes and to check relocalisation
    // 两个关键帧最大最小帧数限制
    mMinFrames = 0;
    mMaxFrames = fps;

    // 输出相机参数
    cout << endl << "Camera Parameters: " << endl;
    cout << "- fx: " << fx << endl;
    cout << "- fy: " << fy << endl;
    cout << "- cx: " << cx << endl;
    cout << "- cy: " << cy << endl;
    cout << "- k1: " << DistCoef.at<float>(0) << endl;
    cout << "- k2: " << DistCoef.at<float>(1) << endl;
    if(DistCoef.rows==5)
        cout << "- k3: " << DistCoef.at<float>(4) << endl;
    cout << "- p1: " << DistCoef.at<float>(2) << endl;
    cout << "- p2: " << DistCoef.at<float>(3) << endl;
    cout << "- fps: " << fps << endl;

    // 读取输入图像的颜色通道顺序( 1:RGB 0:BGR )『R:红 G:绿 B:蓝』
    int nRGB = fSettings["Camera.RGB"];
    mbRGB = nRGB;
    // 输出一下使用的颜色通道排序
    if(mbRGB)
        cout << "- color order: RGB (ignored if grayscale)" << endl;
    else
        cout << "- color order: BGR (ignored if grayscale)" << endl;

    // Load ORB parameters
    // 读取图像信息
    int nFeatures = fSettings["ORBextractor.nFeatures"];    // 特征点的个数
    float fScaleFactor = fSettings["ORBextractor.scaleFactor"]; // 金字塔图层之间的比例系数
    int nLevels = fSettings["ORBextractor.nLevels"];        // 金字塔层数
    int fIniThFAST = fSettings["ORBextractor.iniThFAST"];   // 角点提取的阈值
    int fMinThFAST = fSettings["ORBextractor.minThFAST"];   // 降低后的阈值
    
    // 创建并初始化(显示初始化)特征提取模块(左眼)
    mpORBextractorLeft = new ORBextractor(nFeatures,fScaleFactor,nLevels,fIniThFAST,fMinThFAST);

    if(sensor==System::STEREO)
    // 如果是双目,还要初始化右眼
        mpORBextractorRight = new ORBextractor(nFeatures,fScaleFactor,nLevels,fIniThFAST,fMinThFAST);

    if(sensor==System::MONOCULAR)
    // 如果是单目,提取双倍提取特征点
        mpIniORBextractor = new ORBextractor(2*nFeatures,fScaleFactor,nLevels,fIniThFAST,fMinThFAST);

    // 输出图像信息
    cout << endl  << "ORB Extractor Parameters: " << endl;
    cout << "- Number of Features: " << nFeatures << endl;
    cout << "- Scale Levels: " << nLevels << endl;
    cout << "- Scale Factor: " << fScaleFactor << endl;
    cout << "- Initial Fast Threshold: " << fIniThFAST << endl;
    cout << "- Minimum Fast Threshold: " << fMinThFAST << endl;

    if(sensor==System::STEREO || sensor==System::RGBD)
    {
        mThDepth = mbf*(float)fSettings["ThDepth"]/fx;
        cout << endl << "Depth Threshold (Close/Far Points): " << mThDepth << endl;
    }

    if(sensor==System::RGBD)
    {
        mDepthMapFactor = fSettings["DepthMapFactor"];
        if(fabs(mDepthMapFactor)<1e-5)
            mDepthMapFactor=1;
        else
            mDepthMapFactor = 1.0f/mDepthMapFactor;
    }

}

一、GrabImageStereo()

1. 函数讲解

这个函数System.cc中被调用,重要作用有:

  1. 抓取左右目图像
  2. 将抓取的图像转换为灰度图像
  3. 初始化帧,因为这里往往被作为相机的初始帧
  4. 调用Track();跟踪此帧(这个非常非常重要,是这个追踪线程的最主要部分,代码量和难度都很大)
  5. 返回当前帧的世界坐标(当前帧相机的世界坐标)

2. 函数源码

cv::Mat Tracking::GrabImageStereo(const cv::Mat &imRectLeft, const cv::Mat &imRectRight, const double &timestamp)
{
    // 拷贝左右目图像
    mImGray = imRectLeft;
    cv::Mat imGrayRight = imRectRight;

    // 将RGB或RGBA图像转为灰度图像
    // 对于这个if,elseif表示不理解,感觉可以不用,或者合并
    if(mImGray.channels()==3)
    {
        if(mbRGB)
        {
            cvtColor(mImGray,mImGray,CV_RGB2GRAY);
            cvtColor(imGrayRight,imGrayRight,CV_RGB2GRAY);
        }
        else
        {
            cvtColor(mImGray,mImGray,CV_BGR2GRAY);
            cvtColor(imGrayRight,imGrayRight,CV_BGR2GRAY);
        }
    }
    else if(mImGray.channels()==4)
    {
        if(mbRGB)
        {
            cvtColor(mImGray,mImGray,CV_RGBA2GRAY);
            cvtColor(imGrayRight,imGrayRight,CV_RGBA2GRAY);
        }
        else
        {
            cvtColor(mImGray,mImGray,CV_BGRA2GRAY);
            cvtColor(imGrayRight,imGrayRight,CV_BGRA2GRAY);
        }
    }

    // 显示初始化双目的构造函数
    mCurrentFrame = Frame(mImGray,imGrayRight,timestamp,mpORBextractorLeft,mpORBextractorRight,mpORBVocabulary,mK,mDistCoef,mbf,mThDepth);
    // 跟踪(调用Tracking::Track())
    Track();
    // 返回当前帧的世界坐标
    return mCurrentFrame.mTcw.clone();
}

三、 学习方法(路线)

在前面的特征提取ORBextractor.cc和帧Frame.cc的学习中,作者是一次性将整个文件学完,但是在学习MapPoint.cc等文件时,发现他们并不具备完整性,很锁碎,函数之间几乎很少有关联。所以在后续的学习中开始改变学习方法,从三个主要线程入手,碰到一个函数就进入一个函数学习,果然提高了学习效率也不再感到学了又望(因为层次明显,学完会回到上一层)。而且这样做还有一个当时未曾想到的好处,就是学完这个文件(ORB-SLAM2)后翻看所有的.cc文件,看哪些函数没有被标注过(本人看过的代码都会进行标注),就可以查缺补漏。

四、总结

这两个函数在追踪线程中有着极为重要的作用,Tracking::Tracking在初始化追踪线程时用到,GrabImageStereo() 中调用的Track();是追踪线程的主体,后续会详细讲解追踪线程中的其他函数。如果有什么问题或者建议,欢迎大家交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值