SteroVision -chapter11_第1頁
SteroVision -chapter11_第2頁
SteroVision -chapter11_第3頁
SteroVision -chapter11_第4頁
SteroVision -chapter11_第5頁
已閱讀5頁,還剩79頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、1第11章 相機模型與標定2攝像機模型相機模型:小孔成像模型;相機內參數矩陣:M3攝像機模型相機模型:小孔成像模型;相機內參數矩陣:M4攝像機模型相機模型:小孔成像模型;相機內參數矩陣:MZYXQcfcfMwyxqMQqyyxx,1,其中fx和fy分別是成像透鏡的弧矢、子午面上的焦距,在成像過程中,對實際物像起縮放的作用。cx和cy分別是,物點成像過程中,在x方向和y方向上的偏移。在OpenCV中,有專門的函數計算M。5透鏡畸變6徑向畸變如何用OpenCV內參數矩陣內參數矩陣和畸變向量畸變向量畸變系數:徑向畸變、切向畸變;畸變系數向量:k1,k2,k3,p1,p2;63422163422111

2、rkrkrkyyrkrkrkxxcorectedcorected7徑向畸變63422163422111rkrkrkyyrkrkrkxxcorectedcorected8徑向畸變63422163422111rkrkrkyyrkrkrkxxcorectedcorected9切向畸變xpyrpyyxrpypxxcorectedcorected22212221222210切向畸變63422163422111rkrkrkyyrkrkrkxxcorectedcorected11標定旋轉矩陣與平移向量(也稱為相機外參數) cossin0sincos0001xR cos0sin010sin0cosyR 100

3、0cossin0sincoszR12標定 ITRRRRRRRRRTxyz因此,它的轉置陣的特性:它的逆矩陣旋轉矩陣因此,,旋轉矩陣與平移向量(也稱為相機外參數)旋轉矩陣13標定把點旋轉(這里是繞Z軸),等價于坐標軸反向旋轉。通過簡單的三角計算,我們可以看出旋轉如何改變坐標。旋轉矩陣與平移向量(也稱為相機外參數)旋轉矩陣14標定旋轉矩陣與平移向量(也稱為相機外參數)平移向量世界坐標系中,物點坐標Po 到攝像機坐標系中坐標Pc的轉換:TPRPoc結合上面計算Pc的公式,以及攝像機內參數校正,我們構造出OpenCV所能解決的基本方程式。這些方程的解將是我們所尋找這些方程的解將是我們所尋找的攝像機標定

4、參數。本課后面的棋盤,就是通過棋盤的旋轉、平的攝像機標定參數。本課后面的棋盤,就是通過棋盤的旋轉、平移,來得到這樣的若干組方程,通過求解方程,標定出相機內部移,來得到這樣的若干組方程,通過求解方程,標定出相機內部參數矩陣。參數矩陣。15標定旋轉矩陣與平移向量(也稱為相機外參數)平移向量平移三個參數;旋轉三個參數;攝像機內部四個參數。因此,每個視場的解需要10個參數(注意,攝像機內參數在不同視場保持不變)。使用一個平面物體,我們很快可以看到每個視場固定8個參數。因為不同視角下旋轉和平移的6個參數會變化,對每一個視角用來求解攝像機內參數矩陣的兩個額外參數需要約束。因此,求解全部幾何參數至少需要兩個

5、求解全部幾何參數至少需要兩個視角。視角。16棋盤此圖必須是,此圖必須是,8位(單通道)灰度圖像。位(單通道)灰度圖像。17棋盤 findChessboardCornersC+: bool findChessboardCorners(InputArray image, Size patternSize, OutputArray corners, int flags=CALIB_CB_ADAPTIVE_THRESH+CALIB_CB_NORMALIZE_IMAGE)C: int cvFindChessboardCorners(const void* image, CvSize pattern_si

6、ze, CvPoint2D32f* corners, int* corner_count=NULL, int flags =CV_CALIB_CB_ADAPTIVE_THRESH+CV_CALIB_CB_NORMALIZE_IMAGE)18棋盤該函數用于確定輸入圖像是否是棋盤陣列的一個視圖,定位內部方格角點。如果所有角點都找到,該函數返回一個非0值,它們以一定的順序排列(row by row, left to right in every row)。除此之外,如果沒有發(fā)現所有的角點,或記錄,則返回0。例如,一個規(guī)則的棋盤有8*8個方格,7*7個內部角點,這些點就是黑白方塊的交點。探測的坐標是近

