【ORB-SLAM2】探索之旅 第 3 天 : 深入解析影像金字塔 ( Image Pyramid ) 的實作與應用

類別 ImagePyramid 的成員變數介紹

前面說明了一堆瑣碎的理由,有關程式碼安全性與可讀性的抉擇等。現在終於能夠好好說明影像金字塔類別 ( ImagePyramid ) 的成員變數們了,但我並不會重複說明那些在 Header 檔裡面就有註解的內容,而是說明這些變數名稱為什麼這樣取,之類的。

  • int mnLevels :
    影像金字塔的層數。變數名稱中,英文的前綴 m 代表「成員」;前綴 n 代表「幾個」,意味該變數的型別為 Integer。所以,「m + n + Levels」代表「這個變數為成員變數,且它所屬的影像金字塔有幾個層級」如圖(一)所示。
影像金字塔層數示意圖
圖(二)、影像金字塔層數示意圖。
  • int mnFeatures :
    欲提取的特徵點總量。變數名稱中 m、n 所代表的意涵同上,所以,「m + n + Features」代表「這個變數為成員變數,且我們想提取的特徵點總共有幾個」。

    這邊要特別說明的是,為什麼我們要指定「欲提取的特徵點總量」給「影像金字塔」呢 ? 假設我們想提取 2000 個特徵點,總不能所有的特徵點都集中在金字塔中最下層的影像吧 ! 這樣會造成特徵點過度密集,產生更多無用、多餘的特徵點。

    所以,影像金字塔會根據我們給的「欲提取特徵點總量」,自動計算、分配每一層影像要提取的特徵點數,如圖(二)所示。每一層的特徵點數加起來大約是 2000 個,這樣才對 !
影像金字塔&關鍵點
圖(三)、影像金字塔中,每一層影像,分別都有自己的一組關鍵點。
  • int mfScaleFactor :
    每層之間的縮放係數。這個變數名稱和上面不太一樣的地方是,前綴英文小寫字母 f 代表 該變數的型別是 Float ( 浮點數 )。所以,mfScaleFactor 意涵為「這個變數為成員變數,且影像金字塔的縮放因子為多少。」

    ORB SLAM2 中預設 mfScaleFactor 為 1.2,也就是影像每往上一層,尺寸就縮小 1.2 倍 ( 等同於放大 0.83 倍 ),如圖(一)所示。

  • vector<int> mvnFeaturesPerLevel :
    儲存每一層影像中應提取的「特徵點數」。變數名稱中的 m、n,其意思都和上面提到的一樣,而前綴 v 代表「Vector」,它是 C++ 的動態陣列容器。所以,mvnFeaturesPerLevel 這個變數名稱要表達的是「它是成員變數、一個 Vector,而且每一格儲存的資料型態是 Integer 整數」每一格對應於影像金字塔中的一層,儲存該層需要多少個特徵點,如圖(三)所示。

    至於 Vector 容器,你完全可以不斷把資料存進去,不用擔心長度的問題,因為它會自動調整容量 ! 但是要注意的是,通常我們還是會很小心地管理其中的記憶體,除了避免發生 Bug,也可以提升程式運作的速度與效率。

  • vector<float> mvfScaleFactors :
    儲存每一層影像相較於第一層影像的「縮小倍數」。以此類推,mvfScaleFactors 這個變數名稱,想傳達的是「它是成員變數、一個 Vector,而且每一格儲存的資料型態是 Float 浮點數」每一格對應於影像金字塔中的一層,並儲存「該層影像」是「第一層影像」縮小多少倍而來的,這個倍率的數值型態是 Float。

  • vector<float> mvfInvScaleFactors :
    儲存每一層影像相較於第一層影像的「放大倍數」。變數的命名規則同上。

  • vector<Mat> mvImages :
    儲存每一層影像矩陣。 mvImages 這個變數名稱表示「它是成員變數,並且是一個 Vector,每一格儲存的資料型態是 Mat 影像矩陣,Mat 是 Matrix 的縮寫」。要理解這個變數的結構很簡單,它就是圖(一)顯示的那樣,Vector 的第 1 層 ( Index = 0 ) 儲存的是影像金字塔中的第 1 層,也就是最下面的影像;Vector 的第 2 層 ( Index = 1 ) 儲存的是影像金字塔中的第 2 層,以此類推 !

影像金字塔的變數名稱就介紹到這裡,後續我們在設計其他模組時,也都會依照這種命名規則。到時,我不會再重複介紹變數名稱的命名囉 !

C++ 中的 Vector 容器

C++ 的 Vector 容器有「容量」和「大小」之分,容量代表它最多可以儲存多少筆資料;大小代表目前儲存多少筆資料。一旦儲存的資料量超過其容量,它便會自動搬運記憶體,移動到容量更大的記憶體區塊,所以我們不用擔心儲存資料量大於容量的問題。

但是要注意的是,這個記憶體擴增的過程,會很消耗電腦性能,儘管 C++ 的速度已經很快了。在這種情境下,當程式碼規模擴大、複雜度增加時,只要我們不小心,還是很容易會觸發 Segmentation Fault 這個 Bug,中文叫做「記憶體區段錯誤」。意思就是你的程式不小心去碰了一塊不該存取的記憶體,導致作業系統為了保護安全而直接中斷、Kill 這個程式,小麻煩。

C++ Vector 示意圖
圖(四)、C++ Vector 容器示意圖。

1 則留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *