目录
一、函数作用
二、函数步骤
三、code
四、函数解析
一、函数作用
计算地图点最具代表性的描述子。
由于一个地图点会被许多相机观测到,因此在插入关键帧后,需要判断是否更新代表当前点的描述子,先获得当前点的所有描述子,然后计算描述子之间的两两距离,最好的描述子与其他描述子应该具有最小的距离中值。
二、函数步骤
Step 1 获取该地图点所有有效的观测关键帧信息
Step 2 遍历观测到该地图点的所有关键帧,对应的orb描述子,放到向量vDescriptors中
Step 3 计算这些描述子两两之间的距离.
Step 4 选择最有代表性的描述子,它与其他描述子应该具有最小的距离中值
三、code
void MapPoint::ComputeDistinctiveDescriptors() { // Retrieve all observed descriptors vector<cv::Mat> vDescriptors; map<KeyFrame*,size_t> observations; // Step 1 获取该地图点所有有效的观测关键帧信息 { unique_lock<mutex> lock1(mMutexFeatures); if(mbBad) return; observations=mObservations; } if(observations.empty()) return; vDescriptors.reserve(observations.size()); // Step 2 遍历观测到该地图点的所有关键帧,对应的orb描述子,放到向量vDescriptors中 for(map<KeyFrame*,size_t>::iterator mit=observations.begin(), mend=observations.end(); mit!=mend; mit++) { // mit->first取观测到该地图点的关键帧 // mit->second取该地图点在关键帧中的索引 KeyFrame* pKF = mit->first; if(!pKF->isBad()) // 取对应的描述子向量 vDescriptors.push_back(pKF->mDescriptors.row(mit->second)); } if(vDescriptors.empty()) return; // Compute distances between them // Step 3 计算这些描述子两两之间的距离 // N表示为一共多少个描述子 const size_t N = vDescriptors.size(); // 将Distances表述成一个对称的矩阵 // float Distances[N][N]; std::vector<std::vector<float> > Distances; Distances.resize(N, vector<float>(N, 0)); for (size_t i = 0; i<N; i++) { // 和自己的距离当然是0 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 rest // Step 4 选择最有代表性的描述子,它与其他描述子应该具有最小的距离中值 int BestMedian = INT_MAX; // 记录最小的中值 int BestIdx = 0; // 最小中值对应的索引 for(size_t i=0;i<N;i++) { // 第i个描述子到其它所有描述子之间的距离 // vector<int> vDists(Distances[i],Distances[i]+N); vector<int> vDists(Distances[i].begin(), Distances[i].end()); 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(); } }
四、函数解析
判断该地图点是否是bad地图点,若不是则获取这个地图点的所有观测信息用临时变量observations保存,它是个map<KeyFrame*,size_t>类型的变量。
存储的该地图点可以被哪些关键帧KeyFrame观测到,在这些关键帧中的索引size_t是多少。
遍历观测到该地图点的所有关键帧observations,对应的orb描述子,放到向量vDescriptors中。
计算这些描述子的两两距离存储到矩阵Distances中。
假设这里的矩阵是4*4的。
即观测到该地图点的帧有4个,取出它们四个的描述子,=0,即第一个描述子和第一个描述子的距离为0(自己和自己比较当然为0),,它们的数值等于第一个描述子和第二个描述子的汉明距离。
我们有了描述子矩阵后,我们遍历每一行描述子矩阵,寻找每一行的距离中值,拿第一行来说,的中位数,遍历所有行,找到最小行的中位数以及它的行索引。
将这个地图点最具代表性的描述子设置为最小的行的中位数索引对应的描述子。