通俗易懂理解ORBSLAM2建圖模塊

一豁翎、通俗易懂理解LocalMapping類==建圖(抓要點 切題 Done)

1.參考資料:

ORB SLAM2源碼解讀(十):LocalMapping類
[1] 深藍學(xué)院 視覺SLAM開源代碼論文帶讀(ORB_SLAM2)local mapping部分

2.主要函數(shù):
void LocalMapping::ProcessNewKeyFrame() 
MapPointCulling();
CreateNewMapPoints()
SearchInNeighbors();
Optimizer::LocalBundleAdjustment(mpCurrentKeyFrame, &mbAbortBA,
                                           mpMap);
KeyFrameCulling();

二噪馏、[w1]通俗易懂理解插入關(guān)鍵幀LocalMapping::ProcessNewKeyFrame

1.插入關(guān)鍵幀做了什么,具體流程是什么(W1)

mpCurrentKeyFrame = mlNewKeyFrames.front();
mlNewKeyFrames.pop_front();

(1)從隊列中取出一個關(guān)鍵幀
(2)計算當(dāng)前關(guān)鍵幀的詞袋信息
(只要詞袋向量是空的或者特征點向量是空的启泣,將一幀的描述子轉(zhuǎn)成詞袋向量和特征向量,具體怎么轉(zhuǎn)的skip)
(3)獲取關(guān)鍵幀對應(yīng)的地圖點
對于每個地圖點粘姜,如果該地圖點不是isBad的話
如果地圖點不包含當(dāng)前關(guān)鍵幀的觀測形入,那么就1)添加地圖點觀測,包含當(dāng)前幀和當(dāng)前幀對應(yīng)的特征點id藕赞,2)更新地圖點的平均觀測方向和最大最小距離成肘,這里的參考關(guān)鍵幀是什么?3)更新地圖點的最佳描述子
(4)更新當(dāng)前關(guān)鍵幀的共視圖和生成樹

mpCurrentKeyFrame->UpdateConnections();

(5)將關(guān)鍵幀插入到地圖中

=========================================================================
題目:一個地圖點的參考關(guān)鍵幀是什么?一個地圖點的最大最小距離怎么算的斧蜕。平均觀測方向是什么双霍?
參考:源碼
思路:
1.思路:

參考關(guān)鍵幀:第一次觀測到該地圖點的關(guān)鍵幀。
平均觀測方向:地圖點的位置減去觀測到該地圖點的關(guān)鍵幀的位置的單位向量求和再求平均惩激。

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):

見上

要點程序:
其他:
=========================================================================
題目:什么叫共視圖
參考:
思路:
1.思路:

通俗易懂理解KeyFrame類問題 要點(要點切題 Done)

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
=========================================================================
題目:什么叫地圖點的最佳描述子
參考:
void MapPoint::ComputeDistinctiveDescriptors()
思路:
1.思路:

首先一個地圖被多幀觀測店煞,一個地圖點對應(yīng)每幀有一個特征點,他的描述子是怎樣的风钻,獲取多幀觀測的全部描述子集合顷蟀。然后計算一個距離矩陣,每一行每一列都是對應(yīng)的描述子骡技。然后取出每一行鸣个,得到這一行的距離中值(第i行就是第i個描述子和其他描述子的距離)羞反,比較全部行,得到最小的距離中值囤萤,對應(yīng)的第i行的描述子就是最佳的描述子昼窗。

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
要點程序:
void function() {

    vector<vector<float>> vDistances;
    vDistances.resize(N, vector<float>(N, 0));
    
    for (int i = 0;i < N; i++) {
        vDistances[i][i] = 0;
        for (int j = i + 1; j < N; j++) {
            distanceij = DescriptorDistance(vDescriptor[i], vDescriptor[j]);
            vDistances[i][j] = distanceij;
            vDistances[j][i] = distanceij;
        }
    }
    
    int best_dist = INT_MAX;
    int best_idx;
    
    for (int i = 0; i < N; i++) {
        vector<int> vDistance(vDistances[i].begin(), vDistances[i].end());
        sort(vDistance.begin(), vDistance.end());
        
        int median_distance = vDistance[0.5 * (N - 1)];
        if (median_distance < best_dist) {
            best_dist = median_distance;
            best_idx = i;
        }   
    } 
}
其他:

三、通俗易懂理解地圖點刪除LocalMapping::MapPointCulling()

2.刪除地圖點做了什么涛舍,具體流程是什么

RGBD或者雙目情況下ProcessNewKeyFrame產(chǎn)生的地圖點對觀測不夠的進行setBagFlag澄惊,另一種情況下是CreateNewMapPoints函數(shù)也有mlpRecentAddedMapPoints,產(chǎn)生的地圖點對觀測不夠的進行setBagFlag
setBagFlag就是刪除地圖點的觀測

=========================================================================
題目:ProcessNewKeyFrame中mlpRecentAddedMapPoints的push的條件
參考:
思路:
1.思路:

