天天看點

深挖雙目視覺定位技術細節-标定函數

       提起來雙目定位,相信許多人像現在的我一樣,緊緊會用現成的公式,了解一些定義,明白那些參數的含義,但是深入的來說,估計連張正友教授的标定算法都沒有推明白。因為其中涉及一些矩陣運算的技巧,沒有數學基礎,或者基礎不牢,都無法深度了解。搞雙目兩年了,以前就是生成一張深度圖,或者進行一下雙目測距,網上的代碼複制粘貼修改一下就能用了,但是現在要搞高精度的雙目視覺定位,就必須深挖下去,搞清楚成像光路的方方面面。這裡,我提供一些網上總結比較好的部落格給新來的朋友鋪墊一下:https://www.cnblogs.com/zyly/p/9366080.html ;這篇部落格不僅系統的講解了成像坐标過程,而且在博文最後列舉了一系列參考部落格,感謝他把!“大奧特曼打小怪獸”;

           今天,先說說鏡頭畸變吧,因為沒有一個鏡頭沒有不畸變的,不過是畸變的大小不同,例如你用4.3mm的攝像頭(小型USB相機),基本上是平光鏡頭,其他的規格的,你就不能不考慮鏡頭畸變了。如果你搞搞深度圖,測測距離,基本也沒事那些都是低精度的,誤差大點無所謂,了不起用個張正友标定法,或者Matlib雙目标定一下,精度就不錯了。但是如果你要搞精密測量,糾結mm及的精度,那些方法就總是不能滿足你了。比如現在就不能滿足我了!怎麼辦,深挖技術細節,找到根!

           張氏标定法的偉大,在于将标定過程簡化到列印一張A4紙的棋盤格就能獲得比較高的精度,在攝影測量相機标定場總不能還貼A4紙吧!但是,但是,我們還可以用張正友标定法!不過是更加認真的考慮各個因素的用這個方法處理标定問題。這就是方法創新的意義!

說了這麼多多餘的話,就是為了抛出兩個相機标定的函數:OPENCV函數:

【A】CV_EXPORTS_AS(calibrateCameraExtended) double calibrateCamera( InputArrayOfArrays objectPoints,

                                     InputArrayOfArrays imagePoints, Size imageSize,

                                     InputOutputArray cameraMatrix, InputOutputArray distCoeffs,

                                     OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs,

                                     OutputArray stdDeviationsIntrinsics,

                                     OutputArray stdDeviationsExtrinsics,

                                     OutputArray perViewErrors,

                                     int flags = 0, TermCriteria criteria = TermCriteria(

                                        TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) );

這個【A】函數,是一個支援分析标定的函數,輸出的參數中給出了評估結果。

【B】CV_EXPORTS_W double calibrateCamera( InputArrayOfArrays objectPoints,

                                     InputArrayOfArrays imagePoints, Size imageSize,

                                     InputOutputArray cameraMatrix, InputOutputArray distCoeffs,

                                     OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs,

                                     int flags = 0, TermCriteria criteria = TermCriteria(

                                        TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON) );

這個【B】函數,與【A】僅有功能差別。

以下是一些關于這兩個函數怎麼用的介紹,直接從OPENCV函數翻譯過來的,翻譯有誤差,這裡說一下自己的了解:

1.InputArrayOfArrays objectPoints

這個objectPoints 就是所用的棋盤格角點的世界坐标,當然這裡由你用的标定闆給出。當然你如果自建标定規則要,注意他的資料類型是std :: vector <std :: vector <cv :: Vec3f >>,這意味着你照相多少次就生成多少次,其中的z坐标都為0;2.InputArrayOfArrays imagePoints

這個imagePoints顧名思義就是在圖像中提取棋盤格的角點的像點坐标,注意這是個資料類型是std :: vector <std :: vector <cv :: Vec2f >>,這個給你照相那些坐标都對照,一一對應

3. InputOutputArray cameraMatrix

這個好說就是相機内參數矩陣,可以初始化也可以不,與你後面選擇的計算模式有關系。

4.InputOutputArray distCoeffs

這個就是今天的重點,畸變參數。可以是4,5,8,12或14個元素。一般大家都用5參數,一般精度這個就夠了。至于高精度時候是不是參數越多越好,有人說多了容易不穩定,這一點我可以肯定的告訴你,對于描述一個模型參數越多肯定會越好,你想想現在的深度學習,那個網絡模型參數不是成千上萬!但是,但是,你參數多你需要拍的圖像就越多,而且你的标定場要建的的好!如果還拿個A4紙當标定闆,那就每必要設那麼多參數了。想想為啥?你的資料品質都不構,怎麼平差解方程!是以,這個地方就是一個分水領,不過對于一般計算機視覺需求,5個參數也就差不多了。

