世界坐標系的三維點投影到成像
坐標系中的二維點的投影公式如下:
其中(X,Y,Z)為世界坐標系中的三維點;
(u,v)為成像面坐標系中的二維點;
A為相機的內參數矩陣:(cx,cy)為主光軸點,一般為圖像的中心;fx和fy為焦距;
[R|t]為相機的外參數矩陣:R為旋轉矩陣,t為位移矩陣;
上述公式的簡單推理過程如下
考慮到鏡頭畸變
其中,k1,k2,k3,k4,k5和k6為徑向畸變,p1和p2為軸向畸變。在opencv中,畸變矩陣的參數為(k1,k2,p1,p2[,k3[,k4,k5,k6]]])。
Opencv中的標定模塊常用的標定函數:
double calibrateCamera(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints,Size imageSize, InputOutputArray cameraMatrix, InputOutputArray distCoeffs, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, int flags=0)
其中
objectPoints為世界坐標系中的點。在使用時,應該輸入一個三維點的vector的vector,即vector<vector<Point3f> > (注要記得括號的區別)objectPoints。
imagePoints為其對應的圖像點。和objectPoints一樣,應該輸入std::vector<std::vector<cv::Point2f> > imagePoints型的變量。
imageSize為圖像的大小,在計算相機的內參數和畸變矩陣需要用到;
cameraMatrix為內參數矩陣(相機矩陣 cameraMatrix)
。輸入一個cv::Mat cameraMatrix即可。
distCoeffs為畸變矩陣。輸入一個cv::Mat distCoeffs即可。
rvecs為旋轉向量;應該輸入一個cv::Mat的vector,即vector<cv::Mat> rvecs因為每個vector<Point3f>會得到一個rvecs。
tvecs為位移向量;和rvecs一樣,也應該為vector<cv::Mat> tvecs。
flags為標定是所采用的算法。可如下某個或者某幾個參數:
CV_CALIB_USE_INTRINSIC_GUESS:使用該參數時,在cameraMatrix矩陣中應該有fx,fy,cx,cy的估計值。否則的話,將初始化(cx,cy)圖像的中心點,使用最小二乘估算出fx,fy。如果內參數矩陣和畸變居中已知的時候,應該標定模塊中的solvePnP()函數計算外參數矩陣。
CV_CALIB_FIX_PRINCIPAL_POINT:在進行優化時會固定光軸點。當CV_CALIB_USE_INTRINSIC_GUESS參數被設置,光軸點將保持在中心或者某個輸入的值。
CV_CALIB_FIX_ASPECT_RATIO:固定fx/fy的比值,只將fy作為可變量,進行優化計算。當CV_CALIB_USE_INTRINSIC_GUESS沒有被設置,fx和fy將會被忽略。只有fx/fy的比值在計算中會被用到。
CV_CALIB_ZERO_TANGENT_DIST:設定切向畸變參數(p1,p2)為零。
CV_CALIB_FIX_K1,...,CV_CALIB_FIX_K6:對應的徑向畸變在優化中保持不變。如果設置了CV_CALIB_USE_INTRINSIC_GUESS參數,
CV_CALIB_RATIONAL_MODEL:計算k4,k5,k6三個畸變參數。如果沒有設置,則只計算其它5個畸變參數。
在此注明下相機校正的幾個關鍵步驟,在我的下一篇博文里面有實現的代碼
addChessboardPoints()
函數 - 用於讀入一系列的棋盤圖像並檢測角點;calibrate()
函數 - 用於進行相機校正,得到相機的參數矩陣和畸變系數;remap()
函數 - 用於根據相機校正結果修復圖像的畸變;//主要靠這個函數實現校正initUndistortRectifyMapaddPoints()
函數 -addChessboardPoints()
在檢測完角點后會調用這個函數。也可自己手動調用這個函數添加已知的角點位置和對應的空間坐標點。