OpenCV3.0 alpha在8月21日發布,其中增加了魚眼鏡頭模型,提供了標定、去畸變等一系列api,其實現方法參考了{Camera Calibration Toolbox for Matlab}。本文簡單介紹了OpenCV 中實現的魚眼鏡頭模型,給出調用demo的關鍵代碼、注釋和去畸變的結果。
魚眼鏡頭模型
魚眼鏡頭的內參模型可以表示為,與普通鏡頭的內參一樣,但畸變參數不同,為
,含義如下:
設(X,Y,Z)為一個三維坐標點,投影在圖像上的二維坐標為(u,v),如果不考慮畸變,投影關系如下:
R和t分別代表相機外參中的旋轉矩陣和平移向量。
當考慮魚眼鏡頭的畸變后,投影關系轉化為:
標定流程
首先調用OpenCV的FindChessboardCorners()來尋找圖像上的標定板的角點,再根據標定板的尺寸指定這些角點對應的三維點的三維坐標,再調用fisheye::calibrate()來進行標定,利用標定結果中的內參和畸變參數調用fisheye::undistortImage()對圖像做去畸變操作。
代碼片段
tuple<Mat, Mat, double> calibrate_fisheye(const vector<Mat>& images, const Settings& s) { /*尋找二維角點*/ auto corners = chessboard_corners(images, s); /*計算二維角點對應的三維點坐標*/ auto object_points = vector<vector<Point3d>>(corners.size(), object_positions(s)); cv::Matx33d K; cv::Vec4d D;int flag = 0; flag |= cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC; flag |= cv::fisheye::CALIB_CHECK_COND; flag |= cv::fisheye::CALIB_FIX_SKEW;/*非常重要*/ double rms = fisheye::calibrate(object_points, corners, s.imageSize, K, D, cv::noArray(), cv::noArray(), flag, cv::TermCriteria(3, 20, 1e-6)); return make_tuple(Mat(K), Mat(D), rms); }
代碼非常簡單,和標定普通的鏡頭的區別在於:
- 角點坐標和和對應的三維點坐標為double類型,普通鏡頭為float類型,弄混后不能正確執行
- flag必須指定CALIB_FIX_SKEW,代表求解時假設內參中fx=fy,與魚眼鏡頭標定論文中一致,沒有這個假設的話是得不到結果的
結果
測試了OpenCV的測試數據,34張圖像進行標定,重投影誤差均值為0.343542。
左邊為源圖像,右邊為去畸變結果:
未完成工作
本來以為在畸變圖像上找棋盤格角點會比一般的方法復雜一些,沒想到利用FindChessboardCorners就可以成功找到,所以就暫時這樣用了,對於畸變比較大的圖像,或者手工標出角點,或者實現論文《Automatic Detection of Checkerboards on Blurred and Distorted Images》中自動提取棋盤格的方法。
參考:
http://docs.opencv.org/master/modules/calib3d/doc/calib3d.html