(1)RGBD或者雙目情況下,當(dāng)前關(guān)鍵幀生成的地圖點.這個地圖點會被當(dāng)前關(guān)鍵幀觀測到,
這個會push到mlpRecentAddedMapPoints富雅。
(2)單目情況下,關(guān)鍵幀的地圖點基本是NULL的情況,因為還沒3角化,會不會有匹配產(chǎn)生的地圖點呢掸驱?
會,但是也不會進入這個mlpRecentAddedMapPoints没佑。
單目情況下毕贼,地圖點沒有被當(dāng)前幀觀測到,需要添加當(dāng)前幀的觀測。

=========================================================================
題目:地圖點刪除函數(shù)void LocalMapping::MapPointCulling(地圖點刪除是對雙目和RGBD而言的)蛤奢。erase到底第什么意思鬼癣?和setBadFlag有什么區(qū)別?
參考:
思路:
1.思路:

setBadFlag到底干了啥?把mappoint所有觀測給剔除掉啤贩。得有觀測!!!

(1)pMP->GetFoundRatio() < 0.25f這是什么意思呢??? Found和Visible有什么區(qū)別呢???
found:
單目來說待秃,在TrackLocalMap的Optimization后,如果當(dāng)前幀的地圖點不是outlier的話瓜晤,那就增加1锥余。由于當(dāng)前幀的MapPoints可以被當(dāng)前幀觀測到,所以其被觀測統(tǒng)計量+1
單目情況下痢掠,當(dāng)前幀的地圖點應(yīng)該是NULL的情況驱犹,如果匹配上了,該關(guān)鍵幀對應(yīng)的地圖點就不為NULL了足画, 他就有深度了雄驹。對的。

Visible:
在TrackLocalMap搜索局部地圖點Tracking::SearchLocalPoints()進行匹配的時候淹辞,
如果地圖點(局部地圖點和當(dāng)前幀的地圖點)在當(dāng)前幀的視野范圍內(nèi)医舆,那這個地圖點可見次數(shù)就+1.

(2)(((int)nCurrentKFid - (int)pMP->mnFirstKFid) >= 3) 這個是一個質(zhì)量很好的點。
卻要 erase掉象缀,這是什么回事?可以不erase蔬将,不影響。

因為這個函數(shù)void LocalMapping::MapPointCulling是為雙目和RGB-D服務(wù)的,如果是壞點的話央星,
(怎么判斷是否是外點霞怀,外點的話就沒有觀測了么?)
有觀測質(zhì)量不好是要剔除莉给,所以要setBadFlag
好的點直接erase,這是什么意思呢毙石?
mlpRecentAddedMapPoints push完廉沮,然后進行選擇,然后它后續(xù)用來干啥呢徐矩?后續(xù)沒有用到滞时,只是用來管理地圖點。
所以他的功能就是對觀測次數(shù)不滿足條件以及found/visible比例小的進行setbadflag

結(jié)論雙目和RGB-D情況下滤灯,對觀測次數(shù)不滿足條件以及found/visible比例小的進行setbadflag坪稽。或者單目情況下CreateNewMapPoints產(chǎn)生的地圖點進行setbadflag力喷。

=========================================================================
題目:CreateNewMapPoints函數(shù)也有mlpRecentAddedMapPoints,那么什么時候再次調(diào)用MapPointCulling呢刽漂?
參考:
思路:
1.思路:

這個會在下一次中調(diào)用MapPointCulling把觀測不合格的地圖點setbagflag.

=========================================================================
題目:刪除的地圖點是在哪里引入的。
參考:
思路:
1.思路:

雙目和RGB-D下ProcessNewKeyFrame中mlpRecentAddedMapPoints
單目只有在CreateNewMapPoints中的mlpRecentAddedMapPoints

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
=========================================================================
題目:地圖點找到(mnFound)和可見(mnVisible)是什么意思弟孟?
參考:
思路:
1.思路:

mnFound:

void MapPoint::IncreaseFound(int n) {
  unique_lock<mutex> lock(mMutexFeatures);
  mnFound += n;
}

[1]在不考慮閉環(huán)的情況下,MapPoint_Replace函數(shù)不起作用样悟。

void MapPoint::Replace(MapPoint* pMP) 

[2]IncreaseFound函數(shù)在Tracking中是什么情況下被調(diào)用的呢拂募?
<1>定位模式下。TODO暫不討論
<2>在TrackLocalMap的Optimization后窟她,如果當(dāng)前幀的地圖點不是outlier的話陈症,那就增加1。由于當(dāng)前幀的MapPoints可以被當(dāng)前幀觀測到震糖,其被觀測統(tǒng)計量加1录肯。單目情況下,當(dāng)前幀的地圖點應(yīng)該是NULL的情況吊说,如果匹配上了论咏,該關(guān)鍵幀對應(yīng)的地圖點就不為NULL了, 他就有深度了颁井。對的厅贪。
[3]結(jié)論:在TrackLocalMap的Optimization后,如果當(dāng)前幀的地圖點不是outlier的話雅宾,那就增加1养涮。由于當(dāng)前幀的MapPoints可以被當(dāng)前幀觀測到,所以其被觀測統(tǒng)計量+1
單目情況下眉抬,當(dāng)前幀的地圖點應(yīng)該是NULL的情況贯吓,如果匹配上了,該關(guān)鍵幀對應(yīng)的地圖點就不為NULL了蜀变, 他就有深度了悄谐。對的。那么相應(yīng)的這個地圖點就被當(dāng)前幀觀測到昏苏。

