ORB_SLAM2原理及代码解析:MapPoint::ComputeDistinctiveDescriptors() 函数
目录
1 作用
2 位置及代码
3 原理解析
3.1 参数及含义
3.1 observations
3.2 vDescriptors.reserve(observations.size());
3.3 if(!pKF->isBad())
3.4 vDescriptors.push_back(pKF->mDescriptors.row(mit->second));
3.5 float Distances[N][N];
3.6 DescriptorDistance()函数
3.7 Distances[i][j]=distij;
1 作用
每个地图点可能被多个关键帧观察到,每个关键帧有自己的 ORB 描述子。由于噪声、视角和光照变化,同一个地图点在不同关键帧的描述子可能略有差异。该函数为MapPoint选择一个最具代表性的描述子,用于之后的匹配。
思路:
MapPoint → 关键帧 → 收集描述子 → 计算距离 → 选中代表性描述子 → 更新 mDescriptor
2 位置及代码
(1)声明:MapPoint.h
void ComputeDistinctiveDescriptors();
(2)定义:MapPoint.cc
void MapPoint::ComputeDistinctiveDescriptors() {// Retrieve all observed descriptorsvector<cv::Mat> vDescriptors;map<KeyFrame*,size_t> observations;{unique_lock<mutex> lock1(mMutexFeatures);if(mbBad)return;observations=mObservations;}if(observations.empty())return;vDescriptors.reserve(observations.size());for(map<KeyFrame*,size_t>::iterator mit=observations.begin(), mend=observations.end(); mit!=mend; mit++){KeyFrame* pKF = mit->first;if(!pKF->isBad())vDescriptors.push_back(pKF->mDescriptors.row(mit->second));}if(vDescriptors.empty())return;// Compute distances between themconst size_t N = vDescriptors.size();float Distances[N][N];for(size_t i=0;i<N;i++){Distances[i][i]=0;for(size_t j=i+1;j<N;j++){int distij = ORBmatcher::DescriptorDistance(vDescriptors[i],vDescriptors[j]);Distances[i][j]=distij;Distances[j][i]=distij;}}// Take the descriptor with least median distance to the restint BestMedian = INT_MAX;int BestIdx = 0;for(size_t i=0;i<N;i++){vector<int> vDists(Distances[i],Distances[i]+N);sort(vDists.begin(),vDists.end());int median = vDists[0.5*(N-1)];if(median<BestMedian){BestMedian = median;BestIdx = i;}}{unique_lock<mutex> lock(mMutexFeatures);mDescriptor = vDescriptors[BestIdx].clone();} }
3 原理解析
3.1 参数及含义
3.1 observations
存储的是地图点被哪些关键帧观测到了。
例:
假设有一个
MapPoint pMP
,它在两个关键帧里被观测到了:在
KeyFrame KF1
的第 10 个特征点,在KeyFrame KF2
的第 35 个特征点则observations里面存的是KF1 → 10,KF2 → 35。
3.2 vDescriptors.reserve(observations.size());
预先分配空间,容量等于观测数量。
3.3 if(!pKF->isBad())
如果是坏帧,在回环检测、局部优化时会被标记出来。
3.4 vDescriptors.push_back(pKF->mDescriptors.row(mit->second));
(1)pKF->mDescriptors.row(mit->second)
该 MapPoint 在该关键帧里的 ORB 描述子。
3.5 float Distances[N][N];
Distances[i][j]
= 第i
个描述子 和 第j
个描述子之间的 Hamming 距离。
3.6 DescriptorDistance()函数
(1)声明:ORBmatcher.h
// Computes the Hamming distance between two ORB descriptorsstatic int DescriptorDistance(const cv::Mat &a, const cv::Mat &b);
(2)定义:ORBmatcher.cc
int ORBmatcher::DescriptorDistance(const cv::Mat &a, const cv::Mat &b) {const int *pa = a.ptr<int32_t>();const int *pb = b.ptr<int32_t>();int dist=0;for(int i=0; i<8; i++, pa++, pb++){unsigned int v = *pa ^ *pb; //按位异或XORv = v - ((v >> 1) & 0x55555555); //0x55555555 = 二进制 0101...0101,// 把32位按 2 位一组,计算每组里 1 的个数。v = (v & 0x33333333) + ((v >> 2) & 0x33333333); //把上一步的结果按 4 位一组,计算每组的 1 的个数。dist += (((v + (v >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;//统计成 8 位一组,最后把结果压缩成一个字节,>> 24 把统计出来的 1 的总数移到最低位。}return dist; }
3.7 Distances[i][j]=distij;
i到j的汉明距离。