5. OutputArrayOfArrays rvecs,6.OutputArrayOfArrays tvecs

這兩個參數是标定過程中以标定闆為參考,相機的旋轉、平移參數,想想Matlib标定過程中最後給你一個鏡頭的大緻方向顯示。

 7.OutputArray stdDeviationsIntrinsics  8.OutputArray stdDeviationsExtrinsics  9.OutputArray perViewErrors

這些個參數是對這次标定結果的評價,值越小代表你标定的越好。

10. int flags = 0,

flags這個參數一般都設成0了,技巧也就在這裡。按說一般要精密标定,一般都要标定好幾次。控制一些置信度較高的參數不變,然後解算其他的。如果畸變參數選用過的不是5參數模型,則這個設定參考函數解釋。

11.TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)

這個設定是一個計算疊代的設定,一般不改變。如果高精度标定,也要好好研究一下,第一個參數是類型就是計算疊代的終止條件,第二個是疊代次數,第三個是設定的門檻值。預設的意思是疊代終止條件看後面的兩個參數,最大疊代次數30,最小門檻值是DBL_EPSILON。

标定函數技術細節如此,如有見解歡迎讨論,個人目前研究方向精密視覺測量!

參考如下:

/ ** @brief從校準圖案的多個視圖中查找相機的内部和外部參數。

@param objectPoints在新界面中,它是校準模式點矢量的矢量

校準模式坐标空間(例如std :: vector <std :: vector <cv :: Vec3f >>)。外面的

vector包含與模式視圖的數量一樣多的元素。如果校準模式相同

在每個視圖中顯示并且它是完全可見的,所有向量将是相同的。雖然如此

可以使用部分遮擋的圖案,甚至不同視圖中的不同圖案。然後,

向量将是不同的。這些點是3D,但由于它們處于圖案坐标系中,

那麼,如果鑽機是平面的,那麼将模型放到XY坐标平面上是有意義的

每個輸入對象點的Z坐标為0。

在舊界面中,來自不同視圖的對象點的所有向量被連接配接

一起。

@param imagePoints在新界面中,它是校準投影向量的向量

模式點(例如std :: vector <std :: vector <cv :: Vec2f >>)。 imagePoints.size()和

objectPoints.size()和imagePoints [i] .size()必須等于每個i的objectPoints [i] .size()。

在舊界面中,來自不同視圖的對象點的所有向量被連接配接

一起。

@param imageSize僅用于初始化内在相機矩陣的圖像大小。

@param cameraMatrix輸出3x3浮點相機矩陣

\ f $ A = \ vecthreethree {f_x} {0} {c_x} {0} {f_y} {c_y} {0} {0} {1} \ f $。如果CV \ _CALIB \ _USE \ _INTRINSIC \ _GUESS

和/或CV_CALIB_FIX_ASPECT_RATIO被指定,fx,fy,cx,cy中的部分或全部必須是

在調用函數之前初始化。

@param distCoeffs失真系數的輸出向量

\ f $(k_1,k_2,p_1,p_2 [,k_3 [,k_4,k_5,k_6 [,s_1,s_2,s_3,s_4 [,\ tau_x,\ tau_y]]]])\ f $ of

4,5,8,12或14個元素。

@param rvecs為每個模式視圖估計的旋轉矢量的輸出矢量(參見Rodrigues)

(例如std :: vector <cv :: Mat >>)。也就是說,每個第k個旋轉矢量與相應的一起

第k個平移向量(參見下一個輸出參數描述)帶來校準模式

從模型坐标空間(指定了對象點)到世界坐标

空間,即第k個模式視圖中校準圖案的實際位置(k = 0 .. * M * -1)。

@param tvecs為每個模式視圖估計的平移向量的輸出向量。

@param stdDeviationsIntrinsics為内在參數估算的标準差的輸出向量。

 偏內插補點的順序:

\ f $(f_x,f_y,c_x,c_y,k_1,k_2,p_1,p_2,k_3,k_4,k_5,k_6,s_1,s_2,s_3,

 s_4,\ tau_x,\ tau_y)\ f $如果沒有估計其中一個參數,它的偏差等于零。

@param stdDeviationsExtrinsics對外部參數估計的标準差的輸出向量。

 偏內插補點的順序:\ f $(R_1,T_1,\ dotsc,R_M,T_M)\ f $其中M是模式視圖的數量,

 \ f $ R_i,T_i \ f $連接配接1x3向量。

 @param perViewErrors為每個模式視圖估計的RMS重新投影誤差的輸出向量。

@param flags可能為零的不同标志或以下值的組合:

 -  ** CV_CALIB_USE_INTRINSIC_GUESS ** cameraMatrix包含有效的初始值

fx,fy,cx,cy進一步優化。否則,(cx,cy)最初設定為圖像

中心(使用imageSize),并以最小二乘方式計算焦距。

