通俗易懂理解ORBSLAM2特征提取模塊

一财骨、通俗易懂理解圖像金字塔特征點數(shù)目模她、灰度質(zhì)心圓索引

1.參考資料:

[1] ORBSLAM2 source code

2.主要函數(shù):
//特征點提取器的構(gòu)造函數(shù)

ORBextractor::ORBextractor(int _nfeatures,      //指定要提取的特征點數(shù)目
                           float _scaleFactor,  //指定圖像金字塔的縮放系數(shù)
                           int _nlevels,        //指定圖像金字塔的層數(shù)
                           int _iniThFAST,      //指定初始的FAST特征點提取參數(shù)议双,可以提取出最明顯的角點
                           int _minThFAST):     //如果因為圖像紋理不豐富提取出的特征點不多絮姆,為了達(dá)到想要的特征點數(shù)目羊壹,
                                                //就使用這個參數(shù)提取出不是那么明顯的角點
    nfeatures(_nfeatures), scaleFactor(_scaleFactor), nlevels(_nlevels),
    iniThFAST(_iniThFAST), minThFAST(_minThFAST)//設(shè)置這些參數(shù)
3.遇到的問題:
1)圖像金字塔特征點數(shù)目

等比數(shù)列的思路計算總面積侥祭,然后計算單位面積的分配的特征點數(shù)量叁执,得到金字塔每一層需要提取的特征點數(shù)量。注意其中scale^2用scale替換矮冬。



2)灰度質(zhì)心圓索引

3)FAST特征點判定
4)BRIEF描述子

一個特征點的谈宛,描述子是如何用pattern得到的或者描述子是如何得到的?
BRIEF算法的核心思想是在關(guān)鍵點P的周圍以一定模式選取N個點對,把這N個點對的比較結(jié)果組合起來作為描述子胎署。

5)orientated FAST(ORB orientated rotated brief)

orientated FAST是改變描述子還是增加特征點的方向呢吆录?
不管叫什么名字,這個算法要解決的問題是:

回顧一下BRIEF描述子的計算過程:在當(dāng)前關(guān)鍵點P周圍以一定模式選取N個點對琼牧,組合這N個點對的T操作的結(jié)果就為最終的描述子恢筝。當(dāng)我們選取點對的時候,是以當(dāng)前關(guān)鍵點為原點障陶,以水平方向為X軸滋恬,以垂直方向為Y軸建立坐標(biāo)系。當(dāng)圖片發(fā)生旋轉(zhuǎn)時抱究,坐標(biāo)系不變恢氯,同樣的取點模式取出來的點卻不一樣,計算得到的描述子也不一樣,這是不符合我們要求的勋拟。因此我們需要重新建立坐標(biāo)系勋磕,使新的坐標(biāo)系可以跟隨圖片的旋轉(zhuǎn)而旋轉(zhuǎn)。這樣我們以相同的取點模式取出來的點將具有一致性敢靡。ORB特征原理(淺顯易懂)

[?]6)ORB特征點方向計算實現(xiàn)旋轉(zhuǎn)不變性

這個問題問的起始是怎么具體解決旋轉(zhuǎn)不變性的問題
為什么是圓呢挂滓?這個圖應(yīng)該怎么看呢?


一個是旋轉(zhuǎn)前,一個是旋轉(zhuǎn)后啸胧,我們后續(xù)是在旋轉(zhuǎn)后的基礎(chǔ)上做的赶站。
當(dāng)我們選取點對的時候,是以當(dāng)前關(guān)鍵點為原點纺念,以水平方向為X軸贝椿,以垂直方向為Y軸建立坐標(biāo)系。當(dāng)圖片發(fā)生旋轉(zhuǎn)時陷谱,坐標(biāo)系就要旋轉(zhuǎn)一下烙博。