SearchByProjection
//保存結(jié)果: 為Frame中的特征點增加對應(yīng)的MapPoint
F.mvpMapPoints[bestIdx] = pMP;

mnVisible:
在TrackLocalMap搜索局部地圖點Tracking::SearchLocalPoints()進行匹配的時候尊沸,如果地圖點(局部地圖點和當(dāng)前幀的地圖點)在當(dāng)前幀的視野范圍內(nèi)威沫,那這個地圖點可見次數(shù)就+1.

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
=========================================================================
題目:關(guān)鍵幀id和幀id是不一樣的吧
參考:
思路:

是的,他們沒有繼承的關(guān)系洼专,各自有自己的id棒掠,都是連續(xù)的
KeyFrame構(gòu)造函數(shù)中:

  // 獲取id
  mnId = nNextId++;
1.思路:
2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
=========================================================================
題目:從建立該地圖點開始,到目前為止經(jīng)過了3個關(guān)鍵幀還在屁商,為什么要放棄對該mappoint的檢測?
參考:
思路:

無所謂的烟很。

1.思路:
2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):

四、[射線][w1]通俗易懂理解地圖點創(chuàng)建LocalMapping::CreateNewMapPoints()

3.創(chuàng)建地圖點做了什么蜡镶,具體流程是什么

[1]找到當(dāng)前關(guān)鍵幀共視程度最強的20幀關(guān)鍵幀
[2]計算當(dāng)前關(guān)鍵幀和1個共視關(guān)鍵幀的基本矩陣
[3]通過極線約束限制匹配的搜索范圍雾袱,進行特征點的匹配[特征點對應(yīng)的地圖點是NULL]
[4]三角化生成地圖點

=========================================================================
題目:F21和F12各是什么意思,為什么是相反的官还。
參考:
思路:
1.思路:

F12:當(dāng)前幀1,另一個共視幀2芹橡,正向解算F12,
// Epipolar line in second image l = x1'F12 = [a b c]
// 求出kp1在pKF2上對應(yīng)的極線

bool ORBmatcher::CheckDistEpipolarLine(const cv::KeyPoint &kp1,
                                       const cv::KeyPoint &kp2,
                                       const cv::Mat &F12,
                                       const KeyFrame *pKF2)

初始化部分
F21是從幀1到幀2望伦,將幀1上的點投到幀2上
// Step 2.2 計算 img1 上的點在 img2 上投影得到的極線 l2 = F21 * p1 =
// (a2,b2,c2)

float Initializer::CheckFundamental(
    const cv::Mat &F21,  //當(dāng)前幀和參考幀之間的基礎(chǔ)矩陣
    vector<bool> &vbMatchesInliers,  //匹配的特征點對屬于inliers的標(biāo)記
    float sigma) 
2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):

// 需要好好理解!!!

  /*
   * 這里可以這樣理解:世界坐標(biāo)系原點記為W林说,關(guān)鍵幀1和關(guān)鍵幀2的相機光心分別記為O1
   * O2. 根據(jù)Frame類中的有關(guān)說明,在世界坐標(biāo)系下 這兩幀相機光心的坐標(biāo)可以記為:
   * O1=-Rw1*t1w
   * O2=-RW2*t2w
   * 那么 t12 本質(zhì)上描述的是從O2 ->
   * O1相機光心所產(chǎn)生的位移屯伞,當(dāng)在世界坐標(biāo)系下的時候可以寫成: t12(w) = O2-O1 =
   * -Rw2*t2w+Rw1*t1w
   * 要放在O1坐標(biāo)系下表示的話腿箩,需要進行一個旋轉(zhuǎn)變換(注意不要有平移變換,這個是對點才用的劣摇,如果對向量也應(yīng)用的話很明顯t12的長度都變了)
   * t12(1) = R1w*t12(w)
   *        = -R1w*Rw2*t2w+Rw1*R1w*t1w
   *        = -R1w*Rw2+t2w+t1w
   * 就是下面這行代碼中寫的:
   */
要點程序:

基本矩陣的構(gòu)造

