單目標定:從理論到OpenCV實踐

查志強發表於2018-08-26

(轉載請註明出處:http://blog.csdn.net/zhazhiqiang/ 未經允許請勿用於商業用途)

一、針 孔攝像機模型    2

1.1 優缺點    2

1.2 針 孔攝像機模型圖與公式    2

1.2.1 理想情況    2

1.2.2 實際情況    2

1.3 基本投影幾何    3

1.3.1 投影變換的定義    3

1.3.2 攝像機內引數矩陣    3

二、透鏡攝像機    5

2.1 優缺點    5

2.2 透鏡畸變    5

2.2.1 畸變產生原因    5

2.2.2 徑向畸變    5

2.2.3 切向畸變    6

2.2.4 其他畸變    7

三、旋轉矩陣和平移向量    8

四、攝像機內外引數總結    8

五、攝像機標定    9

5.1 標定目的    9

5.2 單應性矩陣    9

5.3 棋盤    10

5.3.1 棋盤大小    10

5.3.2 角點數量與棋盤圖片數量要求    11

5.4 OpenCV的求解理論方法    11

六、矯正    11

七、OpenCV1.1主要相關函式    12

參考文獻    13

 

 

 

一、針 孔攝像機模型

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標定工具箱 來進行定標,再將定標結果取回來用於立體匹配和視差計算。

 

參考文獻

  1. [書籍]學習OpenCV:第十一章 攝像機模型與標定。

  2. [書籍]基於OpenCV的計算機視覺技術實現

  3. [博文]在OpenCV中用cvCalibrateCamera2進行相機標定

http://blog.csdn.net/zhazhiqiang/article/details/50593677

  1. [博文]雙目測距與三維重建的OpenCV實現問題集錦(一)影象獲取與單目定標

http://blog.csdn.net/zhazhiqiang/article/details/50593730

  1. [書籍]學習OpenCV:第十一章5。

  2. [書籍]學習OpenCV:第十一章。

  3. [書籍]學習OpenCV:第十一章2

相關文章