單目標定:從理論到OpenCV實踐
一、針 孔攝像機模型
1.1 優缺點
優點:簡單好用。
缺點:真實的針孔由於不能為快速曝光收集足夠的光線,因此不是得到圖像的好方法。
1.2 針 孔攝像機模型圖與公式
1.2.1 理想情況
描述:芯片是正方形,芯片中心在光軸上。
f:攝像機焦距
Z:攝像機到物體的距離
X:物理物體長度
x:圖像上的物體長度
1.2.2 實際情況
描述:芯片是矩形(長寬不同),芯片中心不在光軸上。
實際上,芯片的中心通常不在光軸上,因此引入新的參數cx和cy;
物理世界中的點Q(X,Y,Z),以某些偏移的方式投影為點(x_srceen,y_srceen):
1.3 基本投影幾何
1.3.1 投影變換的定義
1.3.2 攝像機內參數矩陣
【重要概念】
定義攝像機的參數(fx,fy,cx,cy)重新排列為3X3的矩陣,稱為攝像機內參數矩陣。
二、透鏡攝像機
2.1 優缺點
優點:利用透鏡收集更多的光線;
缺點:背離了針 孔幾何模型,而且引入透鏡的畸變。
2.2 透鏡畸變
2.2.1 畸變產生原因
畸變產生原因:理論上講是可能定義一種透鏡而不引入任何畸變的,然后現實世界沒有完美的透鏡。這主要是制造上的原因,因為制作一個"球形"透鏡比制作一個數學上理想的透鏡更容易。而且從機械方面也很難把透鏡和成像儀保持平行。
兩種主要的畸變:徑向畸變和切向畸變。
2.2.2 徑向畸變
【重要概念】
徑向畸變:來自於透鏡形狀;
2.2.3 切向畸變
【重要概念】
切向畸變:來自於整個攝像機的組裝過程。
2.2.4 其他畸變
三、旋轉矩陣和平移向量
【重要概念】
四、攝像機內外參數總結
攝像機參數:一般一共15個相關參數:
(1)外參數6個:旋轉3個參數;平移3個參數;
(2)內參數4個:fx,fy,cx,cy;
求解上述10個參數的前提是先假設每次的畸變參數為0;
(3)5個畸變參數:k1,k2,k3,p1,p2;
其中(2)和(3)都為攝像機內參數,其中k3在普通鏡頭不使用,魚眼鏡頭要使用。
五、攝像機標定
5.1 標定目的
矯正因使用透鏡而給針 孔模型帶來的主要偏差。
標定的過程既給出攝像機幾何模型、也給出透鏡的畸變模型,即求解上述的15個相關參數。
5.2 單應性矩陣
【重要概念】
單應性矩陣主要解決外參數和內參數矩陣,且假設畸變參數為0。
在計算機視覺中,平面的單應性被定義為從一個平面到另一個平面的投影映射。
5.3 棋盤
5.3.1 棋盤大小
(1)標准
一個標准象棋棋盤,格子為7X7。
(2)非標准
(3)最小要求
最少需要4個點(3X3的棋盤點)
(4)格子多的好處
5.3.2 角點數量與棋盤圖片數量要求
5.4 OpenCV求解標定的理論方法
5.4.1 攝像機標定的理論方法簡介
(1)傳統標定法
傳統標定技術在定標的時候,需要在攝像機前放置一個特定的標定物,並認為地提供一組已知坐標的特征基元,攝像機通過尋找標定物上這些已知的特征基元來實現定標。它用到了很多射影幾何方面的理論,是一種直接計算攝像機模型的方法。
(2)自標定法
自標定技術則更為靈活,它不需要特定的參照物來實現定標,是一種對環境具有很強適應性的定標技術,也是目前研究的熱點。它利用環境的剛體性,通過對比多幅圖像中的對應點來計算攝像機模型,但就目前的研究來看,其定標精度還無法與傳統定標技術相比。
(3)張正友標定法
5.4.1 OpenCV采用的理論方法
5.4.2 張正友標定相關理論資料
(1)精簡版8頁《Flexible Camera Calibration by Viewing a Plane from Unknown Orientations》- Zhang1999
網址:http://www.vision.caltech.edu/bouguetj/calib_doc/papers/zhan99.pdf
(2)完整版22頁《A Flexible New Technique for Camera Calibration.rar》- Zhang2000
網址:http://research.microsoft.com/~zhang/Papers/TR98-71.pdf
(3)張正友主頁:
網址:http://research.microsoft.com/en-us/um/people/zhang/
(3)張正友主頁中的相機標定頁:
網址:http://research.microsoft.com/en-us/um/people/zhang/Calib/
5.4.3 Brown論文資料
網址:http://www.ifp.uni-stuttgart.de/lehre/vorlesungen/Aero/Brown71.pdf
六、矯正
利用棋盤標定的結果可進行畸變矯正。
七、OpenCV1.1主要相關函數
7.1 單目標定流程與對應主要函數
(1)查找棋盤角點:cvFindChessboardCorners;
(2)亞像素角點:cvFindCornerSubPix;
(3)顯示角點結果:cvDrawChessboardCorners;
(4)單目標定:
[A]方式一:獲取攝像機內外參數:cvCalibrateCamera2(內部包含
cvFindExtrinsicCameraParams2);
[B]方式二:根據攝像機內參數求取外參數:cvFindExtrinsicCameraParams2
注意:上述兩種方式輸出的是旋轉向量和平移向量,如果需要轉換為矩陣使用函數cvRodrigues2,該函數可以將向量和矩陣進行互轉。
(5)圖像畸變矯正:
[A]單目圖像畸變矯正方式一(效率低):cvUndistort2;
[B]單目圖像畸變矯正方式二(效率高):cvInitUndistortMap+cvRemap;
[C]雙目點畸變矯正:cvUndistortPoints(注意:輸入輸出為點坐標,只能在雙目標定中使用)。
(6)統計單目標定誤差(計算3D點在圖像上的投影坐標與棋盤點坐標的差值):
cvProjectPoints2+cvNorm。
注意:cvProjectPoints2輸入的是旋轉向量和平移向量。
7.2 主要相關函數詳解
7.2.1 cvCalibrateCamera2詳解
(1)函數原型
void cvCalibrateCamera2(const CvMat* object_points,
const CvMat* image_points,
const CvMat* point_counts,
CvSize image_size,
CvMat* intrinsic_matrix,//[output]
CvMat* distortion_coeffs,//[output]
CvMat* rotation_vectors=NULL,//[output]
CvMat* translation_vectors=NULL,//[output]
int flags=0
);
(2)參數注釋(9個)
-
object_points:
定標點的世界坐標,為3xN或者Nx3的矩陣,這里N是所有視圖中點的總數。
http://www.360doc.com/content/14/0410/14/10724725_367762917.shtml
-
image_points:
定標點的圖像坐標,為2xN或者Nx2的矩陣,這里N是所有視圖中點的總數。
-
point_counts:
向量,指定不同視圖里點的數目,1xM或者Mx1向量,M是視圖數目。
-
image_size:
圖像大小,只用在初始化內參數時。
-
intrinsic_matrix
輸出內參矩陣(A) ,如果指定
CV_CALIB_USE_INTRINSIC_GUESS和(或)CV_CALIB_FIX_ASPECT_RATION,fx、 fy、 cx和cy部分或者全部必須被初始化。
-
distortion_coeffs:
輸出大小為4x1或者1x4的向量,里面為形變參數[k1, k2, p1, p2]。
-
rotation_vectors:
輸出大小為3xM或者Mx3的矩陣,里面為旋轉向量(旋轉矩陣的緊湊表示方式,具體參考函數cvRodrigues2)
-
translation_vectors:
輸出大小為3xM或Mx3的矩陣,里面為平移向量。
-
flags:【重點】
不同的標志,可以是0(默認),或者下面值的組合:
-
CV_CALIB_USE_INTRINSIC_GUESS(1):內參數矩陣包含fx,fy,cx和cy的初始值。否則,(cx, cy)被初始化到圖像中心(這兒用到圖像大小),焦距用最小平方差方式計算得到。注意,如果內部參數已知,沒有必要使用這個函數,使用cvFindExtrinsicCameraParams2則可。
-
CV_CALIB_FIX_ASPECT_RATIO(2):優化過程中認為fx和fy中只有一個獨立變量,保持比例fx/fy不變,fx/fy的值跟內參數矩陣初始化時的值一樣。在這種情況下,(fx, fy)的實際初始值或者從輸入內存矩陣中讀取(當CV_CALIB_USE_INTRINSIC_GUESS被指定時),或者采用估計值(后者情況中fx和fy可能被設置為任意值,只有比值被使用)。
-
CV_CALIB_FIX_PRINCIPAL_POINT(4):主點在全局優化過程中不變,一直在中心位置或者在其他指定的位置(當CV_CALIB_USE_INTRINSIC_GUESS設置的時候)。
-
CV_CALIB_ZERO_TANGENT_DIST(8):切向形變參數(p1, p2)被設置為0,其值在優化過程中保持為0。
-
CV_CALIB_FIX_FOCAL_LENGTH(16):該標志在優化的時候,直接使用 intrinsic_matrix傳遞過來的
-
CV_CALIB_FIX_K1(32):固定徑向畸變k1。徑向畸變參數可以通過組合這些標志設置為任意值。
-
CV_CALIB_FIX_K2(64):固定徑向畸變k2。徑向畸變參數可以通過組合這些標志設置為任意值。
-
CV_CALIB_FIX_K3(128):固定徑向畸變k3。徑向畸變參數可以通過組合這些標志設置為任意值,通常設置為0。
(3)單目定標函數cvCalibrateCamera2采用怎樣的 flags 比較合適?(來自[文獻4])
由於一般鏡頭只需要計算k1,k2,p1,p2四個參數,所以我們首先要設置 CV_CALIB_FIX_K3;其次,如果所用的攝像頭不是高端的、切向畸變系數非常少的,則不要設置 CV_CALIB_ZERO_TANGENT_DIST,否則單目校正誤差會很大;如果事先知道攝像頭內參的大概數值,並且cvCalibrateCamera2函數的第五個參數intrinsic_matrix非空,則也可設置 CV_CALIB_USE_INTRINSIC_GUESS ,以輸入的intrinsic_matrix為初始估計值來加快內參的計算;其它的 flag 一般都不需要設置,對單目定標的影響不大。
7.2.2 cvFindExtrinsicCameraParams2詳解
(1)函數原型
void cvFindExtrinsicCameraParams2( const CvMat* object_points,
const CvMat* image_points,
const CvMat* intrinsic_matrix,
const CvMat* distortion_coeffs,
CvMat* rotation_vector,//[output]
CvMat* translation_vector//[output]
);
(2)參數注釋(6個)
-
object_points:
定標點的坐標,為3xN或者Nx3的矩陣,這里N是視圖中的個數。
-
image_points:
定標點在圖像內的坐標,為2xN或者Nx2的矩陣,這里N是視圖中的個數。
-
intrinsic_matrix:
內參矩陣(A) 。
-
distortion_coeffs:
大小為4x1或者1x4的向量,里面為形變參數[k1,k2,p1,p2]。如果是NULL,所有的形變系數都為0。
-
rotation_vector:
輸出大小為3x1或者1x3的矩陣,里面為旋轉向量(旋轉矩陣的緊湊表示方式,具體參考函數cvRodrigues2)。
-
translation_vector:
大小為3x1或1x3的矩陣,里面為平移向量。
7.3 單目標定示例代碼
http://blog.sina.com.cn/s/blog_73ef08a80100vi49.html
八、單目標定效果不好的原因分析
(1)問題(來自[文獻3]):OpenCV中用cvCalibrateCamera2 進行相機標定的精度差,標定結果不穩定。
分析:可能原因有:
A.夾角太小會導致誤差較大
可能是在標定的時候標定板所在平面與成像平面(image plane)之間的夾角太小,張正友論文里的仿真數據(有噪聲的數據)說明當兩者夾角太小誤差會很大,從張正友的論文里給出的5幅圖中(http://research.microsoft.com/~zhang/Calib/),其中標定平面與成像平面的夾角分別為:8.8947、11.2325、24.4875、10.8535、9.5829(單位:度)。而且張正友的論文中也提到兩幅標定板之間的位置平行放置的話,相關相當於一幅,因此在實際標定中平行放置的情況最好避免,可能有時你無形之中就犯了這個錯誤。
B.標定時拍攝的圖片太少
雖然張正友的論文里只用了5幅圖片,但是建議用10來幅左右還是必要的,因為我們實際中可能標定板用A4的紙打印出來貼在一塊板上的,標定板上的世界坐標精度就不是特別高,多拍攝幾幅圖像能減少這方面帶來的誤差,而且多個角度拍攝也可能解決了問題一:標定板和成像平面夾角小的問題。
有個例子是用20幅圖片進行標定的:
http://www.vision.caltech.edu/bouguetj/calib_doc/htmls/example.html
C.圖像上角點提取的不准確
用cvFindChessboardCorners函數找角點不是很好,假如拍到的圖像不是完整的棋盤格的時候肯定會有問題的,而且也不少人反應用這個函數提取不出角點,建議可以用其他工具 比如:
OpenCV and MatLab Camera Calibration Toolboxes Enhancement:
http://graphics.cs.msu.ru/en/research/calibration/
Camera Calibration Toolbox for Matlab(強烈推薦):
http://www.vision.caltech.edu/bouguetj/calib_doc/htmls/example.html
(2)建議用其他標定方法(比如Tsai)或其他標定工具進行對比
強烈推薦 用這個matlab標定工具箱來進行標定,可以和OpenCV做對比,它也是基於張正友的平面標定方法的,做得非常人性化,有誤差分析、標定結果三維重建、重投影計算角點等功能 。
Camera Calibration Toolbox for Matlab:
http://www.vision.caltech.edu/bouguetj/calib_doc/
(3)使用OpenCV進行攝像機定標雖然方便,但是定標結果往往不夠准確和穩定,最好是使用 Matlab標定工具箱 來進行定標,再將定標結果取回來用於立體匹配和視差計算。
參考文獻
-
[書籍]學習OpenCV:第十一章 攝像機模型與標定。
-
[書籍]基於OpenCV的計算機視覺技術實現
http://blog.csdn.net/zhazhiqiang/article/details/50593677
http://blog.csdn.net/zhazhiqiang/article/details/50593730
-
[書籍]學習OpenCV:第十一章5。
-
[書籍]學習OpenCV:第十一章。
-
[書籍]學習OpenCV:第十一章2