說到雙攝像頭測距,首先要複習一下測距原理,把learning opencv翻到416和418頁,可以看到下面兩幅圖
圖1. 雙攝像頭模型俯檢視
圖2, 雙攝像頭模型立體檢視
圖1解釋了雙攝像頭測距的原理,書中z的公式如下:
在opencv中,f的量綱是畫素點,tx的量綱由定標棋盤格的實際尺寸和使用者輸入值確定,一般總是設成公釐,當然為了精度提高也可以設定為0.1公釐量級,d=xl-xr的量綱也是畫素點。因此分子分母約去,z的量綱與tx相同
圖2解釋了雙攝像頭獲取空間中某點三維座標的原理。
可以看到,實際的座標計算利用的都是相似三角形的原理,其表示式就如同q矩陣所示。
空間中某點的三維座標就是(x/w, y/w, z/w)。
因此,為了精確地求得某個點在三維空間裡的距離,我們需要獲得的引數有焦距f、視差d、攝像頭中心距tx。
如果還需要獲得x座標和y座標的話,那麼還需要額外知道左右像平面的座標系與立體座標系中原點的偏移cx和cy。其中f, tx, cx和cy可以通過立體標定獲得初始值,並通過立體校準優化,使得兩個攝像頭在數學上完全平行放置,並且左右攝像頭的cx, cy和f相同(也就是實現圖2中左右檢視完全平行對準的理想形式)。而立體匹配所做的工作,就是在之前的基礎上,求取最後乙個變數:視差d(這個d一般需要達到亞畫素精度)。從而最終完成求乙個點三維座標所需要的準備工作。
在清楚了上述原理之後,我們也就知道了,所有的這幾步:標定、校準和匹配,都是圍繞著如何更精確地獲得f, d, tx, cx和cy而設計的。
雙目測距的原理就說到這裡,為了避免大家看到大段純敘述性的文字頭暈,下面的行文將會以faq的形式圍繞著實現雙攝像頭測距過程中碰到的幾點疑惑展開。當然,其中的解答也只是我的個人理解,如有不當,敬請指正。
q1:標定時棋盤格的大小如何設定,對最後結果有沒有影響?
a:當然有。在標定時,需要指定乙個棋盤方格的長度,這個長度(一般以公釐為單位,如果需要更精確可以設為0.1公釐量級)與實際長度相同,標定得出的結果才能用於實際距離測量。一般如果尺寸設定準確的話,通過立體標定得出的translation的向量的第乙個分量tx的絕對值就是左右攝像頭的中心距。一般可以用這個來驗證立體標定的準確度。比如我設定的棋盤格大小為270 (27mm),最終得出的tx大小就是602.8 (60.28mm),相當精確。
q2:通過立體標定得出的tx符號為什麼是負的?
a:這個其實我也不是很清楚。個人的解釋是,立體標定得出的t向量指向是從右攝像頭指向左攝像頭(也就是tx為負),而在opencv座標系中,座標的原點是在左攝像頭的。因此,用作校準的時候,要把這個向量的三個分量符號都要換一下,最後求出的距離才會是正的。
但是這裡還有乙個問題,就是learning opencv中q的表示式,第四行第三列元素是-1/tx,而在具體實踐中,求出來的實際值是1/tx。這裡我和maxwellsdemon討論下來的結果是,估計書上q表示式裡的這個負號就是為了抵消t向量的反方向所設的,但在實際寫opencv**的過程中,那位朋友卻沒有把這個負號加進去。(一家之言,求更詳細的解釋)
q3:cvfindstereocorrespondencebm的輸出結果好像不是以畫素點為單位的視差?
a:在opencv2.0中,bm函式得出的結果是以16位符號數的形式的儲存的,出於精度需要,所有的視差在輸出時都擴大了16倍(2^4)。其具體**表示如下:
dptr[y*dstep] = (short)(((ndisp - mind - 1 + mindisp)*256 + (d != 0 ? (p-n)*128/d : 0) + 15) >> 4);
可以看到,原始視差在左移8位(256)並且加上乙個修正值之後又右移了4位,最終的結果就是左移4位
因此,在實際求距離時,cvreprojectto3d出來的x/w,y/w,z/w都要乘以16 (也就是w除以16),才能得到正確的三維座標資訊
q4:利用雙攝像頭進行測距的時候世界座標的原點究竟在**?
a:世界座標系的原點是左攝像頭凸透鏡的光心。
說起這個,就不得不提到針孔模型。如圖3所示,針孔模型是凸透鏡成像的一種簡化模型。當物距足夠遠時(遠大於兩倍焦距),凸透鏡成像可以看作是在焦距處的小孔成像。(ref:
圖3. 針孔模型
在實際計算過程中,為了計算方便,我們將像平面翻轉平移到針孔前,從而得到一種數學上更為簡單的等價形式(方便相似三角形的計算),如圖4所示。
圖4. 針孔模型的數學等價形式
因此,對應圖2就可以知道,世界座標系原點就是左攝像頭針孔模型的針孔,也就是左攝像頭凸透鏡的光心
q5:f和d的單位是畫素,那這個畫素到底表示什麼,它與公釐之間又是怎樣換算的?
a:這個問題也與針孔模型相關。在針孔模型中,光線穿過針孔(也就是凸透鏡中心)在焦距處上成像,因此,圖3的像平面就是攝像頭的ccd感測器的表面。每個ccd感測器都有一定的尺寸,也有一定的解析度,這個就確定了公釐與畫素點之間的轉換關係。舉個例子,ccd的尺寸是8mm x 6mm,解析度是640x480,那麼公釐與畫素點之間的轉換關係就是80pixel/mm。
在實際運用中,我們在數學上將這個像平面等效到小孔前(圖4),這樣就相當於將在透鏡中心點之前假設了一塊虛擬的ccd感測器。
q6:為什麼cvstereorectify求出的q矩陣cx, cy, f都與原來的不同?
a:這個在前文有提到過。在實際測量中,由於攝像頭擺放的關係,左右攝像頭的f, cx, cy都是不相同的。而為了使左右檢視達到完全平行對準的理想形式從而達到數學上運算的方便,立體 校準所做的工作事實上就是在左右像重合區域最大的情況下,讓兩個攝像頭光軸的前向平行,並且讓左右攝像頭的f, cx, cy相同。因此,q矩陣中的值與兩個instrinsic矩陣的值不一樣就可以理解了。
實驗結果:
實驗下來,雖然block matching演算法本身對精度有所限制,但測距基本能達到能讓人接受的精度,結果如下圖5所示
圖5. opencv雙攝像頭測距結果
上圖中,中、左、右三個物體分別被放在離攝像頭50cm, 75cm和90cm的位置。可以看出測距的結果相當不錯。當然,上面這幅圖是比較好的結果。由於bm演算法的限制,同一點雲中相同距離的點一般會有正負2厘公尺之內的誤差。
圖6是利用雙目攝像頭測物體長寬的結果,可以看出結果似乎不太準確。。。
圖6. opencv雙攝像頭測邊長結果
其中,物體寬為117-88=29mm,但實際寬度為5.2cm,物體高位71-13=58mm,但實際高度為13cm。這方面的誤差還是比較難以理解
此外,還有乙個問題至今尚未完全理解,就是雙目攝像頭的中心距,為什麼採用tx而不是t向量的長度。因為如果要左右檢視重合區域最大化的話兩個攝像頭的光軸都要與t垂直才是(如圖7),這樣的話,校正後兩個攝像頭的中心距應該是t才對。不知道我這樣的理解對不對?
圖7. 雙攝像頭立體校準俯檢視
opencv雙目測距實現
開篇之前,首先要感謝maxwellsdemon和wobject,沒有和你們的討論,也就沒有此篇的成文。說到雙攝像頭測距,首先要複習一下測距原理,把learning opencv翻到416和418頁,可以看到下面兩幅圖 圖1.雙攝像頭模型俯檢視 圖2,雙攝像頭模型立體檢視 圖1解釋了雙攝像頭測距的原理...
雙目測距測深度 科普 雙目測距原理
參考資料 1 深度相機原理揭秘 雙目立體視覺 2 雙目測距原理 3 相機標定原理及實現 1 雙目測距基本原理 如圖所示,p點是待測物體,camera r和camera l代表相機的光心位置,兩綠點為點p在兩個相機感光器上的成像點,f為相機焦距,b為兩相機中心距,z為所求深度資訊,兩綠點間距為d。d ...
雙目測距match cost 之rtl實現
以後爭取能達到月更,這次把雙目測距的sad cost匹配代價求法詳細介紹 不廢話,直接上圖 實現原理比較簡單,主要是點減,具體rtl實現過程中會遇到兩數相減出現負值的情況,如果這樣直接求取絕對值即可,在rtl實現過程中可以按照如下操作 第一種方式 c result 8 result 7 0 1 b1...