ORBSLAM特征点提取概要(以rgbd为例):
由rgbd_tum.cc的
SLAM.TrackRGBD(imRGB,imD,tframe);
到
Tracking.cc的cv::Mat Tracking::GrabImageRGBD(const cv::Mat &imRGB,const cv::Mat &imD, const double ×tamp)
中的
mCurrentFrame = Frame(mImGray,mImDepth,timestamp,mpORBextractorLeft,mpORBVocabulary,mK,mDistCoef,mbf,mThDepth);
到
Frame.cc的构造函数中的
ExtractORB(0,imGray);
到
void Frame::ExtractORB(int flag, const cv::Mat &im)
{
if(flag==0)
(*mpORBextractorLeft)(im,cv::Mat(),mvKeys,mDescriptors);
else
(*mpORBextractorRight)(im,cv::Mat(),mvKeysRight,mDescriptorsRight);
}
到此重载()运算符,其中mpORBextractorLeft在Tracking的构造函数中定义。
特征点提取主要是在void ORBextractor::operator()( InputArray _image, InputArray _mask, vector<KeyPoint>& _keypoints,OutputArray _descriptors)
这个重载函数中进行的!
1.先对图像构建金字塔,一共8层,在以下函数中实现。
void ORBextractor::ComputePyramid(cv::Mat image)
每一层金字塔存放到此处:
mvImagePyramid[level]
2.FAST关键点提取
对每一层金字塔根据一定的范围(w=30),在每个网格中按照阈值进行FAST特征点的提取
ORBextractor.iniThFAST: 20
ORBextractor.minThFAST: 7
首先按照每个网格提取20个特征点的标准,若无法满足,则改为7个特征点。(在void ORBextractor::ComputeKeyPointsOctTree(vector<vector >& allKeypoints)函数中)
特征点存放到此处:
vector<cv::KeyPoint> vToDistributeKeys;
vToDistributeKeys.reserve(nfeatures*10);
然后进行四叉树存储
keypoints = DistributeOctTree(vToDistributeKeys, minBorderX, maxBorderX, minBorderY, maxBorderY,mnFeaturesPerLevel[level], level);
存储时,若每个节点特征点数目为1,或者特征点数量已经满足要求,则停止切分,何为以满足要求?
在ORBextractor::ORBextractor构造函数中,如下所示,mnFeaturesPerLevel[level]为每一层需要提取的特征点数量,是由一些比例计算出来的,每一层提取的特征点数目不一样,不过8层mnFeaturesPerLevel之和接近ORBextractor.nFeatures: 1000
mnFeaturesPerLevel.resize(nlevels);
float factor = 1.0f / scaleFactor;
float nDesiredFeaturesPerScale = nfeatures*(1 - factor)/(1 - (float)pow((double)factor, (double)nlevels));
int sumFeatures = 0;
for( int level = 0; level < nlevels-1; level++ )
{
mnFeaturesPerLevel[level] = cvRound(nDesiredFeaturesPerScale);
sumFeatures += mnFeaturesPerLevel[level];
nDesiredFeaturesPerScale *= factor;
}
在四叉数(vectorcv::KeyPoint ORBextractor::DistributeOctTree)的代码中N即为mnFeaturesPerLevel[level]
if((int)lNodes.size()>=N || (int)lNodes.size()==prevSize)
{
bFinish = true;
}
此为“若特征点数量已经满足要求,或者node的数目和上一次相比没有变化,即不能再分裂,则停止切分”
以下为一整图片的测试结果:
Before tree:1162
After tree:217
Before tree:882
After tree:181
Before tree:650
After tree:151
Before tree:496
After tree:127
Before tree:379
After tree:105
Before tree:274
After tree:89
Before tree:203
After tree:73
Before tree:160
After tree:62
Before tree是每一层中vToDistributeKeys的数目,After tree是keypoints的数目。
最终在void ORBextractor::operator()函数中输出每一层经过放大后的特征点位置,一共为1000左右
本文参考了
一步步带你看懂orbslam2源码–orb特征点提取(二),
认真的虎ORBSLAM2源码解读(四):图解ORB特征提取ORBextractor,此二文叙述详细,可习之。
若有不当之处,请指出,共同进步,谢谢