// 根據(jù)兩關(guān)鍵幀的姿態(tài)計算兩個關(guān)鍵幀之間的基本矩陣
cv::Mat LocalMapping::ComputeF12(KeyFrame *&pKF1, KeyFrame *&pKF2) {
  // 先構(gòu)造兩幀之間的R12,t12

  cv::Mat R1w = pKF1->GetRotation();
  cv::Mat t1w = pKF1->GetTranslation();
  cv::Mat R2w = pKF2->GetRotation();
  cv::Mat t2w = pKF2->GetTranslation();

  cv::Mat R12 = R1w * R2w.t();

  /*
   * 這里可以這樣理解:世界坐標(biāo)系原點記為W珠移,關(guān)鍵幀1和關(guān)鍵幀2的相機光心分別記為O1
   * O2. 根據(jù)Frame類中的有關(guān)說明,在世界坐標(biāo)系下 這兩幀相機光心的坐標(biāo)可以記為:
   * O1=-Rw1*t1w
   * O2=-RW2*t2w
   * 那么 t12 本質(zhì)上描述的是從O2 ->
   * O1相機光心所產(chǎn)生的位移末融,當(dāng)在世界坐標(biāo)系下的時候可以寫成: t12(w) = O2-O1 =
   * -Rw2*t2w+Rw1*t1w
   * 要放在O1坐標(biāo)系下表示的話钧惧,需要進行一個旋轉(zhuǎn)變換(注意不要有平移變換,這個是對點才用的滑潘,如果對向量也應(yīng)用的話很明顯t12的長度都變了)
   * t12(1) = R1w*t12(w)
   *        = -R1w*Rw2*t2w+Rw1*R1w*t1w
   *        = -R1w*Rw2+t2w+t1w
   * 就是下面這行代碼中寫的:
   */

  cv::Mat t12 = -R1w * R2w.t() * t2w + t1w;

  // 得到 t12 的反對稱矩陣
  cv::Mat t12x = SkewSymmetricMatrix(t12);

  const cv::Mat &K1 = pKF1->mK;
  const cv::Mat &K2 = pKF2->mK;

  // Essential Matrix: t12叉乘R12
  // Fundamental Matrix: inv(K1)*E*inv(K2)
  return K1.t().inv() * t12x * R12 * K2.inv();
}
void Initializer::FindFundamental(vector<bool> &vbMatchesInliers, float &score,
                                  cv::Mat &F21)

//F21:從參考幀到當(dāng)前幀的基礎(chǔ)矩陣

//從F恢復(fù)R t
bool Initializer::ReconstructF(
    vector<bool> &vbMatchesInliers,  //匹配好的特征點對的Inliers標(biāo)記
    cv::Mat &F21,                    //從參考幀到當(dāng)前幀的基礎(chǔ)矩陣
    cv::Mat &K,                      //相機的內(nèi)參數(shù)矩陣
    cv::Mat &R21,  //計算好的相機從參考幀到當(dāng)前幀的旋轉(zhuǎn)
    cv::Mat &t21,  //計算好的相機從參考幀到當(dāng)前幀的平移
    vector<cv::Point3f> &vP3D,  //三角化測量之后的特征點的空間坐標(biāo)
    vector<bool> &vbTriangulated,  //某個特征點是否被三角化了的標(biāo)記
    float minParallax,  //認(rèn)為三角化測量有效的最小視差角
    int minTriangulated)  //認(rèn)為使用三角化測量進行數(shù)據(jù)判斷的最小測量點數(shù)量
=========================================================================
題目:如何利用極線約束進行特征點匹配
參考:
int ORBmatcher::SearchForTriangulation(
    KeyFrame *pKF1, KeyFrame *pKF2, cv::Mat F12,
    vector<pair<size_t, size_t> > &vMatchedPairs, const bool bOnlyStereo) 
思路:
1.思路:

PS:我認(rèn)為是像素垢乙。

// 檢查極線距離是否符合要求,用在初始化時根據(jù)兩個初始關(guān)鍵幀計算地圖點的時候
bool ORBmatcher::CheckDistEpipolarLine(const cv::KeyPoint &kp1,
                                       const cv::KeyPoint &kp2,
                                       const cv::Mat &F12,
                                       const KeyFrame *pKF2)

越上層,分辨率越低语卤,不確定性范圍越大

越上層追逮,分辨率越低,不確定性范圍越大粹舵。
總結(jié):將pKF1圖像的每個特征點與pKF2圖像同一node節(jié)點的所有特征點依次檢測钮孵,判斷是否滿足對極幾何約束(點到極線的距離,小于設(shè)定的閾值)眼滤,滿足約束就是匹配的特征點巴席,找到滿足對極約束并且描述子之間的距離最小的建立匹配對。然后利用旋轉(zhuǎn)直方圖去除誤匹配诅需。

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
要點程序:
=========================================================================
題目: 如何三角化建立地圖點呢漾唉?
參考:

第6講 視覺前端(切題 Done) TODO

思路:
1.思路:

射線公式:

兩條射線的夾角大于3.6度