7、似的,為了更精確確定它們的位置,該函數調用了cornerSubPix(). 你也可以調用函數cornerSubPix(), 調用時如果返回的精度不夠,可以選用不同的輸入參數。 findChessboardCorners19棋盤 findChessboardCorners參數說明:參數說明:image 棋盤源圖像,必須是8-bit 灰度或彩色圖像.patternSize 一副棋盤圖像上的角點列數、行數,該參數數據類型為: Size(points_per_row,points_per_colum) 。corners 探測到的角點矢量。flags 標志項,可以是0,或者如下的參數組合: CV_CAL

8、IB_CB_ADAPTIVE_THRESH,使用自適應閾值,將圖像轉成黑白圖像,而不是一個固定閾值(比如從圖像的平均亮度值計算而得到); CV_CALIB_CB_NORMALIZE_IMAGE ,在應用固定或自適應閾值之前,對圖像歸一化,根據“均衡化直方圖”,調校gamma值。20棋盤 findChessboardCorners參數說明:參數說明: CV_CALIB_CB_FILTER_QUADS 使用附加判據(比如 contour area, perimeter, square-like shape) to 濾除“偽方格”,這些“偽方格”是在輪廓提取階段產生的。 CALIB_CB_FAST_

9、CHECK在圖像上運行一個快速檢查,查找角點;如果一個也沒發(fā)現,就直接停止調用本函數。當沒有觀察到棋盤的時候,這個標志項,可以極大的加速衰退調校下的函數調用。21棋盤參數:參數:image 目標圖像. 必須是 8-bit color image.patternSize 每一個棋盤上的角點個數Size(row,column) (patternSize =cv:Size(points_per_row,points_per_column).corners 探測到的角點數組, findChessboardCorners 的輸出結果。patternWasFound 該參數用于說明,整個棋盤上是否有角點。

10、 findChessboardCorners的返回值,應該是在此傳遞。如果沒有發(fā)現棋盤上的方格角點的話,該函數在棋盤角點上單獨繪制紅色的圓,或者,如果沒有發(fā)現棋盤的話,該函數將繪制角點連線。drawChessboardCorners22cornerSubPix精確定位角點的位置:C+: void cornerSubPix(InputArray image, InputOutputArray corners, Size winSize, Size zeroZone,TermCriteria criteria)C: void cvFindCornerSubPix(const CvArr* imag

11、e, CvPoint2D32f* corners, int count, CvSize win, CvSizezero_zone, CvTermCriteria criteria)棋盤23Parametersimage 輸入圖像.corners 輸入角點的初始坐標,和提供給output的精細坐標;winSize 搜索窗口邊長的一半,例如,如果winSize=Size(5,5) , 那么搜索的窗口范圍: (5 * 2 + 1 ) (5 * 2 + 1 )= 11 11zeroZone 在搜索區(qū)域中間的“死域(dead region)”尺度的一半,在該域范圍內,下面的求和公式無效。有時候,它也被用

12、于避開自相關矩陣的奇異點。當將該參數設定為(-1,-1)時,表示沒有這樣的“死域”。criteria 迭代終止判據,在角點坐標定位過程中,需要多次迭代計算,那么迭代停止的依據,就是該參數。它用于指定角點計算的最大迭代次數maxCount,或者角點坐標位移,在一定的迭代次數內,小于epsilon。cornerSubPix棋盤24cornerSubPix該函數可以實現角點子像素精確位置的查找,或者徑向馬鞍點的子像素精確位置,如下圖所示:子像素精確的角點定位器,的理論基礎是:從中心點q發(fā)出的,到q鄰域內的p點的每一個矢量,垂直于圖像梯度, 。棋盤25iTipiDIqp考慮下面的表達式:cornerS

13、ubPix其中的ipDI是在q 的鄰域中,一系列點pi中的第 i 個圖像梯度在計算過程中,就是找到q 的確切值,以使i 最小。設定i為0,建立方程組:iiiiTTppppiiiDIDIDIDIp在q 的鄰域內,即在搜索窗口(“search window”)內,求取梯度和。調用第一個梯度項G和第二個梯度b,我們得到:1qGb該算法,將鄰域窗口中心每次設置在新的中心q,然后迭代計算,直到中心停滯在某一個預設的閾值范圍內。棋盤26TermCriteriaclass TermCriteria該類定義了迭代算法中的終止判據。你可以用默認的構造器,對其初始化,可以不用管其它任何參數;或者,使用構造器的高級

14、變量,對新結構實現完全初始化。棋盤27TermCriteriaTermCriteria:TermCriteriaC+: TermCriteria:TermCriteria()C+: TermCriteria:TermCriteria(int type, int maxCount, double epsilon)C+: TermCriteria:TermCriteria(const CvTermCriteria& criteria)參數說明:參數說明:type 終止判據的類型 : TermCriteria:COUNT, TermCriteria:EPS orTermCriteria:CO

15、UNT + TermCriteria:EPS.maxCount 迭代的最大數,或者計算的元素的最大數。epsilon 期望的參數精度或變化量,在精度內,迭代停止。criteria 以不建議的CvTermCriteria 格式,提供終止判據。棋盤28TermCriteriaTermCriteria:operator CvTermCriteria將終止判據轉換為不建議的CvTermCriteria 格式C+: TermCriteria:operator CvTermCriteria() const棋盤29單應性TTzyxqZYXQ11在計算機視覺中,平面的單應性被定義為從一個平面到另一個平面的投影

16、映射。因此一個二維平面上的點映射到攝像機成像儀上的映射就是平面單應性的例子。可以將單應性簡單表示為:QsHq用單應性來描述平面物體的觀測:從物體平面到圖像平面的映射,同時表征了這兩個平面的相對位置和攝像機投影矩陣。30單應性tRW QW稍微利用一點幾何和矩陣代數的知識,便可以求解這個變換矩陣。最重要的是H有兩部分:用于定位觀察的物體平面的物理變換物理變換;使用攝像機內參數矩陣攝像機內參數矩陣的投影。物理變換部分:是物平面相關的部分旋轉部分旋轉R和部分平移和部分平移t的綜合影響。然后,通過乘以得到攝像機矩陣M,即:10000,yyxxcfcfMQsMWq其中31單應性110121321YXtrr

17、sMYXtrrrsMyx到此,似乎已經完成了。但實際上,我們的關注點不是表征所有空間的坐標Q,而只是定義我們所尋找的平面的坐標考慮到一般性,我們可以選擇定義這個平面,使得Z=0.這樣做的原因是,如果把旋轉矩陣分解為3個31向量(即R=r1 r2 r3,那么其中的一個列向量就不需要了。具體如下:映射目標點到成像儀的單應性矩陣H可以完全用H=sMr1 r2 t表述,其中:QsHqQ注意,此時H是33矩陣。32單應性OpenCV使用上述公式,來計算單應性矩陣。它使用同一物體的多個圖像來計算每個視場的旋轉和平移,同時也計算攝像機內參數(對所有視場不變)。如我們討論的,旋轉和平移分別用三個角度、三個偏移

18、量定義,因此每個視場有6個未知量。一個已知平面物體(如棋盤)能夠提供8個方程,即映射一個正方形到四邊形可以用4個(x,y)點來描述。每個新的圖像幀為計算新的6個未知量提供8個方程,因此若給定足夠圖像,我們能夠計算出未知參數的任何值。通過下面簡單方程,單應性矩陣H把源圖像平面上的點集位置與目標圖像平面上的點集位置聯系起來:1,1,1srcsrcsrcdstdstdstdstsrcsrcdstyxpyxppHpHpp33單應性findHomographyC+: Mat findHomography(InputArray srcPoints, InputArray dstPoints, int me

19、thod=0, double ransacReprojThreshold=3, OutputArray mask=noArray() )C: int cvFindHomography(const CvMat* src_points, const CvMat* dst_points, CvMat* homography, intmethod=0, double ransacReprojThreshold=3, CvMat* mask=0 )34單應性參數說明:參數說明:srcPoints 原平面上點的坐標,數據類型為CV_32FC2 的矩陣,或二維點矢量 .dstPoints 目標平面上點的坐標

20、,數據類型為CV_32FC2 的矩陣,或二維點矢量 .method 計算H矩陣的方法,下面是幾個可選的方法: 0 使用所有點的常規(guī)方法; CV_RANSAC - RANSAC- 基于智能方法 CV_LMEDS - Least-Median robust methodransacReprojThreshold 最大允許的投影誤差, 該誤差用于限定“目標點與轉換 點的歐幾里得距離”。也就是,如果kdstPointsi - convertPointsHomogeneous(H*srcPointsi)k ransacReprojThreshold那么點意味著點i超出了范圍。如果srcPoints an

21、d dstPoints 以像素計量,那么設置該參數是有意義的,通常設置在110之間。mask 通過robust method ( CV_RANSAC or CV_LMEDS ),可選擇mask指定區(qū)域輸出。 注意,輸入的mask值是被忽略的。findHomography35單應性findHomography該函數用于計在算源圖像平面,到目標圖像面之間的單應性矩陣H:11iiiiiyxHyxs源圖像上的點,經過H變換后,與目標圖像的對應點之間位置誤差要最小:23332312322212333231131211hyhxhhyhxhyhyhxhhyhxhxiiiiiiiiiii36單應性findHo

22、mography如果參數method設為0,那么該函數將會用所有的點對兒,計算初始H的預估值,方法就是用最簡單的最小方差。然而,如果不是所有的點對兒(srcPointsi,:math:dstPoints_i)都符合嚴格的透視投影變換(也就是有些例外點),這個初始估計是比較糟的。在這時,你可以在兩個智能方法中間選擇一個。兩種智能方法,RANSAC和LMeDS,原理就是試驗對應點對兒組成的隨機子集合(每次試驗4對兒子集合),估計H矩陣,估算方法就是簡單的最小二乘方算法;然后,對所得的H計算它的“質量/優(yōu)良”(也就是,根據參數ransacReprojThreshold 限定的閾值,判斷優(yōu)劣)。最好的

23、點對兒子集,用于計算H的初始值,以及mask區(qū)域內符合條件的“界內像素界內像素”點,或者計算不符合閾值條件的“界外像素界外像素”點。無論采用智能還是非智能的方法,計算所得到的H矩陣,都需要進一步提煉。也就是使用Levenberg-Marquardt方法,減少再投影誤差。37單應性findHomographyl不滿足條件的界外像素,不管比例多大,RANSAC方法都可以處理;但是它需要一個閾值,用于從界外像素中分辨界內像素。l而LMeDS方法卻不需要任何閾值,不過它只有在“界內像素”比例超過50%的時候,才能正常工作。l最后如果沒有“界外像素”,或者噪聲非常小,使用默認的方法,即method=0。

24、該函數被用于發(fā)現相機的初始內部參數和外部參數。H矩陣最終是由一個比例尺度(a scale)決定,這樣就要對它做歸一化處理,以便于h33=1。38攝像機標定 棋盤角點個數和參數個數 內部探秘 標定函數 矯正39攝像機標定棋盤角點個數和參數個數未知參數:4個內參數:fx, fy, cx, cy;5個畸變參數: k1,k2,k3(三個徑向) p1,p2(兩個切向)空間3D幾何相關(即外參數)只需一個棋盤視場只與如何畸變的2D相關6個不同視場圖像;3個旋轉參數();3個平移參數(Tx,Ty,Tz);總而言之,在每個視場中,我們必須計算總而言之,在每個視場中,我們必須計算4個內參數和個內參數和6個外參數

25、。個外參數。為了得到高質量的結果,通常需要為了得到高質量的結果,通常需要10幅幅7*8或者更大棋或者更大棋盤圖像。不同棋盤之間移動量要足夠大。盤圖像。不同棋盤之間移動量要足夠大。40攝像機標定內幕探秘這一部分內容,大家自行學習。41攝像機標定標定函數一旦有多個圖像的角點,就可以調用函數calibrateCamera此函數將要做大量分解工作以提供我們需要的信息。具體來說,我們會得到:攝像機內參數;攝像機內參數;畸變系數:畸變系數: k1,k2,k3和 p1,p2旋轉向量;旋轉向量;平移向量。平移向量。棋盤位置、方向(攝像機外參數)42攝像機標定calibrateCameraC+: double

26、calibrateCamera(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints,Size imageSize, InputOutputArray cameraMatrix, InputOutputArraydistCoeffs, OutputArrayOfArrays rvecs, OutputArrayOfArraystvecs, int flags=0, TermCriteria criteria=TermCriteria( TermCriteria:COUNT+TermCriteria:EPS, 30, DB

27、L_EPSILON) )C: double cvCalibrateCamera2(const CvMat* object_points, const CvMat* image_points,const CvMat* point_counts, CvSize image_size, CvMat*camera_matrix, CvMat* distortion_coeffs, CvMat* rotation_vectors=NULL, CvMat* translation_vectors=NULL,int flags=0, CvTermCriteria term_crit=cvTermCriter

28、ia(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,DBL_EPSILON)43攝像機標定calibrateCamera參數說明objectPoints 在新的界面中,它是標定板上角點組合的矢量(vectors)的矢量(vector),也就是一個二維矢量。外層矢量vector的維數,等于標定板圖像的個數。如果在每個視圖 中都是同一個標定板,并且完全可見,那么內層矢量的維數就是角點的個數。不過在不同視圖中,也可以用不同的方格個數,或者將標定板中的一部分方格擋住。那么矢量vectors的維數也會不同。角點是3D的,但是由于它們位于一個網格坐標系統(tǒng)中,如果標定板是平面的,那

29、么可以令每個角點的Z坐標為0,這樣就將模型轉換為XY坐標平面。imagePoints 在新的界面中,它是標定板上角點的投影(即在CCD上的想點)組合的矢量(vectors)的矢量(vector), objectPoints 和imagePoints 是 一 一對應的。imagePoints.size() = objectPoints.size()imagePointsi.size() = objectPointsi.size()44攝像機標定calibrateCamera參數說明point_counts 在舊的界面中,它是一個整數組成的矢量,它的維數,也就是它的元素個數標定板視圖的個數一致。每

30、一個元素值,就是對應視圖的角點個數。多數情況下,所有視圖上的角點個數是一樣的。imageSize 圖像的尺度僅僅用于初始化相機的內部參數矩陣。cameraMatrix 輸出 3x3 floating-point camera matrix10000yyxxcfcfM如果CV_CALIB_USE_INTRINSIC_GUESS 和(或) CV_CALIB_FIX_ ASPECT _RATIO以經指定,那么在調用本函數前, fx, fy, cx, cy的一部分或全部被初始化45distCoeffs 輸出的畸變系數組成的矢量(k1; k2; p1; p2; k3; k4; k5; k6) ,該矢量可

31、以是4元、5元或8元。rvecs 輸出矢量,即每個視圖的旋轉角度矢量(vectors)共同組成一個大的矢量(vector)。在vector中每個vectors,比如第k個vectors與tvecs中的第k個旋轉矢量vectors對應,并共同對應于標定板的某一個空間位置,世界坐標系中的某個位置。也就是,標定板的第k個視圖真是位置。tvecs 輸出矢量,即每個標定板視圖的預估平移矢量。flags 標志。標志可以為0,或由下面的不同值的組合表示: CV_CALIB_USE_INTRINSIC_GUESS 相機矩陣含有cameraMatrixfx, fy, cx, cy的有初始效值,后面還要對它們進一

32、步優(yōu)化。相機矩陣中的(cx,cy)一開始設定在圖像的中心位置(根據imageSize來確定),以最小二次方的形式計算焦距。注意,如果內部參數是已知的,不必僅僅估算外部參數而調用該函數。直接調用 solvePnP() 函數就可以了。攝像機標定calibrateCamera參數說明46攝像機標定calibrateCamera參數說明 CV_CALIB_FIX_PRINCIPAL_POINT 在全局優(yōu)化過程中,主點不變。主點位于中心,或者在 CV_CALIB_USE_INTRINSIC_GUESS被設定時,位于指定的其它位置。 CV_CALIB_FIX_ASPECT_RATIO 只有在fy是自由參數

33、時,本函數才會考慮該這個參數。當輸入相機矩陣后,fx/fy的比率保持不變。當參數CV_CALIB_USE_INTRINSIC_GUESS沒有被設定時,fx和fy的輸入值被忽略,只有它們的比率值在下一步中被使用。 CV_CALIB_ZERO_TANGENT_DIST 切向畸變系數(p1,p2)被設置為0,并且一直保持0不變。 CV_CALIB_FIX_K1,.,CV_CALIB_FIX_K6 在優(yōu)化過程中,對應的徑向畸變系數不變。如果CV_CALIB_USE_INTRINSIC_GUESS已經被設定,這些系數由cameraMatrix提供。其它設為0。 CV_CALIB_RATIONAL_MOD

34、EL 使徑向畸變系數k4、k5、k6有效。為了提供后向兼容性,這個額外的參數應該顯示地指定,使標定函數利用旋轉模型,并返回8個參數。如果該參數沒有設定,標定函數僅僅計算和返回5個畸變系數。47攝像機標定calibrateCamera參數說明criteria 終止判據,用于迭代優(yōu)化算法的終止條件。term_crit 與 criteria同樣。.48攝像機標定只計算外參數C+: bool solvePnP(InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArraydistCoeffs, O

35、utputArray rvec, OutputArray tvec, bool useExtrinsicGuess=false, int flags=ITERATIVE )C: void cvFindExtrinsicCameraParams2(const CvMat* object_points, const CvMat* image_points,const CvMat* camera_matrix, const CvMat* distortion_coeffs,CvMat* rotation_vector, CvMat* translation_vector, intuse_extrin

36、sic_guess=0 )49矯正標定攝像機通常是想做兩件事情:一、矯正畸變效應;二、重構三維場景。在深入第12章之前,我們先考慮第一個任務。OpenCV提供了一個直接使用的校正算法,即輸入原始圖像和畸變系數(由函數calibrateCamera()得到),生成矯正后的圖像。這個工作可以以兩種方式實現:一、一次性通過函數undistort()()實現;二、也可以通過initUndistortRectifyMap()()與remap()()函數,分步驟完成。這個方法通常適合視頻、或者從同一個攝像機中得到多個圖像的應用。注意注意“矯正(矯正(undistortion)”與與“校正(校正(recti

37、fication)”的關系。參的關系。參考書上:考書上:P430底腳注。底腳注。50矯正51矯正基本步驟:1、計算畸變initUndistortRectifyMap(),(),映射remap()() ;2、矯正圖像,也就是利用remap得到的映射矩陣,重新調整圖像像素位置;undistort()()= initUndistortRectifyMap()()+remap()()一次完成以上兩個步驟,但是計算畸變映射是耗時的工作,因此當畸變系一次完成以上兩個步驟,但是計算畸變映射是耗時的工作,因此當畸變系數固定不變時,調用數固定不變時,調用undistort()是笨方法。()是笨方法。最后,如果是

38、一些列的最后,如果是一些列的2D點矯正,那么可以調用函數點矯正,那么可以調用函數undistortPoints()。()。將這些點,從當前有畸變坐標,轉換到無畸變的坐標。將這些點,從當前有畸變坐標,轉換到無畸變的坐標。52矯正initUndistortRectifyMap()()C+: void initUndistortRectifyMap (InputArray cameraMatrix, InputArray distCoeffs, InputArray R,InputArray newCameraMatrix, Size size, int m1type, OutputArray ma

39、p1, OutputArray map2)C: void cvInitUndistortMap(const CvMat* camera_matrix, const CvMat* distortion_coeffs, CvArr* mapx, CvArr* mapy)C: void cvInitUndistortRectifyMap(const CvMat* camera_matrix, const CvMat* dist_coeffs, Const CvMat* R, const CvMat* new_camera_matrix, CvArr* mapx, CvArr* mapy)53矯正in

40、itUndistortRectifyMap()()參數說明:參數說明:cameraMatrix 輸入相機內部參數矩陣10000yyxxcfcfAdistCoeffs 輸入畸變系數矢量 (k1; k2; p1; p2; k3; k4; k5; k6) ,該矢量可以是 4元,5元, or 8元.R 可選項,選擇物空間(3*3矩陣)的校正變換。由立體校正函數stereoRectify()計算得到的R1或R2,可以在此處傳遞給本函數。如果矩陣是空的,那么就做恒等變換。在cvInitUndistortMap 函數中,假定函數中,假定R是單位矩陣。是單位矩陣。newCameraMatrix 輸出新的相機矩

41、陣10000yyxxcfcfA54矯正size 消除畸變后的圖像尺寸;m1type 本函數將通過上述參數,計算輸出兩個映射矩陣,分別是map1、map2(或者c版的mapx、mapy)。此處的參數將指定第一個映射矩陣的數據類型為CV_32FC1 or CV_16SC2 . 細節(jié)參見函數convertMaps() map1 第一個輸出映射;map2 第二個輸出映射.initUndistortRectifyMap()()參數說明:參數說明:55矯正initUndistortRectifyMap()()該函數用于計算消畸變和校正變換計算消畸變和校正變換,計算得到的結果是兩個映射矩陣map1、map2

42、(或者c版的mapx、mapy),這兩個映射是remap()()函數的輸入參數。消畸變的圖像,相當于用一個無畸變的攝像機,拍攝的圖像。如果是單目攝像機, newCameraMatrix直接等于cameraMatrix ;如果想要更好的控制比率,我們可以調用getOptimalNewCamera Matrix()函數;如果是立體攝像機(即雙目攝像機), newCameraMatrix通常被設定為P1或或P2,這兩個參數是由stereoRectify()函數計算得到的。再有,根據旋轉矩陣R,虛擬調整相機鏡頭對準物空間的新方向虛擬調整相機鏡頭對準物空間的新方向。雙目立體攝像時,兩個攝像頭方向可能不會

43、剛好平行,那么可以對它們拍攝的圖像,重新映射,這樣處理后的兩幅圖像,就如同兩個平行攝像機拍攝的兩幅圖像一樣。56矯正initUndistortRectifyMap()()該函數,實際上是構建了兩個映射矩陣兩個映射矩陣,通過調用remap()()函數,實現了你逆映射算法逆映射算法。也就是說,對于目標圖像目標圖像(也就是通過校正所得的那個圖像)上的每一個像素(u,v),該函數都要計算源圖像源圖像(相機拍攝得到的那個圖像)的相應坐標。下面是逆映射的操作過程:yyxxfcuyfcux/這一步是,利用相機內參數矩陣A,將目標圖像目標圖像的每一個像素,反算到實際的物理空間。TyxRWYX11第二步,旋轉矩

44、陣R,對像素做旋轉變換,如果是單目攝像頭,做恒等變換,如果是雙目,調整兩圖像平行對準。57矯正initUndistortRectifyMap()()WYyWXx/第三步,做歸一化處理yxpyrprkrkrkyyxrpyxprkrkrkxx 22216342212221634221221221下面是第四步,對源圖像消畸變處理:yyyxxxcfyvumapcfxvumap ,第五步,用原攝像機內參數矩陣,重新投影該像素,得到目標圖像像素坐標(u,v)。58矯正initUndistortRectifyMap()()如果是雙目立體攝像機,這個函數將被調用兩次:每個攝像頭被調用一次,在stereoRec

45、tify()函數立體校正之后,兩個攝像頭要輪流立體標定stereoCalibrate()。如果立體攝像機還沒有標定,我們依然能夠利用基礎矩陣基礎矩陣F直接校正變換,此時需要調用stereoRectifyUncalibrated()函數,基礎矩陣基礎矩陣F是它的輸入參數。對于每個攝像頭,在像素區(qū)域內,這個函數計算單應性矩陣H,來實現校正變換,而不是在3D空間中做矩陣R旋轉。旋轉矩陣R可以從H計算得到:ixcameraMatrHixcameraMatrR1其中, newCameraMatrix可以任意選擇。59標定實例為了大家學習方便,我在這里為大家設計了一段簡易的程序,來理解前面所描述的函數用法

46、,及其工作原理。在相機標定過程中,首先要有一副黑白方格盤,也就是所謂的棋盤所謂的棋盤。假定攝像機已經拍攝好棋盤的圖像。那么我們要用OpenCV中的函數findChessboardCorners()函數,找到棋盤上的角點,然后用drawChessboardCorners()繪制角點,下面是簡單的一個例程序。60查找角點函數:查找角點函數: findChessboardCorners()()和繪制角點函數:和繪制角點函數: drawChessboardCorners()()標定實例61.pro文件中添加的配置win32:CONFIG(release, debug|release) INCLUDEP

47、ATH += D:/Qt/opencv240/install/include DEPENDPATH += D:/Qt/opencv240/install/include LIBS += -LD:/Qt/opencv240/install/lib/ -llibopencv_core240 LIBS += -LD:/Qt/opencv240/install/lib/ -llibopencv_highgui240 LIBS += -LD:/Qt/opencv240/install/lib/ -llibopencv_imgproc240 LIBS += -LD:/Qt/opencv240/instal

48、l/lib/ -llibopencv_calib3d240 else:win32:CONFIG(debug,debug|release) INCLUDEPATH += D:/Qt/opencv240a/install/include DEPENDPATH += D:/Qt/opencv240a/install/include LIBS += -LD:/Qt/opencv240a/install/lib/ -llibopencv_core240d LIBS += -LD:/Qt/opencv240a/install/lib/ -llibopencv_highgui240d LIBS += -LD

49、:/Qt/opencv240a/install/lib/ -llibopencv_imgproc240d LIBS += -LD:/Qt/opencv240/install/lib/ -llibopencv_calib3d240d 查找角點函數:查找角點函數: findChessboardCorners()()和繪制角點函數:和繪制角點函數: drawChessboardCorners()()62標定實例/下面是要包含的頭文件#include #include #include #include #include using namespace std; using namespace cv;

50、 #include #include #include 查找角點函數:查找角點函數: findChessboardCorners()()和繪制角點函數:和繪制角點函數: drawChessboardCorners()()63標定實例查找角點函數:查找角點函數: findChessboardCorners()()和繪制角點函數:和繪制角點函數: drawChessboardCorners()()int main() /讀取棋盤視圖 Mat image=imread(chessboards/chessboard02.jpg,0); imshow(original image:,image); st

51、d:vectorimageCorners;/輸出角點矢量 Size boardSize(6,4);/棋盤角點的行數、列數 bool found=findChessboardCorners(image,boardSize,imageCorners); cv:drawChessboardCorners(image,boardSize,imageCorners,found); imshow(Corners on Chessboard,image); cv:waitKey(0); return 0; 通過本程序,我們可以了解,在OpenCV中如何查找棋盤角點,后面的繪制角點,只是用來查看是否找到角點,

52、以后的程序中可以省略。64精密定位角點函數:精密定位角點函數:cornerSubPix()()精確定位角點的位置:C+: void cornerSubPix(InputArray image, InputOutputArray corners, Size winSize, Size zeroZone,TermCriteria criteria)C: void cvFindCornerSubPix(const CvArr* image, CvPoint2D32f* corners, int count, CvSize win, CvSizezero_zone, CvTermCriteria cr

53、iteria)標定實例65Parametersimage 輸入圖像.corners 輸入角點的初始坐標,和提供給output的精細坐標;winSize 搜索窗口邊長的一半,例如,如果winSize=Size(5,5) , 那么搜索的窗口范圍: (5 * 2 + 1 ) (5 * 2 + 1 )= 11 11zeroZone 在搜索區(qū)域中間的“死域(dead region)”尺度的一半,在該域范圍內,下面的求和公式無效。有時候,它也被用于避開自相關矩陣的奇異點。當將該參數設定為(-1,-1)時,表示沒有這樣的“死域”。criteria 迭代終止判據,在角點坐標定位過程中,需要多次迭代計算,那么迭

54、代停止的依據,就是該參數。它用于指定角點計算的最大迭代次數maxCount,或者角點坐標位移,在一定的迭代次數內,小于epsilon。cornerSubPix標定實例66cornerSubPix該函數可以實現角點子像素精確位置的查找,或者徑向馬鞍點的子像素精確位置,如下圖所示:子像素精確的角點定位器,的理論基礎是:從中心點q發(fā)出的,到q鄰域內的p點的每一個矢量,垂直于圖像梯度, 。標定實例67iTipiDIqp考慮下面的表達式:cornerSubPix其中的ipDI是在q 的鄰域中,一系列點pi中的第 i 個圖像梯度在計算過程中,就是找到q 的確切值,以使i 最小。設定i為0,建立方程組:ii

55、iiTTppppiiiDIDIDIDIp在q 的鄰域內,即在搜索窗口(“search window”)內,求取梯度和。調用第一個梯度項G和第二個梯度b,我們得到:1qGb該算法,將鄰域窗口中心每次設置在新的中心q,然后迭代計算,直到中心停滯在某一個預設的閾值范圍內。標定實例68TermCriteriaclass TermCriteria該類定義了迭代算法中的終止判據。你可以用默認的構造器,對其初始化,可以不用管其它任何參數;或者,使用構造器的高級變量,對新結構實現完全初始化。標定實例69TermCriteriaTermCriteria:TermCriteriaC+: TermCriteria:

56、TermCriteria()C+: TermCriteria:TermCriteria(int type, int maxCount, double epsilon)C+: TermCriteria:TermCriteria(const CvTermCriteria& criteria)參數說明:參數說明:type 終止判據的類型 : TermCriteria:COUNT, TermCriteria:EPS orTermCriteria:COUNT + TermCriteria:EPS.maxCount 迭代的最大數,或者計算的元素的最大數。epsilon 期望的參數精度或變化量,在精

57、度內,迭代停止。criteria 以不建議的CvTermCriteria 格式,提供終止判據。標定實例70TermCriteriaTermCriteria:operator CvTermCriteria將終止判據轉換為不建議的CvTermCriteria 格式C+: TermCriteria:operator CvTermCriteria() const標定實例71int main() /讀取棋盤視圖 Mat image=imread(chessboards/chessboard02.jpg,0); imshow(original image:,image); std:vectorimageC

58、orners;/輸出角點矢量 Size boardSize(6,4);/棋盤角點的行數、列數 bool found=findChessboardCorners(image, boardSize, imageCorners); coutimageCornersendl; cv:TermCriteria tc(TermCriteria:MAX_ITER+cv:TermCriteria:EPS, 30,/最大迭代次數 0.1);/最小精度 if(found) cv:cornerSubPix(image,imageCorners, /既是輸入變量,也是輸出變量cv:Size(5,5),Size(-1,

59、-1), tc); coutimageCornersendl; return 0; 精密定位角點函數:精密定位角點函數:cornerSubPix()實例程序()實例程序72標定實例定義方法為:定義全局變量vector vector imagePoints;將imageCorners保存到objectPoints的方法為: imagePoints.push_back(imageCorners);接下來,進一步,我們可以將定位角點坐標的過程,封裝在一個函數中,這個函數命名為:addChessboardPoints()()而imageCorners保存到objectPoints,可以封裝在另一個函數

60、中:addPoints(imageCorners)到現在,我們已經可以讀取棋盤圖像,定位角點坐標,讀取棋盤圖像,定位角點坐標,每一幅視圖上的角點坐標,都組成一個矢量vector,N幅視圖就有N個vector,所以我們可以另外定義一個二維點矢量imagePoints,并將conerSubPix函數找到的點矢量imageCorners,作為一個矢量元素保存在imagePoints里。73標定實例addChessboardPoints()()int main() /讀取棋盤視圖 Mat image=imread(chessboards/chessboard02.jpg,0); imshow(original image:,ima

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論