在圖1中,P為關(guān)鍵點烟逊。圓內(nèi)為取點區(qū)域渣窜,每個小格子代表一個像素。現(xiàn)在我們把這塊圓心區(qū)域看做一塊木板宪躯,木板上每個點的質(zhì)量等于其對應(yīng)的像素值乔宿。根據(jù)積分學(xué)的知識我們可以求出這個密度不均勻木板的質(zhì)心Q。
我們知道圓心是固定的而且隨著物體的旋轉(zhuǎn)而旋轉(zhuǎn)眷唉。當(dāng)我們以PQ作為坐標(biāo)軸時(圖2)予颤,在不同的旋轉(zhuǎn)角度下囤官,我們以同一取點模式取出來的點是一致的冬阳。這就解決了旋轉(zhuǎn)一致性的問題。

以計算出來的特征點方向為x軸党饮,再建立y軸肝陪。在這個基礎(chǔ)上計算特征點的描述子,這樣就特征點就具備了旋轉(zhuǎn)不變性刑顺。
計算灰度質(zhì)心用的是圓呢氯窍?為什么方形的不行呢


我目前認(rèn)為是可以的蹲堂。如圖狼讨。

=========================================================================
題目:圖像金字塔特征點數(shù)目的計算方式。描述子加入計算特征點的方向的目的柒竞。
參考:
思路:
1.思路:

圖像金字塔特征點數(shù)目的計算方式:等比數(shù)列政供。
描述子加入計算特征點的方向的目的:為了使得特征點的描述子具有旋轉(zhuǎn)不變性。

2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
要點程序:
// 最底層分配的特征點個數(shù)
  float nDesiredFeaturesPerScale =
      nfeatures * (1 - factor) /
      (1 - (float)pow((double)factor, (double)nlevels));
其他:

二、通俗易懂理解特征提取仿函數(shù)布隔、圖像擴(kuò)充金字塔

1.參考資料:

[1] ORBSLAM2 source code

2.主要函數(shù):
void Frame::ExtractORB(int flag, const cv::Mat &im)
void ORBextractor::operator()( InputArray _image, InputArray _mask, vector<KeyPoint>& _keypoints,
                      OutputArray _descriptors)
void ORBextractor::ComputePyramid(cv::Mat image)
3.遇到的問題:
1)仿函數(shù)
void ORBextractor::operator()( InputArray _image, InputArray _mask, vector<KeyPoint>& _keypoints,
                      OutputArray _descriptors)

為什么要重載小括號運算符operator()?
可以用于仿函數(shù)(一個可以實現(xiàn)函數(shù)功能的對象)
仿函數(shù)(functor)又稱為函數(shù)對象(functor object)是一個能行使函數(shù)功能的類离陶。仿函數(shù)的語法幾乎和我們使用的函數(shù)調(diào)用一樣,不過作為仿函數(shù)的類衅檀,都必須重載operator()運算符
1.仿函數(shù)可以擁有自己的數(shù)據(jù)成員和成員變量招刨,這意味著仿函數(shù)擁有狀態(tài)。這在一般的函數(shù)中是不可能的哀军。
2.仿函數(shù)通常比一般函數(shù)有更好的速度沉眶。

2)圖像金字塔

cv::Rect矩形類參數(shù)設(shè)置

typedef struct CvRect 
{ 
  int x; /* 方形的左上角的x-坐標(biāo) */ 
  int y; /* 方形的左上角的y-坐標(biāo)*/ 
  int width; /* 寬 */ 
  int height; /* 高 */ 
}

圖像金字塔

通俗解釋:最底層圖像,分辨率最高杉适,可以看到最遠(yuǎn)的點沦寂。

copyMakeBorder
把源圖像拷貝到目的圖像的中央,四面填充指定的像素淘衙。圖片如果已經(jīng)拷貝到中間传藏,只填充邊界



PS:BORDER_ISOLATED由于我們是整張圖像而不是ROI,所以可加可不加彤守。

=========================================================================
題目:什么叫仿函數(shù)毯侦,怎么寫,怎么用具垫,有什么好處侈离?
參考:
思路:
1.思路:

仿函數(shù)的語法幾乎和我們使用的函數(shù)調(diào)用一樣,不過作為仿函數(shù)的類筝蚕,都必須重載operator()運算符
1.仿函數(shù)可以擁有自己的數(shù)據(jù)成員和成員變量卦碾,這意味著仿函數(shù)擁有狀態(tài)。這在一般的函數(shù)中是不可能的起宽。
2.仿函數(shù)通常比一般函數(shù)有更好的速度洲胖。

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

// 這是一個變量

ORBextractor* mpORBextractorLeft, *mpORBextractorRight;

// 這是一個變量,這是一個看著像函數(shù)的用法

    (*mpORBextractorLeft)(im,         //待提取特征點的圖像
                          cv::Mat(),  //掩摸圖像, 實際沒有用到
                          mvKeys,  //輸出變量坯沪,用于保存提取后的特征點
                          mDescriptors);  //輸出變量绿映,用于保存特征點的描述子

// 然后為什么能這么干呢?在類里面實現(xiàn)了這個operator()函數(shù)

  void operator()(cv::InputArray image, cv::InputArray mask,
                  std::vector<cv::KeyPoint> &keypoints,
                  cv::OutputArray descriptors)
其他:

三腐晾、通俗易懂理解特征點四叉樹均勻化分配策略

1.參考資料:

[1] ORBSLAM2 source code
[2] ORB-SLAM2代碼筆記(十):ORBextractor

2.主要函數(shù):
void ORBextractor::ComputeKeyPointsOctTree(
    vector<vector<KeyPoint> >& allKeypoints)
void ExtractorNode::DivideNode(ExtractorNode &n1,   
                               ExtractorNode &n2, 
                               ExtractorNode &n3, 
                               ExtractorNode &n4)

非常重要的函數(shù):

vector<cv::KeyPoint> ORBextractor::DistributeOctTree(const vector<cv::KeyPoint>& vToDistributeKeys, const int &minX,
                                       const int &maxX, const int &minY, const int &maxY, const int &N, const int &level)
void ExtractorNode::DivideNode(ExtractorNode &n1,   
                               ExtractorNode &n2, 
                               ExtractorNode &n3, 
                               ExtractorNode &n4)
3.主要過程如下:
1)劃分網(wǎng)格(網(wǎng)格大小是30像素)叉弦,對每個網(wǎng)格進(jìn)行FAST特征提取,沒有提取的到的降低檢測閾值
2)對當(dāng)前層圖像生成一個提取器節(jié)點藻糖,把特征點分配到這個提取器節(jié)點中
3)1分為4一次淹冰,看看節(jié)點數(shù)量是否大于我要提取的節(jié)點個數(shù),如果小于的話巨柒,還需要接著分裂樱拴,其中節(jié)點為空凝颇,刪除節(jié)點,節(jié)點中特征點數(shù)量為1疹鳄,不再分裂拧略。大于的話,結(jié)束分裂瘪弓,從每個節(jié)點中選擇一個響應(yīng)值最好的垫蛆,然后獲取最終的特征點集合。



4.PS:
1)特征點提取的傳統(tǒng)方法(網(wǎng)格篩點法):
void ORBextractor::ComputeKeyPointsOld(
    std::vector<std::vector<KeyPoint> > &allKeypoints)
2)主要過程如下:

第一步計算將圖像分成多少個cell腺怯,對每個cell分別進(jìn)行提取特征點袱饭,cell的計算方法是根據(jù)需要提取的特征點數(shù)目,假設(shè)每個cell中需要提取5個特征點呛占,以此進(jìn)行計算需要的cell數(shù)目虑乖。
接著對計算好的cell進(jìn)行特征點提取。首先使用閾值較大的參數(shù)作為FAST特征點檢測閾值晾虑,如果提取到的特征點數(shù)目足夠多疹味,那么直接計算下一個元包即可,否則使用較小的參數(shù)重新提取特征點帜篇。
然后就涉及到特征點數(shù)目的分配問題糙捺。由于圖像中不可避免出現(xiàn)紋理豐富和紋理較淺的區(qū)域,在紋理豐富的區(qū)域笙隙,角點的數(shù)目可能提取很多洪灯,而在紋理不豐富的區(qū)域,角點提取很少竟痰。對于將特征點數(shù)目不足的cell中剩余不足的數(shù)目分配到其他cell中签钩,提高其他cell中期望提取的特征點數(shù)量閾值,直到最后提取足夠數(shù)量的特征點坏快。當(dāng)然如果提取的數(shù)量確實不足預(yù)期铅檩,也就停止了。

5.問題
=========================================================================
題目:特征點均勻化策略一分為4都是一分為4到底嗎假消,比如說1張圖像柠并,已經(jīng)一分為4岭接。在這個基礎(chǔ)上富拗,下一輪是否對這4個中的每一個都進(jìn)行一分為四了?還是說到數(shù)目了就停止了鸣戴。
參考:
思路:
1.思路:

不斷地進(jìn)行一分為4啃沪。=>快要達(dá)到目標(biāo)數(shù)量的時候,那就sort一下=>從數(shù)量多的進(jìn)行開始進(jìn)行一分為4窄锅,同時每次判斷是否滿足目標(biāo)數(shù)量创千。這樣很符合一個人的思維缰雇。

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

四、通俗易懂理解ORB特征點方向計算實現(xiàn)旋轉(zhuǎn)不變性

1.參考資料:

[1] ORBSLAM2 source code

2.主要函數(shù):
static void computeOrientation(const Mat& image, vector<KeyPoint>& keypoints, const vector<int>& umax)
static float IC_Angle(const Mat& image, Point2f pt,  const vector<int> & u_max)

這個圖有疑問啊!!!暫時不jiujie





五追驴、通俗易懂理解ORB描述子steer brief計算方法

1.參考資料:

[1] ORBSLAM2 source code

2.主要函數(shù):
static void computeOrbDescriptor(const KeyPoint& kpt,
                                 const Mat& img, const Point* pattern,
                                 uchar* desc)
3.如何將描述子和特征點方向結(jié)合起來

我們期望準(zhǔn)確地描述特征點械哟,所以當(dāng)我們把圖像順時針轉(zhuǎn)了一個角度的話,我們期望獲取某一點旋轉(zhuǎn)后的坐標(biāo)殿雪,以便正常地描述該特征點暇咆。因為旋轉(zhuǎn)后坐標(biāo)對應(yīng)的灰度值和之前的灰度值是一樣的。
描述特征點的坐標(biāo)集合中的坐標(biāo)值是固定的丙曙。
高斯模糊把雜點去掉



高斯模糊能把雜點去掉

4.問題
1)描述子最終的形式是怎樣的爸业?

cv::Mat格式,描述整幅圖像的特征點亏镰,每一行是一個描述子.
對于一個描述子來說扯旷,一共比較32次,每次用16個點索抓,比較8次钧忽,產(chǎn)生1個字節(jié),所以每個描述子用32*8=256bit.

=========================================================================
題目:如何利用特征點方向?qū)γ枋鲎舆M(jìn)行旋轉(zhuǎn)呢逼肯?請寫出公式惰瓜。
參考:
思路:
1.思路:
2.圖解(請用紙):
3.公式推導(dǎo)(請用紙):
要點程序:
// x'= xcos(θ) - ysin(θ),  y'= xsin(θ) + ycos(θ)
#define GET_VALUE(idx) \
        center[cvRound(pattern[idx].x*b + pattern[idx].y*a)*step + \        // y'* step
               cvRound(pattern[idx].x*a - pattern[idx].y*b)]                // x'
其他:
=========================================================================
題目:高斯模糊的目的是什么?
參考:
思路:
1.思路:

高斯blur汉矿,去除噪點崎坊。

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

// 注意:提取特征點的時候,使用的是清晰的原圖像洲拇;這里計算描述子的時候奈揍,為了避免圖像噪聲的影響,使用了高斯模糊

    GaussianBlur(workingMat,  //源圖像
                 workingMat,  //輸出圖像
                 Size(7, 7),  //高斯濾波器kernel大小赋续,必須為正的奇數(shù)
                 2,           //高斯濾波在x方向的標(biāo)準(zhǔn)差
                 2,           //高斯濾波在y方向的標(biāo)準(zhǔn)差
                 BORDER_REFLECT_101);  //邊緣拓展點插值類型
其他:

六男翰、通俗易懂理解去畸變、算圖像邊界纽乱、劃分網(wǎng)格

1.參考資料:

[1] ORBSLAM2 source code

2.主要函數(shù):
Frame::Frame(const cv::Mat &imGray, const double &timeStamp, ORBextractor* extractor,ORBVocabulary* voc, cv::Mat &K, cv::Mat &distCoef, const float &bf, const float &thDepth)
    :mpORBvocabulary(voc),mpORBextractorLeft(extractor),mpORBextractorRight(static_cast<ORBextractor*>(NULL)),
     mTimeStamp(timeStamp), mK(K.clone()), mDistCoef(distCoef.clone()), mbf(bf), mThDepth(thDepth)
void Frame::UndistortKeyPoints()
void Frame::ComputeImageBounds(const cv::Mat &imLeft)   

注意一下去畸變函數(shù)需要輸入雙通道的mat:

//為了能夠直接調(diào)用opencv的函數(shù)來去畸變蛾绎,需要先將矩陣調(diào)整為2通道(對應(yīng)坐標(biāo)x,y) 
mat=mat.reshape(2);
cv::undistortPoints(mat,mat,mK,mDistCoef,cv::Mat(),mK);
//調(diào)整回只有一個通道,回歸我們正常的處理方式
mat=mat.reshape(1);

分配特征點到網(wǎng)格鸦列,網(wǎng)格在匹配的時候用到

void Frame::AssignFeaturesToGrid()
bool Frame::PosInGrid(const cv::KeyPoint &kp, int &posX, int &posY)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末租冠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子薯嗤,更是在濱河造成了極大的恐慌顽爹,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骆姐,死亡現(xiàn)場離奇詭異镜粤,居然都是意外死亡捏题,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門肉渴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來公荧,“玉大人,你說我怎么就攤上這事同规≈煽螅” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵捻浦,是天一觀的道長晤揣。 經(jīng)常有香客問我,道長朱灿,這世上最難降的妖魔是什么昧识? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮盗扒,結(jié)果婚禮上跪楞,老公的妹妹穿的比我還像新娘。我一直安慰自己侣灶,他們只是感情好甸祭,可當(dāng)我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著褥影,像睡著了一般池户。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凡怎,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天校焦,我揣著相機(jī)與錄音,去河邊找鬼统倒。 笑死寨典,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的房匆。 我是一名探鬼主播耸成,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼浴鸿!你這毒婦竟也來了井氢?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤赚楚,失蹤者是張志新(化名)和其女友劉穎毙沾,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宠页,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡左胞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了举户。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烤宙。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖俭嘁,靈堂內(nèi)的尸體忽然破棺而出躺枕,到底是詐尸還是另有隱情,我是刑警寧澤供填,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布拐云,位于F島的核電站,受9級特大地震影響近她,放射性物質(zhì)發(fā)生泄漏叉瘩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一粘捎、第九天 我趴在偏房一處隱蔽的房頂上張望薇缅。 院中可真熱鬧,春花似錦攒磨、人聲如沸泳桦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽灸撰。三九已至,卻和暖如春拼坎,著一層夾襖步出監(jiān)牢的瞬間梧奢,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工演痒, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留亲轨,地道東北人。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓鸟顺,卻偏偏與公主長得像惦蚊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子讯嫂,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,960評論 2 355

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