單目標定:從理論到OpenCV實踐
(轉載請註明出處:http://blog.csdn.net/zhazhiqiang/ 未經允許請勿用於商業用途)
一、針 孔攝像機模型
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
相關文章
- 雙目標定與三維計算:從理論到OpenCV實踐OpenCV
- DevOps 從理論到實踐指南dev
- 從理論到實踐 全面理解HTTP/2HTTP
- Kubernetes 叢集升級指南:從理論到實踐
- 從Monolith到微服務:理論與實踐 - Kent BeckMono微服務
- 從理論到實踐,Mysql查詢優化剖析MySql優化
- 《python 程式設計從入門到實踐》序:學習目標Python程式設計
- Kubernetes 資料儲存:從理論到實踐的全面指南
- 從 MySQL 到 WuTongDB 的遷移指導:理論與實踐框架MySql框架
- TRIZ理論助力企業專利戰略升級:從理論到實踐的全面解析
- RocketMQ實戰系列從理論到實戰MQ
- 貝葉斯分類器詳解 從零開始 從理論到實踐
- 深度解析BERT:從理論到Pytorch實戰PyTorch
- Docker最全教程——從理論到實戰(二)Docker
- Docker最全教程——從理論到實戰(三)Docker
- Docker最全教程——從理論到實戰(七)Docker
- Docker最全教程——從理論到實戰(六)Docker
- Docker最全教程——從理論到實戰(五)Docker
- Docker最全教程——從理論到實戰(四)Docker
- Docker最全教程——從理論到實戰(一)Docker
- Docker最全教程——從理論到實戰(八)Docker
- 從理論到實踐,設計一款遊戲數值架構遊戲架構
- OpenCV----實現目標識別與分割OpenCV
- python opencv如何實現目標區域裁剪功能PythonOpenCV
- 90%的人都搞不懂的資料治理,從理論到實踐,都在這裡了
- web3從入門到實戰-理論篇Web
- 從理論走向實踐,多角度詳解Cloud NativeCloud
- 目標和——遞迴的實踐遞迴
- 張正友標定Opencv實現、標定流程以及影像座標轉為世界座標OpenCV
- 理解RESTful:理論與最佳實踐REST
- Flutter 自定義 Widget(理論+實踐)Flutter
- js正則理論與實踐JS
- opencv的目標跟蹤演算法OpenCV演算法
- 實踐心得:從讀論文到復現到為開源貢獻程式碼
- 從單幅影像到雙目立體視覺的3D目標檢測演算法視覺3D演算法
- 混合高斯模型實現運動目標檢測(OpenCV內建實現)模型OpenCV
- GraphQL 從入門到實踐
- 全面掌握膠囊網路:從基礎理論到PyTorch實戰PyTorch