本文介紹使用OpenCV自帶的標定例程對單目攝像頭標定的過程。
操作系統:Linux
OpenCV版本:3.2.0
攝像頭:640×480像素,90度廣角鏡頭
一、標定步驟
1、找到標定例程
進入OpenCV安裝目錄,找到samples/cpp/tutorial_code/calib3d/camera_calibration
目錄,把它拷貝到一個合適的位置。(因為可能需要修改一些代碼,因此不建議直接在原目錄下使用。)
2、修改標定配置參數
找到camera_calibration/in_VID5.xml
文件,這是標定程序使用的配置文件,需要設置里面的幾個參數。
1.棋盤格的寬度和高度。
1 <!-- Number of inner corners per a item row and column. (square, circle) -->
2 <BoardSize_Width>9</BoardSize_Width>
3 <BoardSize_Height>6</BoardSize_Height>
需要特別注意的是,這里的寬度和高度是指內部交叉點的個數,而不是方形格的個數。如下圖所示的棋盤格,內部交叉點的寬度是9,高度是6。請務必填寫正確,否則無法標定。

2.每格的寬度
每格的寬度應設置為實際的毫米數,該參數的實際用途尚待考證。目前看來,即使設置的不准確也無大礙。
1 <!-- The size of a square in some user defined metric system (pixel, millimeter)-->
2 <Square_Size>20</Square_Size>
例程提供了三種輸入方式。不過,如果待標定的攝像頭已經接入電腦,建議使用input camera方式。該方式只需要設置視頻輸入設備號,對於筆記本電腦來說,通常0表示筆記本自帶攝像頭,1表示外接攝像頭。
1 <!-- The input to use for calibration. 2 To use an input camera -> give the ID of the camera, like "1"
3 To use an input video -> give the path of the input video, like "/tmp/x.avi"
4 To use an image list -> give the path to the XML or YAML file containing the list of the images, like "/tmp/circles_list.xml"
5 -->
6 <Input>"1"</Input>
3、編譯
新建camera_calibration/CMakeLists.txt
文件,寫入如下內容。
1 project(Camera_Calibration) 2 set(CMAKE_CXX_STANDARD 11) 3
4 find_package(OpenCV 3.0 QUIET) 5 if(NOT OpenCV_FOUND) 6 find_package(OpenCV 2.4.3 QUIET) 7 if(NOT OpenCV_FOUND) 8 message(FATAL_ERROR "OpenCV > 2.4.3 not found.") 9 endif() 10 endif() 11
12 include_directories(${OpenCV_INCLUDE_DIR}) 13 add_executable(Camera_Calibration camera_calibration.cpp) 14 target_link_libraries(Camera_Calibration ${OpenCV_LIBS})
編譯
1 wjg@wjg-PC:camera_calibration/build$ cmake .. 2 wjg@wjg-PC:camera_calibration/build$ make
4、運行
運行時需要傳入配置文件:
wjg@wjg-PC:camera_calibration/build$ Camera_Calibration ../in_VID5.xml
程序啟動后會出現當前攝像頭拍攝到的畫面,右下角有操作提示。按下鍵盤'q'鍵開始標定。請務必使攝像頭從不同方向拍攝棋盤格,以保證程序准確計算圖像畸變。共拍攝25張照片后自動結束標定,標定結果寫入camera_calibration/out_camera_data.xml
。此時,為了查看標定效果,可以按下鍵盤'u'鍵,畫面將切換到去畸變后的圖像,如果畸變完全消除,則標定成功,否則應該重新標定。
這里有一些注意事項:
- 可以直接在另一台電腦屏幕上顯示棋盤格,而不必打印出來。屏幕上顯示的棋盤格更平整,不會引入額外的誤差。
- 要在上下左右各個角度拍攝棋盤格,以減少各個圖片間的相關性,有利於求解相機參數和畸變系數。
現在,就可以使用標定好的相機內參和畸變系數啦!
二、相機去畸變
有了標定好的參數,如何把輸入圖片的畸變去除呢?其實很簡單,只需要調用OpenCV提供的一個函數就可以了:
cv::undistort(temp, frame, mK, mDistCoef);
其中,temp為原圖片,frame為去畸變后的圖片,mK為相機內參數矩陣,mDistCoef為畸變矩陣。后兩個矩陣都可以在camera_calibration/out_camera_data.xml
中找到。
三、理論知識——相機模型
光會用還不夠,我們應該至少了解為什么需要標定,標定有什么用。
簡單來說,標定是為了能夠從空間點的像素坐標映射到世界坐標,這是3D立體視覺必須經過的過程。這一過程需要三步,第一步從畸變的像素坐標映射到去畸變的像素坐標,需要用到畸變矩陣mDistCoef;第二步從去畸變的像素坐標映射到相機坐標,需要用到相機內參數矩陣mK;第三步從相機坐標映射到世界坐標,需要用到相機外參數矩陣,也就是相機位姿變換矩陣。下圖展示了第二步和第三步的過程。
