一、Tracking::Tracking
1. 函数讲解,
这是Tracking中的构造函数,此函数的主要作用是为在初始化(初始化追踪线程)的时候使用,主要作用是:
- 获取相机的内参
- 初始化相机的内参矩阵
- 初始化畸变系数
- 初始化帧率
- 输出相机参数(RGB相机还要输出颜色通道顺序)
- 读取图像信息
- 初始化特征特取器(双目则初始化左右目)
- 输出图像信息
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中被调用,重要作用有:
- 抓取左右目图像
- 将抓取的图像转换为灰度图像
- 初始化帧,因为这里往往被作为相机的初始帧
- 调用Track();跟踪此帧(这个非常非常重要,是这个追踪线程的最主要部分,代码量和难度都很大)
- 返回当前帧的世界坐标(当前帧相机的世界坐标)
2. 函数源码
cv::Mat Tracking::GrabImageStereo(const cv::Mat &imRectLeft, const cv::Mat &imRectRight, const double ×tamp)
{
// 拷贝左右目图像
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();是追踪线程的主体,后续会详细讲解追踪线程中的其他函数。如果有什么问题或者建议,欢迎大家交流。
663

被折叠的 条评论
为什么被折叠?



