//我們在從金字塔的圖像中獲取特征點時為每一個特征點計算了描述子
//現在看看如何計算一個空間的地圖點的描述子
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用來存儲這些所有與可以觀測到該地圖點的特征點的描述子vDescriptors.reserve(observations.size());for(map<KeyFrame*,size_t>::iterator mit=observations.begin(), mend=observations.end(); mit!=mend; mit++){//獲取可以觀測到此地圖點的所有關鍵幀KeyFrame* pKF = mit->first;//然后獲取,在該關鍵幀下與該地圖點對應的特征點的描述子//vDescriptors中存儲了所有的那些可以觀測到該地圖點的圖像上的與之對應的特征點的描述子。if(!pKF->isBad())vDescriptors.push_back(pKF->mDescriptors.row(mit->second));}if(vDescriptors.empty())return;// Compute distances between themconst size_t N = vDescriptors.size();//Distances是一個N*N的二維數組float Distances[N][N];//計算任意兩個描述子之間的海明距離//Distances[N][N]是一個對稱矩陣并且對角線上的元素都為0for(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 rest//需要找到的是一個最小的中值距離int BestMedian = INT_MAX;int BestIdx = 0;for(size_t i=0;i<N;i++){//將Distences中的每一行單獨拿出來//因為在這個矩陣中第i行表示,第i個描述子與其他所有描述子之間的海明距離vector<int> vDists(Distances[i],Distances[i]+N);//將這些距離進行排序sort(vDists.begin(),vDists.end());//經過排序之后都要取排序后的中值int median = vDists[0.5*(N-1)];//遍歷Distances中的所有行找到一個最小的中值,那么該描述子就可以代表這個地圖點的描述子if(median<BestMedian){BestMedian = median;BestIdx = i;}}{unique_lock<mutex> lock(mMutexFeatures);mDescriptor = vDescriptors[BestIdx].clone();}
}
Take the descriptor with least median distance to the rest
就是在所有的描述子中找到那個與其他所有的描述子之間的距離的中值最小的描述子作為該地圖點的描述子,
這里選擇的是中值作為衡量標準。