三角化知識荧库,參考第6講 視覺前端(切題 Done) TODO
一個用的是投影矩陣,一個是用變換矩陣赵刑,一模一樣分衫。
[1]生成的3D點是否在2幀前方,不在的話就放棄這個點
[2]計算3D點在當(dāng)前關(guān)鍵幀下的重投影誤差
[3]計算3D點在另一個關(guān)鍵幀下的重投影誤差
[4]計算距離的連續(xù)性,(沒有太明白般此,經(jīng)驗吧蚪战,TODO)
[5]增加地圖點,計算地圖點最佳描述子铐懊,計算地圖點平均方向和最大最小距離邀桑。

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
要點程序:

五、[背][w1]通俗易懂理解地圖點融合LocalMapping::SearchInNeighbors()

關(guān)鍵是:地圖點和特征點匹配上了科乎,地圖點添加觀測和關(guān)鍵幀添加地圖點壁畸。

=========================================================================
題目:創(chuàng)建地圖點之后,如何進行地圖點融合喜喂?
參考:
思路:
1.思路:

[1]找到當(dāng)前關(guān)鍵幀共視程度最強的20幀相鄰幀

    // Extend to some second neighbors
    const vector<KeyFrame *> vpSecondNeighKFs =
        pKFi->GetBestCovisibilityKeyFrames(5);

[2]Extend to some second neighbors
存入一級和對應(yīng)的二級相鄰幀(就是一級的共視關(guān)鍵幀5幀)瓤摧。
[3]對于當(dāng)前幀的地圖點和每一個關(guān)鍵幀。
將MapPoints往當(dāng)前幀投影玉吁,
投影的步驟:
地圖點是不是在該關(guān)鍵幀前面,地圖點是不是在該關(guān)鍵幀視野范圍內(nèi)腻异,是否在地圖點的最大最小范圍內(nèi)进副,是否和平均觀測方向夾角小于60度
匹配的步驟:
根據(jù)地圖點的尺度確定在關(guān)鍵幀上的搜索范圍,獲取地圖點的匹配集合悔常,距離小于閾值的前提下描述子距離最小得到匹配點影斑。
如果地圖點和當(dāng)前幀的特征點匹配上了:
<1>如果地圖點和當(dāng)前關(guān)鍵幀的特征點匹配上的話,那就那就先看這個特征點對應(yīng)的地圖點是不是為空
<2>如果關(guān)鍵幀的特征點有地圖點的話机打,那么看那個地圖點的觀測次數(shù)較多矫户,多的替換少的。
<3>如果關(guān)鍵幀的特征點對應(yīng)的地圖點為NULL的話残邀,那么地圖點添加觀測皆辽,關(guān)鍵幀添加地圖點。

[4]上面是當(dāng)前幀的地圖點每一個關(guān)鍵幀進行融合芥挣。
現(xiàn)在是每一個關(guān)鍵幀的地圖點當(dāng)前幀進行融合驱闷。
[5]更新當(dāng)前幀MapPoints的描述子,深度空免,觀測方向和最大最小距離空另。
[6]更新當(dāng)前幀的covisibility圖。更新共視的關(guān)鍵幀和對應(yīng)的權(quán)重蹋砚。

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
要點程序:
其他:
=========================================================================
題目:地圖點進行替換扼菠,替換的信息包含什么呢摄杂?
參考:
int ORBmatcher::Fuse(KeyFrame *pKF, const vector<MapPoint *> &vpMapPoints,
                     const float th)
思路:
1.思路:

[1]如果地圖點和當(dāng)前關(guān)鍵幀的特征點匹配上的話,那就那就先看這個特征點對應(yīng)的地圖點是不是為空
[2]如果關(guān)鍵幀的特征點有地圖點的話循榆,那么看那個地圖點的觀測次數(shù)較多析恢,多的替換少的。
<1>如果要的地圖點不包含該幀的觀測冯痢,那么該幀替換地圖點,地圖點添加該幀觀測
<2>如果要的地圖點包含該幀的觀測氮昧,那么就有沖突了,那么把該幀的地圖點置為NULL浦楣。
[3]如果關(guān)鍵幀的特征點對應(yīng)的地圖點為NULL的話袖肥,那么地圖點添加觀測,關(guān)鍵幀添加地圖點振劳。


=========================================================================
題目:local BA做了什么椎组,具體流程是什么
參考:
思路:
1.思路:

當(dāng)前幀相連的局部關(guān)鍵幀和對應(yīng)局部地圖點的LocalBA