注意,如果已知内部參數,則不需要僅使用此函數

估計外在參數。請改用solvePnP。

 -  ** CV_CALIB_FIX_PRINCIPAL_POINT **全局期間主要點未更改

優化。它停留在中心或指定的不同位置

CV_CALIB_USE_INTRINSIC_GUESS也已設定。

 -  ** CV_CALIB_FIX_ASPECT_RATIO **函數僅将fy視為自由參數。該

比率fx / fy保持與輸入cameraMatrix相同。什麼時候

未設定CV_CALIB_USE_INTRINSIC_GUESS,fx和fy的實際輸入值為

忽略,隻計算它們的比率并進一步使用。

 -  ** CV_CALIB_ZERO_TANGENT_DIST **設定切向失真系數\ f $(p_1,p_2)\ f $

為零并保持為零。

 -  ** CV_CALIB_FIX_K1,...,CV_CALIB_FIX_K6 **相應的徑向失真

優化期間系數不變。如果CV_CALIB_USE_INTRINSIC_GUESS是

設定,使用提供的distCoeffs矩陣的系數。否則,它被設定為0。

 -  ** CV_CALIB_RATIONAL_MODEL **啟用系數k4,k5和k6。提供

向後相容性,應該明确指定這個額外的标志來制作

校準函數使用有理模型并傳回8個系數。如果标志不是

設定,該函數僅計算并傳回5個失真系數。

 -  ** CALIB_THIN_PRISM_MODEL **啟用系數s1,s2,s3和s4。

為了提供向後相容性,應該明确指定這個額外的标志來制作

校準功能使用薄棱鏡模型并傳回12個系數。如果标志不是

設定,該函數僅計算并傳回5個失真系數。

 -  ** CALIB_FIX_S1_S2_S3_S4 **薄棱鏡失真系數在此期間不會改變

優化。如果設定了CV_CALIB_USE_INTRINSIC_GUESS,則系數來自

提供了distCoeffs矩陣。否則,它被設定為0。

 -  ** CALIB_TILTED_MODEL **系數tauX和tauY已啟用。提供

向後相容性,應該明确指定這個額外的标志來制作

校準功能使用傾斜傳感器模型并傳回14個系數。如果标志不是

設定,該函數僅計算并傳回5個失真系數。

 -  ** CALIB_FIX_TAUX_TAUY **傾斜傳感器模型的系數在此期間不會改變

優化。如果設定了CV_CALIB_USE_INTRINSIC_GUESS,則系數來自

提供了distCoeffs矩陣。否則,它被設定為0。

@param criteria疊代優化算法的終止标準。

該函數估計兩個制作立體聲對的相機之間的轉換。如果你有一個立體聲

錄影機,兩個錄影機的相對位置和方向是固定的,如果你計算

相對于第一相機和第二相機(R1,T1)和(R2,T2)的物體姿勢,

分别(這可以用solvePnP完成),那些姿勢肯定是彼此相關的。

這意味着,給定(\ f $ R_1 \ f $,\ f $ T_1 \ f $),應該可以計算(\ f $ R_2 \ f $,\ f $ T_2 \ f $)。隻有你

需要知道第二台錄影機相對于第一台錄影機的位置和方向。這是

所述功能的作用。它計算(\ f $ R \ f $,\ f $ T \ f $),以便:

\ F [R_2 = R * R_1

T_2 = R * T_1 + T,\ f]

可選地,它計算基本矩陣E:

\ f [E = \ vecthreethree {0} { -  T_2} {T_1} {T_2} {0} { -  T_0} { -  T_1} {T_0} {0} * R \ f]

其中\ f $ T_i \ f $是翻譯向量的組成部分\ f $ T \ f $:\ f $ T = [T_0,T_1,T_2] ^ T \ f $。而且功能

也可以計算基本矩陣F:

\ f [F = cameraMatrix2 ^ { -  T} E cameraMatrix1 ^ { -  1} \ f]

除了立體聲相關資訊,該功能還可以執行每個的完整校準

兩個相機。但是,由于參數空間的高次元和輸入中的噪聲

資料,該功能可以偏離正确的解決方案。如果内在參數可以

每個錄影機單獨估算高精度(例如,使用

calibrateCamera),建議您這樣做,然後将CV_CALIB_FIX_INTRINSIC标志傳遞給

函數以及計算的内部參數。否則,如果所有參數都是

一次估計,限制一些參數是有意義的,例如,通過

CV_CALIB_SAME_FOCAL_LENGTH和CV_CALIB_ZERO_TANGENT_DIST标志,通常是

合理的假設。

與calibrateCamera類似,該功能最大限度地減少了所有的重新投影誤差

指向兩個攝像頭的所有可用視圖。該函數傳回的最終值

重新投影錯誤。

 * /