ORB-SLAM(六)MapPoint與Map


地圖點可以通過關鍵幀來構造,也可以通過普通幀構造,但是最終,必須是和關鍵幀對應的,通過普通幀構造的地圖點只是臨時被Tracking用來追蹤用的。

構造函數(地圖點3D坐標及其參考幀):

// 參考幀是關鍵幀,該地圖點將於許多幀關鍵幀對應,建立關鍵幀之間的共視關系
MapPoint::MapPoint(const cv::Mat &Pos, KeyFrame *pRefKF, Map* pMap)
// 參考幀是普通幀,該地圖點只與當前普通幀的特征點對應
MapPoint::MapPoint(const cv::Mat &Pos, Map* pMap, Frame* pFrame, const int &idxF)

地圖點和關鍵幀之間的觀測關系是最重要的,參考關鍵幀是哪一幀,該地圖點被哪些關鍵幀觀測到,對應的哪個(idx)特征點?通過兩個成員維護:

std::map<KeyFrame*,size_t> mObservations;
// 觀測到該地圖點的相機數
int nObs; 

添加地圖點觀測:能夠觀測到同一個地圖點的關鍵幀之間存在共視關系

void MapPoint::AddObservation(KeyFrame* pKF, size_t idx);

刪除地圖點觀測:從當前地圖點的mObservation和nObs成員中刪掉對應關鍵幀觀測關系,若該關鍵幀恰好是參考幀,則需要重新指定。當觀測相機數小於等於2時,該地圖點需要剔除。刪掉觀測關系,和刪掉地圖點(以及替換地圖點),需要區分開!

void MapPoint::EraseObservation(KeyFrame* pKF);

剔除MapPoint不僅需要刪掉地圖點中維護的關鍵幀觀測關系,還需要刪掉對應關鍵中對應的地圖點,以及Map中該地圖點的內存:

void KeyFrame::EraseMapPointMatch(const size_t &idx)
{
    unique_lock<mutex> lock(mMutexFeatures);
    mvpMapPoints[idx]=static_cast<MapPoint*>(NULL);
}

mpMap->EraseMapPoint(this);

下面是一個重要的函數:

void MapPoint::Replace(MapPoint* pMP);

將當前地圖點(this),替換成pMp。主要使用在閉環時,調整地圖點和關鍵幀,建立新的關系:

關鍵幀將聯系的this替換成pMap:

pKF->ReplaceMapPointMatch(mit->second, pMP);// KeyFrame中mit->second索引對應的地圖點,用pMP替換掉原來的this
pMP->AddObservation(pKF,mit->second);// pMp地圖點添加觀測關鍵幀
// 刪掉Map中該地圖點
mpMap->EraseMapPoint(this);

無論是SetBadFlag()還是Replace(),當前地圖點的mbBad標志都被記為true,表明當前地圖點是個壞點。

visible和found的區別:該地圖點在視野范圍內,該地圖點有對應特征點的幀數。通常來說,found的地圖點一定是visible的,但是visible的地圖點很可能not found

float MapPoint::GetFoundRatio()
{
    unique_lock<mutex> lock(mMutexFeatures);
    return static_cast<float>(mnFound)/mnVisible;
}

GetFoundRatio低表示該地圖點在很多關鍵幀的視野范圍內,但是沒有匹配上很多特征點。

最后是MapPoint中幾個比較重要的函數:

void MapPoint::ComputeDistinctiveDescriptors();
void MapPoint::UpdateNormalAndDepth();
int MapPoint::PredictScale(const float &currentDist, KeyFrame* pKF);

1. 計算地圖點描述子:

從mObservations中獲取觀察到當前地圖點的關鍵幀及對應描述子,描述子放入vDescriptor描述子向量組成的向量中。在這些描述子中,選擇距離(類似hamming距離)其他描述子最近的(中值距離最小,看代碼去體會一下是什么意思)作為地圖點的描述子mDescriptor。

2. 計算地圖點平均觀測方向和深度

地圖點到所有觀測到的關鍵幀相機中心向量,歸一化后相加。

深度范圍:地圖點到參考幀(只有一幀)相機中心距離,乘上參考幀中描述子獲取時金字塔放大尺度,得到最大距離mfMaxDistance;最大距離除以整個金字塔最高層的放大尺度得到最小距離mfMinDistance。通常來說,距離較近的地圖點,將在金字塔層數較高的地方提取出,距離較遠的地圖點,在金字塔層數較低的地方提取出(金字塔層數越低,分辨率越高,才能識別出遠點)。因此通過地圖點的信息(主要是對應描述子),我們可以獲得該地圖點對應的金字塔層級:

const int level = pRefKF->mvKeysUn[observations[pRefKF]].octave;

從而預測該地圖點在什么距離范圍內能夠被觀測到!

3. int MapPoint::PredictScale(const float &currentDist, KeyFrame* pKF)

注意金字塔ScaleFactor和距離的關系:當前特征點對應ScaleFactor為1.2的意思是:圖片分辨率下降1.2倍后,可以提取出該特征點(分辨率更高時,肯定也可以提取出,這里取金字塔中能夠提取出該特征點最高層級作為該特征點的層級)

同時,由當前特征點的距離,可以推測所在層級。

 

Map則比較簡單,主要負責維護其中關鍵幀和地圖點容器,設置參考地圖點用於繪圖:

std::set<MapPoint*> mspMapPoints;
std::set<KeyFrame*> mspKeyFrames;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM