博客轉載自:http://blog.csdn.net/Loser__Wang/article/details/51811347html
本文目的在於記錄如何使用MATLAB作攝像機標定,並經過opencv進行校訂後的顯示。ios
首先關於校訂的基本知識經過OpenCV官網的介紹便可簡單瞭解:ide
http://docs.opencv.org/2.4/doc/tutorials/calib3d/camera_calibration/camera_calibration.html工具
對於攝像機咱們所關心的主要參數爲攝像機內參,以及幾個畸變係數。上面的鏈接中後半部分也給瞭如何標定,然而OpenCV自帶的標定程序稍顯繁瑣。於是在本文中我主推使用MATLAB的工具箱。下面讓咱們開始標定過程。spa
標定的最開始階段最須要的確定是標定板。兩種方法,直接從opencv官網上能下載到:
http://docs.opencv.org/2.4/_downloads/pattern.png.net
方法二:逼格滿滿(MATLAB)3d
J = (checkerboard(300,4,5)>0.5); figure, imshow(J);
那麼有了棋盤格以後天然是須要進行照片了。很少說,直接上程序。按q鍵便可保存圖像,儘可能把鏡頭的各個角度都覆蓋好。code
#include "opencv2/opencv.hpp" #include <string> #include <iostream> using namespace cv; using namespace std; int main() { VideoCapture inputVideo(0); //inputVideo.set(CV_CAP_PROP_FRAME_WIDTH, 320); //inputVideo.set(CV_CAP_PROP_FRAME_HEIGHT, 240); if (!inputVideo.isOpened()) { cout << "Could not open the input video " << endl; return -1; } Mat frame; string imgname; int f = 1; while (1) //Show the image captured in the window and repeat { inputVideo >> frame; // read if (frame.empty()) break; // check if at end imshow("Camera", frame); char key = waitKey(1); if (key == 27)break; if (key == 'q' || key == 'Q') { imgname = to_string(f++) + ".jpg"; imwrite(imgname, frame); } } cout << "Finished writing" << endl; return 0; }
保存大約15到20張便可。你們能夠看到個人方法,直接對着實驗室的屏幕拍攝的。這個階段有個注意事項就是測量好屏幕上每一個方格的大小,這個標定的時候會用到。htm
直接而在MATLAB的Command Window裏面輸入cameraCalibrator便可調用標定應用。 blog
首先先把以前照好的圖像添加進去,這是出現:
這就是以前讓你記錄的標定板中每一個方格的大小。 輸入無誤後就涉及到最關鍵的一步了(MATLAB的這個實在太方便了,都是傻瓜式操做),選擇參數。
爲何說他關鍵呢,由於若是你仔細閱讀了OpenCV的說明以後你會大概明白畸變參數,總共有五個,徑向畸變3個(k1,k2,k3)和切向畸變2個(p1,p2)。
徑向畸變
切向畸變
以及在OpenCV中的畸變係數的排列(這點必定要注意k1,k2,p1,p2,k3),千萬不要覺得k是連着的。
而且經過實驗代表,三個參數的時候因爲k3所對應的非線性較爲劇烈。估計的很差,容易產生極大的扭曲,因此咱們在MATLAB中選擇使用兩參數,而且選擇錯切和桶形畸變。
點擊開始後等待一段時間便可完成標定。而且MATLAB給出的可視化仍是很不錯的,能夠對比校訂先後的樣子
點擊show Undistorted便可看到無畸變的圖像
到這爲止,你已經完成了標定過程。選擇導出參數,便可把參數進行保存。
保存後能夠退出標定應用,在MATLAB主界面中將保存的Mat文件打開
第二行就是參數
裏面的RadialDistortion對應k1,k2,k3設置爲0了。
TangentialDistortion對應p1,p2。
IntrinsicMatrix對應內參,注意這個和OpenCV中是轉置的關係,注意不要搞錯。
對應
#include "opencv2/opencv.hpp" #include <iostream> using namespace cv; using namespace std; int main() { VideoCapture inputVideo(0); if (!inputVideo.isOpened()) { cout << "Could not open the input video: " << endl; return -1; } Mat frame; Mat frameCalibration; inputVideo >> frame; Mat cameraMatrix = Mat::eye(3, 3, CV_64F); cameraMatrix.at<double>(0, 0) = 4.450537506243416e+02; cameraMatrix.at<double>(0, 1) = 0.192095145445498; cameraMatrix.at<double>(0, 2) = 3.271489590204837e+02; cameraMatrix.at<double>(1, 1) = 4.473690628394497e+02; cameraMatrix.at<double>(1, 2) = 2.442734958206504e+02; Mat distCoeffs = Mat::zeros(5, 1, CV_64F); distCoeffs.at<double>(0, 0) = -0.320311439187776; distCoeffs.at<double>(1, 0) = 0.117708464407889; distCoeffs.at<double>(2, 0) = -0.00548954846049678; distCoeffs.at<double>(3, 0) = 0.00141925006352090; distCoeffs.at<double>(4, 0) = 0; Mat view, rview, map1, map2; Size imageSize; imageSize = frame.size(); initUndistortRectifyMap(cameraMatrix, distCoeffs, Mat(), getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0), imageSize, CV_16SC2, map1, map2); while (1) //Show the image captured in the window and repeat { inputVideo >> frame; // read if (frame.empty()) break; // check if at end remap(frame, frameCalibration, map1, map2, INTER_LINEAR); imshow("Origianl", frame); imshow("Calibration", frameCalibration); char key = waitKey(1); if (key == 27 || key == 'q' || key == 'Q')break; } return 0; }
修復以前和以後的結果對比
還有就是以前討論的爲何選2係數而不是3係數。由於。。。。。。。 下面是三係數的修正結果,慘不忍睹啊