本次主要讲解ORBSLAM2中的单目图像帧构造函数Frame::Frame
,在其中主要完成了特征点的提取,畸变矫正以及将特征点分配到网格中的功能。
首先是构造函数的参数
Frame::Frame(const cv::Mat &imGray, //灰度图
const double &timeStamp, //时间戳
ORBextractor* extractor, //ORB特征点提取器的句柄
ORBVocabulary* voc, //ORB字典的句柄
cv::Mat &K, //相机的内参数矩阵
cv::Mat &distCoef, //相机的去畸变参数
const float &bf, //baseline*f
const float &thDepth) //区分远近点的深度阈值
:mpORBvocabulary(voc),
mpORBextractorLeft(extractor),
mpORBextractorRight(static_cast<ORBextractor*>(NULL)),
mTimeStamp(timeStamp),
mK(K.clone()),
mDistCoef(distCoef.clone()),
mbf(bf),
mThDepth(thDepth)
在构造函数中主要完成了以下功能:
- 帧Id的自增
// Step 1 帧的ID 自增 mnId=nNextId++;
- 获取前面在特征点提取器中计算的金字塔的相关参数
// Step 2 计算图像金字塔的参数 //获取图像金字塔的层数 mnScaleLevels = mpORBextractorLeft->GetLevels(); //获取每层的缩放因子 mfScaleFactor = mpORBextractorLeft->GetScaleFactor(); //计算每层缩放因子的自然对数 mfLogScaleFactor = log(mfScaleFactor); //获取各层图像的缩放因子 mvScaleFactors = mpORBextractorLeft->GetScaleFactors(); //获取各层图像的缩放因子的倒数 mvInvScaleFactors = mpORBextractorLeft->GetInverseScaleFactors(); //获取sigma^2 mvLevelSigma2 = mpORBextractorLeft->GetScaleSigmaSquares(); //获取sigma^2的倒数 mvInvLevelSigma2 = mpORBextractorLeft->GetInverseScaleSigmaSquares();
- 对ORB特征点的提取
// Step 3 对这个单目图像进行提取特征点, 第一个参数0-左图, 1-右图 ExtractORB(0,imGray); //求出特征点的个数 N = mvKeys.size(); //如果没有能够成功提取出特征点,那么就直接返回了 if(mvKeys.empty()) return;
- 对特征点去畸变
// Step 4 用OpenCV的矫正函数、内参对提取到的特征点进行矫正 UndistortKeyPoints(); // Set no stereo information // 由于单目相机无法直接获得立体信息,所以这里要给右图像对应点和深度赋值-1表示没有相关信息 mvuRight = vector<float>(N,-1); mvDepth = vector<float>(N,-1);
- 地图点初始化
// 初始化本帧的地图点 mvpMapPoints = vector<MapPoint*>(N,static_cast<MapPoint*>(NULL)); // 记录地图点是否为外点,初始化均为外点false mvbOutlier = vector<bool>(N,false);
- 计算去畸变后的图像边界(只发生在第一帧或者相机内参发生变化时)
// Step 5 计算去畸变后图像边界。这个过程一般是在第一帧或者是相机标定参数发生变化之后进行 if(mbInitialComputations) { // 计算去畸变后图像的边界 ComputeImageBounds(imGray); // 表示一个图像像素相当于多少个图像网格列(宽) mfGridElementWidthInv=static_cast<float>(FRAME_GRID_COLS)/static_cast<float>(mnMaxX-mnMinX); // 表示一个图像像素相当于多少个图像网格行(高) mfGridElementHeightInv=static_cast<float>(FRAME_GRID_ROWS)/static_cast<float>(mnMaxY-mnMinY); //给类的静态成员变量复制 fx = K.at<float>(0,0); fy = K.at<float>(1,1); cx = K.at<float>(0,2); cy = K.at<float>(1,2); // 猜测是因为这种除法计算需要的时间略长,所以这里直接存储了这个中间计算结果 invfx = 1.0f/fx; invfy = 1.0f/fy; //特殊的初始化过程完成,标志复位 mbInitialComputations=false; }
- 将特征点分配到对应的网格中,这主要是为了后续加速特征匹配,这个具体的用法我们后续在特征匹配阶段再提。
// 将特征点分配到图像网格中 AssignFeaturesToGrid();