相机标定总结
相機標定總結
from:?http://blog.sina.com.cn/s/blog_a2885cb50102vm1g.html
本文是一篇關于相機標定意義和原理的個人總結,包含了OpenCV和Matlab中常用的相機標定函數的注解。
相機標定是機器視覺的基礎,標定結果的好壞直接決定了機器視覺的系統精度,作用可見一斑。在這一年半的時間里,我個人也是隨著實驗和程序的進一步理解,對標定的原理和意義有了更多的想法。同樣,由于博文的關系,仍有一些朋友會常常詢問標定的程序問題。本人的2010-05-17OpenCV標定程序
的問題也多次被朋友詢問,由于當時對標定的認識還不夠系統,因此現在認為該文對標定的意義和原理有很多誤解,并在此推薦一些較好的博文拱大家學習:
雙目測距與三維重建的OpenCV實現問題集錦(一)圖像獲取與單目標定;
雙目測距與三維重建的OpenCV實現問題集錦(二)雙目標定與雙目校正;
雙攝像頭測距的OpenCV實現;
分享一些OpenCV實現立體視覺的經驗;
下面結合本人的畢業論文及一年半來對機器視覺的學習,對相機標定的意義和原理進行敘述。
1.單目相機模型
單目相機模型中的三種坐標系關系如圖1所示,相機坐標系即是以光軸中心O為原點的坐標系,其z軸滿足右手法則,成像原點所代表平面即為像平面坐標系(實際應用中,均以圖像左上角為坐標系原點),實際物體坐標系即為世界坐標系。
圖1?單目相機模型的三坐標系統關系
其中,在世界坐標系的值為,是在像平面坐標系的投影點,其相機坐標系的值為。是相機坐標系軸與像平面夾角,一般情況下軸與像平面垂直,值為。且相機坐標系與像平面平行,為相機的焦距。
對于從相機坐標系到像平面坐標系的變換,像平面坐標系是用像素單位來表示的,而相機坐標系則是以毫米為單位來表示,因此,要完成改變換過程就需要先得到像平面的像素單位與毫米單位之間的線性關系。在圖1中,相機光軸中心z軸方向上與像平面的交點稱為投影中心,坐標為,是像素單位,而每個像素在和的物理尺寸為和,單位是像素/毫米,則像平面的像素與毫米間的線性關系如式(1):
(1)根據小孔模型下投影變換原理,像平面的物理坐標對應的相機坐標系滿足式(2):
??????????????????????????????(2)
其對應的矩陣形式為式(3):
?????????????????(3)
聯立式(1)和式(3),得到式(4)即為相機坐標系與像平面坐標系變換的矩陣。
???????????????????(4)
左圖????其中,左圖即為相機的6個內參數,其組成的矩陣即為內參數矩陣。
????對于從相機坐標系到世界坐標系的變換,是通過旋轉矩陣R和平移矩陣T完成的,如圖2所示。
圖2?相機坐標系與世界坐標系的變換關系
其中,平移矩陣T是三維列向量,旋轉矩陣R是坐標軸依次繞和軸旋轉角度和所形成的三個矩陣的總乘積。它們的定義如式(5):
?????????????????????????(5)
則矩陣R的計算公式如式(6):
?(6)
因此,從相機坐標系到世界坐標系的變換如式(7),其中,表示,為旋轉矩陣,為平移矩陣,該變換矩陣稱為外參數矩陣。
???????????????????????(7)
最后,聯立式(4)和式(7)求得像平面坐標系與世界坐標系之間的變換關系,如式(8):
????????????(8)
其中,即為透視投影矩陣,表示空間中三維點坐標與圖像平面二維坐標之間的線性關系,表示的像平面齊次坐標值,表示的世界坐標系齊次坐標值。基于以上幾何原理和相機模型得到的圖像信息和三維信息之間的關系,存在不可逆性,即可以通過已知世界坐標系的坐標值求得二維坐標值,如果要進行二維坐標到三維坐標的反求還需要其他的數學模型輔助求解。
2.Matlab標定工具箱應用
1)??制作標定板,標定板尺寸為324(mm)X252(mm),即7行9列63個36mm的正方形方格組成,如圖3所示。
圖3??標定方格板
2)??將水平平行的左右相機同時采集標定板的不同位姿圖像,共計12組位姿(對于采集的圖像,位姿越多,標定結果也會越精確,建議在10組到20組之間)如圖4,5所示。
圖4??左相機的標定圖像
圖5??右相機的標定圖像
3)??在工具箱中通過Extract grid corners提取每幅標定圖像的特征點(即黑方格與白方格的交點)。
4)??進行單目標定,得到左右相機的內外參數以及畸變系數,并將參數保存到Calib_Results_left和Calib_Results_right兩個mat格式的文件中。
3.Matlab標定結果與OpenCV標定結果的比較與分析
Matlab標定結果:
通過上節的步驟(1)-(4),可以得到如圖6和7所示的左右相機的內參數、畸變系數結果。
圖6??左相機的內參數和畸變系數
圖7??右相機的內參數和畸變系數
?????????對于左右相機由于透鏡畸變造成的誤差使用工具箱中的visualize_distortions功能進行分析,可以得到左相機的畸變圖,如8、9、10所示,相應的右相機畸變圖,如11、12、13所示。
圖8??左相機鏡頭畸變圖
圖9??左相機徑向畸變圖
圖10??左相機切向畸變圖
?????????對于圖8到10,圖中的0點即為左相機光學中心,圖中的箭頭顯示相機圖像的畸變方向。圖8左相機整體畸變模型中,該相機的左側畸變不明顯,若物體的圖像在此則不易受畸變因素影響造成線條的彎曲;圖9左相機徑向畸變模型中,該相機的畸變系數由中心向外增大,即物體的圖像越靠近圖像邊緣,其線條的彎曲程度就越大;圖10左相機切向畸變模型中,箭頭方向顯示該相機切向畸變的增大方向,在相機的左側其切向畸變與徑向畸變的方向相反,使得整體畸變模型中,相機左側的畸變較小。
圖11??右相機鏡頭畸變圖
圖12??右相機徑向畸變圖
圖13??右相機切向畸變圖
對于圖11到13,圖中的0點與左相機相同,即為右相機光學中心,圖中的箭頭顯示相機圖像的畸變方向。圖11右相機整體畸變模型中,該相機的中間及偏左側畸變不明顯,若物體的圖像在此則不易受畸變因素影響造成線條的彎曲;圖12右相機徑向畸變模型中,該相機的畸變系數由中心向外增大,但右相機比左相機在光軸中心附近有更大的區域畸變很小,因此位于右側相機光學中心的圖像,其線條因受畸變造成的彎曲很小;圖13右相機切向畸變模型中,箭頭方向顯示該相機切向畸變的增大方向,在相機的左側其切向畸變與徑向畸變的方向相反,使得整體畸變模型中,位于右相機圖像左側的線條受畸變影響較小。
OpenCV標定結果:
在此列舉的OpenCV標定結果是我雙目視覺標定且優化后的結果,與Matlab的會有差異。
左側相機的內參數矩陣:
?????????????????????????????????(9)
右側相機的內參數矩陣:
????????????????????????????????(10)
該式(9)-(10)與式(1)相對應。而Matlab中的cc對應于式(1)中的相機光軸中心在圖像平面的投影坐標,fc即為式(1)中的和。
至此,講解完了OpenCV與Matlab所對應的相機標定內參數矩陣的含義。
OpenCV與Matlab標定中的差異:
OpenCV的標定參數中,對于鏡頭畸變采用的方法是Brown博士在71年發表的文章中提到的;而Matlab中的鏡頭畸變參數采用基于Heikkil博士提出的方法,將非線性干擾因素引入到內外參數的求解過程。
Heikkil采用的矩陣來表示以上的兩種畸變系數。根據Brown的非線性模型,和表示鏡頭的徑向畸變系數,通常只使用兩項,只是針對即便較大的鏡頭(例如魚眼鏡頭,其余情況下該系數值為0),而和表示切向畸變系數,由式(11)和式(12)求解該矩陣,本文的畸變系數求解伴隨在相機標定過程中。
????????????????????????(11)
其中,
是像平面上的任一點坐標值,是進行徑向畸變矯正后的坐標值,是
作為光學中心畸變為0的點進行泰勒級數展開后得到的。
?????????????????????(12)
其中,是像平面上的任一點坐標值,是進行切向畸變矯正后的坐標值,如式(11)的定義相同。
4.外參數的作用及其在相機標定中的意義
外參數定義了如圖2所示的圖像平面到世界坐標系的變換關系。而標定就是通過相機尋找圖像平面中如圖3所示的標定板的特征點位置,所以得到的外參數是圖像平面與標定板所處平面的線性變換關系。在我的2010-06-14基于Matlab的雙目視覺定位問題研究
中,通過Matlab標定工具箱產生的圖4與圖5就可以表達上述含義。
因此,對于不同的棋盤格標定板空間位置,必然對應于不同的外參數矩陣。同樣的,在視覺伺服中,雅可比矩陣也有同樣的數學意義。對于視覺伺服,個人認為可以看些徐德的論文入門。
5.OpenCV標定程序說明
用于尋找圖像中的棋盤格標定板的特征點:
???????CvSize?board_sz=?cvSize(?board_w,board_h?);
?
???????IplImage*?imgLeft=cvCreateImage(cvSize(imgL->width,imgL->height),imgL->depth,imgL->nChannels);
???????IplImage*?imgRight=cvCreateImage(cvSize(imgR->width,imgR->height),imgR->depth,imgR->nChannels);
?
???????CvPoint2D32f*?cornersLeft=?new?CvPoint2D32f[board_n?];
???????CvPoint2D32f*?cornersRight=?new?CvPoint2D32f[board_n?];
?
???????int?corner_countLeft,corner_countRight;
?
???????cvResize(imgL,imgLeft,CV_INTER_LINEAR);
???????cvResize(imgR,imgRight,CV_INTER_LINEAR);
?
???????if(frame++ %?board_dt?== 0) {
??????????????//Find chessboard corners:
??????????????int?foundLeft?=?cvFindChessboardCorners(
?????????????????????imgLeft,?board_sz,cornersLeft, &corner_countLeft,
?????????????????????CV_CALIB_CB_ADAPTIVE_THRESH?|?CV_CALIB_CB_FILTER_QUADS
?????????????????????);
??????????????int?foundRight?=?cvFindChessboardCorners(
?????????????????????imgRight,?board_sz,cornersRight, &corner_countRight,
?????????????????????CV_CALIB_CB_ADAPTIVE_THRESH?|?CV_CALIB_CB_FILTER_QUADS
?????????????????????);
?
??????????????//Get Subpixel accuracy on those corners
??????????????cvCvtColor(imgLeft,grayLeft,?CV_BGR2GRAY);//if input is colorful then use this
??????????????cvCvtColor(imgRight,grayRight,?CV_BGR2GRAY);
??????????????//cvCopy(image1, gray_image1);
??????????????//cvCopy(image2, gray_image2);
?
??????????????cvFindCornerSubPix(grayLeft,cornersLeft,?corner_countLeft,
?????????????????????cvSize(11,11),cvSize(-1,-1),cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 ));//尋找棋盤格標定板的特征點
??????????????cvFindCornerSubPix(grayRight,cornersRight,?corner_countRight,
?????????????????????cvSize(11,11),cvSize(-1,-1),cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 )); //尋找棋盤格標定板的特征點
?
??????????????//畫出找到的特征點
??????????????cvDrawChessboardCorners(imgLeft,board_sz,?cornersLeft,corner_countLeft,?foundLeft);
??????????????cvDrawChessboardCorners(imgRight,board_sz,?cornersRight,corner_countRight,foundRight);
?
??????????????if?(corner_countLeft>=board_n?&&?foundLeft&&?corner_countRight>=board_n?&&foundRight)
??????????????{//保存特征點在圖像坐標中的坐標值,用于Calibrate2和StereoCalibration的調用
?????????????????????step?=?success*board_n;
?????????????????????for(?int?i=step,?j=0;?j<<span>board_n; ++i,++j?) {
????????????????????????????CV_MAT_ELEM(*image_pointsLeft,float,i,0) =cornersLeft[j].x;
????????????????????????????CV_MAT_ELEM(*image_pointsLeft,float,i,1) =cornersLeft[j].y;
????????????????????????????CV_MAT_ELEM(*image_pointsRight,float,i,0) =cornersRight[j].x;
????????????????????????????CV_MAT_ELEM(*image_pointsRight,float,i,1) =cornersRight[j].y;
????????????????????????????CV_MAT_ELEM(*object_points,float,i,0) = (float)(j/board_w);
????????????????????????????CV_MAT_ELEM(*object_points,float,i,1) = (float)(j%board_w);
????????????????????????????CV_MAT_ELEM(*object_points,float,i,2) = 0.0f;
?????????????????????}
?????????????????????CV_MAT_ELEM(*point_counts,int,success,0)=?board_n;
??????????????}
???????}
隨后調用cvCalibateCamera2和cvStereoCalibate函數進行相機的標定。標定的例程可以參考LearningOpenCV。
?
以下推薦兩本OpenCV的參考書:
學習OpenCV(中文版) 于仕琪譯 清華大學出版社,2009;(OpenCV 2.0庫)
基于OpenCV的計算機視覺技術實現 陳勝勇,劉盛編著 科學出版社,2008;(OpenCV 1.0庫)
www.opencv.org.cn
中文論壇
總結
- 上一篇: 摄像机的建模
- 下一篇: 三维视觉传感器的类型