lLocalKeyFrames:當(dāng)前關(guān)鍵幀和當(dāng)前關(guān)鍵幀的共視關(guān)鍵幀。
lLocalMapPoints:當(dāng)前關(guān)鍵幀和當(dāng)前關(guān)鍵幀的共視關(guān)鍵幀對應(yīng)的地圖點历恐。
對于有一些關(guān)鍵幀寸癌,能觀測到該地圖點lLocalMapPoints,但是不屬于lLocalKeyFrames弱贼,把它設(shè)置為lFixedCameras蒸苇。
[1]添加位姿頂點,其中第一關(guān)鍵幀不優(yōu)化
[2]添加不優(yōu)化的位姿頂點
[3]添加地圖點,對地圖點進行邊緣化吮旅,對于每一個地圖點的觀測溪烤,建立邊
<1>設(shè)置信息矩陣,權(quán)重為地圖點對應(yīng)金字塔層尺度因子權(quán)重的倒數(shù)庇勃,進行去量綱
<2>使用魯棒核函數(shù)去除外點
<3>添加邊
[4]第一階段優(yōu)化槐壳,迭代5次
[5]對于誤差太大酸舍,不優(yōu)化呼畸。第二階段屬于精求解嘿期,所以不使用魯棒核函數(shù)。
[6]第二階段罕拂,優(yōu)化10次揍异。
[7]對于誤差太大的,去除關(guān)鍵幀和地圖點的邊聂受。關(guān)鍵幀移除地圖點蒿秦,地圖點移除關(guān)鍵幀的觀測。
[8]更新關(guān)鍵幀的位姿蛋济,更新地圖點的位置和平均觀測方向棍鳖、最大最小距離。

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
要點程序:
其他:
=========================================================================
題目:初始關(guān)鍵幀,要鎖住位姿不優(yōu)化渡处,為什么?
參考:第 5 講 后端優(yōu)化實踐:逐行手寫求解器 要點(切題 Done)
思路:
1.思路:

為了限定優(yōu)化值不亂飄镜悉,那么代碼如何實現(xiàn),添加超強先驗医瘫,H矩陣巨大侣肄,使得\Delta x為0,或者讓雅克比矩陣為0醇份,那么H \Delta x = 0稼锅,所以\Delta x為0。

六僚纷、[背][w1]通俗易懂理解LocalMapping::LocalBundleAdjustment

=========================================================================
題目:local BA做了什么矩距,具體流程是什么
參考:
思路:
1.思路:

當(dāng)前幀相連的局部關(guān)鍵幀和對應(yīng)局部地圖點的LocalBA

lLocalKeyFrames:當(dāng)前關(guān)鍵幀和當(dāng)前關(guān)鍵幀的共視關(guān)鍵幀。
lLocalMapPoints:當(dāng)前關(guān)鍵幀和當(dāng)前關(guān)鍵幀的共視關(guān)鍵幀對應(yīng)的地圖點怖竭。
對于有一些關(guān)鍵幀锥债,能觀測到該地圖點lLocalMapPoints,但是不屬于lLocalKeyFrames痊臭,把它設(shè)置為lFixedCameras哮肚。
[1]添加位姿頂點,其中第一關(guān)鍵幀不優(yōu)化
[2]添加不優(yōu)化的位姿頂點
[3]添加地圖點,對地圖點進行邊緣化广匙,對于每一個地圖點的觀測允趟,建立邊
<1>設(shè)置信息矩陣,權(quán)重為地圖點對應(yīng)金字塔層尺度因子權(quán)重的倒數(shù)鸦致,進行去量綱
<2>使用魯棒核函數(shù)去除外點
<3>添加邊
[4]第一階段優(yōu)化拼窥,迭代5次
[5]對于誤差太大,不優(yōu)化蹋凝。第二階段屬于精求解,所以不使用魯棒核函數(shù)总棵。
[6]第二階段鳍寂,優(yōu)化10次。
[7]對于誤差太大的情龄,去除關(guān)鍵幀和地圖點的邊迄汛。關(guān)鍵幀移除地圖點,地圖點移除關(guān)鍵幀的觀測骤视。
[8]更新關(guān)鍵幀的位姿鞍爱,更新地圖點的位置和平均觀測方向、最大最小距離专酗。

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
要點程序:
其他:
=========================================================================
題目:初始關(guān)鍵幀睹逃,要鎖住位姿不優(yōu)化,為什么?
參考:第 5 講 后端優(yōu)化實踐:逐行手寫求解器 要點(切題 Done)
思路:
1.思路:

為了限定優(yōu)化值不亂飄,那么代碼如何實現(xiàn)沉填,添加超強先驗疗隶,H矩陣巨大,使得\Delta x為0翼闹,或者讓雅克比矩陣為0斑鼻,那么H \Delta x = 0,所以\Delta x為0猎荠。


七坚弱、[背誦][w1]通俗易懂理解關(guān)鍵幀刪除LocalMapping::KeyFrameCulling

=========================================================================
題目:關(guān)鍵幀刪除的原則
參考:
思路:
1.思路:

進來很容易,要留下來就很難关摇。[寬進嚴(yán)留]
[1]得到當(dāng)前關(guān)鍵幀對應(yīng)的共視關(guān)鍵幀荒叶。
[2]對于每一個共視關(guān)鍵幀。某個關(guān)鍵幀對應(yīng)的地圖點拒垃,該地圖點的觀測次數(shù)大于3次停撞,這樣的地圖點,它的數(shù)量若大于該幀對應(yīng)的地圖點數(shù)量的90%悼瓮,那么這個關(guān)鍵幀就是冗余的戈毒,可以刪除該關(guān)鍵幀。
PS:ORBSLAM中加了一些策略横堡,但是整體是這樣的埋市。
策略是:當(dāng)前關(guān)鍵幀對應(yīng)的特征點有一個層數(shù),要求地圖點的其他觀測命贴,它對應(yīng)的特征點的金字塔層數(shù)應(yīng)該小于當(dāng)前關(guān)鍵幀對應(yīng)的特征點的層數(shù)道宅,也就是說要遠一點。

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
=========================================================================
題目:如何刪除關(guān)鍵幀
參考:

