OpenCV雙目標定的流程

轉載地址:

http://blog.csdn.net/chenyusiyuan/article/details/5967291

《1》首先應該閱讀張正友大神的文章,對單目標定,都求解的是哪些參數,如何求的初始值,然後是如何帶入到後面的L-M 優化中對參數refine的。

Zhang Z. A Flexible New Technique for Camera Calibration[J]. Tpami, 2000, 22(11):1330-1334.

Zhang Z. Flexible Camera Calibration by Viewing a Plane from Unknown Orientations[C]// The Proceedings of the Seventh IEEE International Conference on Computer Vision. IEEE, 2002:666-673 vol.1.

《2》然後閱讀Learning OpenCV的中文版第十一章(單目),第十二章(雙目),同時打開英文原版對照着一起閱讀。因爲中文版中有一些翻譯讀不太通順,而且有的公式印刷錯了,最好也在線打開OpenCV Documents,查看相應API 的解釋,比如OpenCV-2.4.13.5 Docs

《3》閱讀 OpenCV 源代碼目錄下 /samples/cpp 下的calibration.cpp(單目標定,矯正),stereo_calib.cpp(雙目標定,矯正,校正), stereo_match.cpp(雙目匹配,計算視差)


一些實踐總結:

《1》單目標定:

a. 根據張論文在自己實現求單應陣 H時,在棋盤格上選擇點時, 要保證能提供至少4個點,且這4個點不能有三點共線的情況,否則,實際上只有三個點有用。OpenCV中可以用RANSAC的思想計算魯棒的H。

b. 每個標定版平面和每個成像平面存在一個H。求解相機參數,至少需要2幀圖像(2幀時,除了構造AX=b 的方式和3幀以上的方式不一樣,還有額外的假設),一般3幀以上。 將這n幀 H 聯合起來解內參;

c. 內參求得後,帶入到每個H中求得每幀的位姿R,T

d. 論文中求畸變時,是對K1,K2,構造的方程,類似的擴展到K3, p1, p2的也可以自己推導,思路一致。

《2》雙目標定

a. 通過立體標定得到左右相機的外參R,T=[Tx,Ty,Tz]。設左,右相機的內參分別爲 :

KL=[fx_l,  0,    cx_l
     0,    fy_l,  cy_l
     0,     0,     1 ]

KR=[fx_r,  0,    cx_r
     0,    fy_r,  cy_r
     0,     0,     1 ]

畸變係數各自爲:distCoeffsL, distCoeffsR

Mat Rl, Rr, Pl, Pr, Q;   Rect validRoi[2];
	stereoRectify(cameraMatrix[0], distCoeffs[0],
		cameraMatrix[1], distCoeffs[1],
		imageSize, R, T, Rl, Rr, Pl, Pr, Q,
		CALIB_ZERO_DISPARITY, 1, imageSize, &validRoi[0], &validRoi[1]);

最後由stereoRectify()函數輸出的 Rl, Rr,Pl,Pr分別是 :

Rl:左相機和左虛擬相機的變換,只有旋轉Rl,沒有平移; 兩個虛擬相機之間是共面,行對齊。

Rr:右相機和右虛擬相機的變換,只有旋轉Rr,沒有平移;

Rl, Rr是如下得來:

1.     把 R分解爲兩個旋轉矩陣rl, rr,每個都旋轉一半,rl, rr 滿足: rr * rl=R  //實際發現,rr,rl所在的軸角方向,與原來R所在的軸角方向不一致。

2.      Eigen::Vector3d e1 = T.normalized(); 
	Eigen::Vector3d e2 = Eigen::Vector3d(-T(1), T(0), 0);
	e2.normalize();
	Eigen::Vector3d e3 = e1.cross(e2);

	Eigen::Matrix3d Rect, rl, rr;
	Rect << e1.transpose(), e2.transpose(), e3.transpose();
	
        RL=Rect* rl;  
        RR=Rect* rr;

Pl: 左虛擬相機的內參KL_virtual;

Pr:  右虛擬相機的內參KR_virtual;

KL_virtual=[f, 0 , cx1, 0
            0, f,  cy,  0
            0, 0,  1,   0 ]

KR_virtual=[f, 0 , cx2, f*b
            0, f,  cy,  0
            0, 0,  1,   0 ]

 stereoRectify() 的標誌位 flags=CALIB_ZERO_DISPARITY時, cx1=cx2, 深度值計算公式不變:

Z=f*b/d

當標誌位不是上面的時,cx1 不等於cx2, 深度值計算公式修正爲:

Z=f*b/(d-delta), delta=cx1-cx2

輸出的Q:當flags=CALIB_ZERO_DISPARITY時, Q(3,3)=0

Q=[1, 0,  0, -cx1
   0, 1,  0, -cy
   0, 0,  0,  f
   0, 0,  -1/b, (cx1-cx2)/b ]

實際發現: 

OpenCV中返回的 Q(3,2)是 1/b,取了絕對值。

兩個虛擬相機的基線b=normal(T)

b. 然後分別對原始左右相機計算映射陣

Mat rmap[2][2];
initUndistortRectifyMap( KL, distCoeffsL, Rl, Pl, imageSize, CV_16SC2, rmap[0][0], rmap[0][1]);
initUndistortRectifyMap( KR, distCoeffsR, Rr, Pr, imageSize, CV_16SC2, rmap[1][0], rmap[1][1]);

c.最後

Mat img = imread(raw_image, 0), rimg;
remap(img, rimg, rmap[0][0], rmap[0][1], CV_INTER_LINEAR);//對左圖rectification
相應的用 rmap[1][0], rmap[1][1]對右圖rectify 。


論文 “A Compact Algorithm for Rectification of Stereo Pairs” Andrea Fusiello · Emanuele Trucco · Alessandro Verri  也提出了一種計算rectify的方法,其中有幾個地方備註:





OpenCV 和matlab中計算rectify的方法和上面論文中不一樣,大致原理:Learning OpenCV 12章,具體細節詳見  matlab工具箱中 rectify_stereo_pair.m。

Matlab Calibration ToolBox    http://www.vision.caltech.edu/bouguetj/calib_doc/index.html

這樣大致就對單應矩陣,本徵矩陣,基礎矩陣有了一個大致瞭解。從上面可以大致看來,對空間點3D位置估計的精確程度取決於該點深度值的計算,而深度值的計算主要依賴於雙目匹配,或者叫立體匹配的精度,當然也依賴於前期標定過程中確定的相機內參,畸變參數,兩個相機間R,T的精確程度。

 http://vision.deis.unibo.it/~smatt/stereo.htm   Stefano Mattoccia 的講義 Stereo Vision: algorithms and applications,190頁的ppt,講解得非常形象詳盡。

還沒看,待續。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章