通俗易懂理解KeyFrame類問題 要點(切題 Done)

思路:
1.思路:
2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):

八胸蛛、[w1]通俗易懂理解KeyFrame類問題 要點(要點切題 Done)

參考

ORB SLAM2源碼解讀(四):KeyFrame類 任乾

主要有3大類函數(shù):

管理關(guān)鍵幀和MapPoint之間關(guān)系的函數(shù)

管理共視關(guān)系的函數(shù)

管理生成樹的函數(shù)

=========================================================================
題目:什么叫共視圖
參考:void KeyFrame::UpdateConnections()
思路:
1.思路:

KeyFrame為關(guān)鍵幀污茵,關(guān)鍵幀之所以存在是因為優(yōu)化需要,所以關(guān)鍵幀所有的內(nèi)容都是為優(yōu)化服務(wù)的葬项。
圖優(yōu)化需要構(gòu)建節(jié)點和邊泞当,節(jié)點有關(guān)鍵幀的位姿,邊民珍,第一種邊是關(guān)鍵幀和MapPoint之間的襟士,第二種邊是和其他關(guān)鍵幀之間的,他們之間需要通過MapPoint產(chǎn)生聯(lián)系嚷量,兩幀能共同觀測到一定數(shù)量的MapPoint可以在他倆之間建立邊陋桂,這種通過共視關(guān)系建立的模型叫 covisibility graph。
covisibility graph:每個關(guān)鍵幀是一個節(jié)點蝶溶,如果兩個關(guān)鍵幀之間的共視地圖點數(shù)量大于15嗜历,則在這兩個節(jié)點之間建立邊,邊的權(quán)重是共視地圖點的數(shù)量。

2.圖解(請用紙):
KeyFrame_UpdateConnections
3.公式推導(dǎo)(請用紙):
要點程序:
map<KeyFrame*, int> KFCounter;
=========================================================================
題目:什么叫本質(zhì)圖秸脱,為什么存在落包,怎么用?
參考:
思路:
1.思路:

大范圍的話摊唇,計算量會很大,簡版就是essential graph,通過spanning tree來管理關(guān)鍵幀之間的關(guān)系咐蝇。每個幀都有一個父節(jié)點和多個子節(jié)點,節(jié)點為其他關(guān)鍵幀巷查,在構(gòu)建優(yōu)化模型的時候有序,只有具有父子關(guān)系的關(guān)鍵幀之間才建立邊,換句話說岛请,essential graph就是covisibility graph的子集旭寿,大大減小邊的數(shù)量,從而減小計算量崇败。

covisibility graph:每個關(guān)鍵幀是一個節(jié)點盅称,如果兩個關(guān)鍵幀之間的共視地圖點數(shù)量大于15,則在這兩個節(jié)點之間建立邊后室,邊的權(quán)重是共視地圖點的數(shù)量
spanning tree:保留所有的關(guān)鍵幀缩膝,給每一個關(guān)鍵幀找了1個父節(jié)點和多個子節(jié)點,每幀只跟自己的父節(jié)點和子節(jié)點相連岸霹,與其他幀不連接
essential graph:根據(jù)spanning tree建立的圖模型疾层,就是簡版的covisibility graph

spanning tree、essential graph
其中子節(jié)點可能有多個贡避,因為有一個容器mspChildrens痛黎,父節(jié)點只能有一個,因為有一個變量mpParent
當(dāng)前關(guān)鍵幀的父節(jié)點就是和當(dāng)前關(guān)鍵幀共視強度最強的刮吧。

本質(zhì)圖存在的意義是為全局優(yōu)化服務(wù)的湖饱。

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
要點程序:
mpParent = mvpOrderedConnectedKeyFrames.front();
// 建立雙向連接關(guān)系
mpParent->AddChild(this);
=========================================================================
題目:local mapping中如何刪除關(guān)鍵幀
參考:void KeyFrame::SetBadFlag()

// 刪除和該幀相關(guān)的所有連接關(guān)系

void KeyFrame::SetBadFlag() 

// 刪除當(dāng)前關(guān)鍵幀和指定關(guān)鍵幀之間的共視關(guān)系

void KeyFrame::EraseConnection(KeyFrame *pKF)
思路:
1.思路:

[1]當(dāng)前關(guān)鍵幀有很多共視的關(guān)鍵幀,這些共視關(guān)鍵幀中的每一幀杀捻,從它的共視關(guān)鍵幀中琉历,erase當(dāng)前幀的聯(lián)系。
[2]當(dāng)前幀對應(yīng)的地圖點水醋,這些地圖點把當(dāng)前幀從觀測中erase。如果當(dāng)前幀是地圖點的參考關(guān)鍵幀(即觀測到該地圖點的第一個關(guān)鍵幀)彪置,重新給地圖點指定參考關(guān)鍵幀拄踪。如果地圖點觀測的數(shù)量太少,那么把地圖點給刪除[詳細見通俗易懂理解MapPoint類 要點(切題 Done)]拳魁。
本質(zhì)圖相關(guān)
[3]重新給每個children指定父親惶桐,應(yīng)為自己要死了,這個父親是從children的共視關(guān)鍵幀中選擇,找孩子和共視關(guān)鍵幀中強度最高的作為children的父親姚糊。見下圖贿衍。
[4]如果有的孩子找不到父親,那么孩子的父親等于我的父親救恨。

2.圖解(請用紙):
KeyFrame_SetBadFlag
3.公式推導(dǎo)(請用紙):
要點程序:

=========================================================================
題目:評估當(dāng)前關(guān)鍵幀場景深度贸辈,在哪用呢?
參考:
float KeyFrame::ComputeSceneMedianDepth(const int q)
思路:
1.思路:

相機坐標(biāo)系下地圖點深度的中間值作為場景的平均深度肠槽。
單目地圖點初始化用到擎淤。

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
要點程序:
其他:
=========================================================================
題目:共視圖、本質(zhì)圖建立的邊如何在Optimizer中得到體現(xiàn)呢秸仙?有什么關(guān)系呢嘴拢?
參考:
思路:
void Optimizer::LocalBundleAdjustment(KeyFrame* pKF, bool* pbStopFlag,
                                      Map* pMap)
1.思路:

通過一個關(guān)鍵幀,我可以找到他的共視關(guān)鍵幀寂纪,組成lLocalKeyFrames席吴,由lLocalKeyFrames得到lLocalMapPoints, 能夠觀測到lLocalMapPoints但是不屬于lLocalKeyFrames進行fix捞蛋,不優(yōu)化孝冒。

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
要點程序:

九、通俗易懂理解MapPoint類 要點(切題 Done)

參考

ORB SLAM2源碼解讀(二):MapPoint類

題目:如何刪除地圖點襟交?
參考:
// 把這個地圖點給刪掉
SetBadFlag()
思路:
1.思路:

[1]刪除地圖點的觀測
[2]因為地圖點被很多關(guān)鍵幀觀測到迈倍,每個觀測包含關(guān)鍵幀和對應(yīng)的特征點id,把關(guān)鍵幀對應(yīng)的地圖點置空

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
要點程序:

問題

MapPoint的id是怎樣的。

這個地圖點被很多關(guān)鍵幀觀測到捣域,地圖點的每一個觀測包含關(guān)鍵幀和對應(yīng)在關(guān)鍵幀中的索引啼染。

主要函數(shù)

void MapPoint::AddObservation(KeyFrame* pKF, size_t idx)
void MapPoint::EraseObservation(KeyFrame* pKF)
void MapPoint::Replace(MapPoint* pMP)
// 把這個地圖點給刪掉
SetBadFlag()
void MapPoint::ComputeDistinctiveDescriptors()
void MapPoint::UpdateNormalAndDepth()
int MapPoint::PredictScale(const float& currentDist, Frame* pF)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市焕梅,隨后出現(xiàn)的幾起案子迹鹅,更是在濱河造成了極大的恐慌,老刑警劉巖贞言,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斜棚,死亡現(xiàn)場離奇詭異,居然都是意外死亡该窗,警方通過查閱死者的電腦和手機弟蚀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酗失,“玉大人义钉,你說我怎么就攤上這事」骐龋” “怎么了捶闸?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵夜畴,是天一觀的道長。 經(jīng)常有香客問我删壮,道長贪绘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任央碟,我火速辦了婚禮税灌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘硬耍。我一直安慰自己垄琐,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布经柴。 她就那樣靜靜地躺著狸窘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪坯认。 梳的紋絲不亂的頭發(fā)上翻擒,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音牛哺,去河邊找鬼陋气。 笑死,一個胖子當(dāng)著我的面吹牛引润,可吹牛的內(nèi)容都是我干的巩趁。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼淳附,長吁一口氣:“原來是場噩夢啊……” “哼议慰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起奴曙,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤别凹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后洽糟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體炉菲,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年坤溃,在試婚紗的時候發(fā)現(xiàn)自己被綠了拍霜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡薪介,死狀恐怖沉御,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情昭灵,我是刑警寧澤吠裆,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站烂完,受9級特大地震影響试疙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜抠蚣,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一祝旷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嘶窄,春花似錦怀跛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至现横,卻和暖如春漓拾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背戒祠。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工骇两, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人姜盈。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓低千,卻偏偏與公主長得像,于是被迫代替她去往敵國和親馏颂。 傳聞我的和親對象是個殘疾皇子示血,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容