攝像機標定--矯正畸變

來源:互聯網
上載者:User

標籤:style   blog   http   使用   io   strong   資料   2014   

之前做過攝像機標定的研究,不過現在忘了好多,昨天下午又撿起來,好好複習一下(主要是學習opencv一書內容)。

攝像機標定基本知識:

攝像機標定誤差包括內參(4個)、畸變參數(徑向和切向共5個)、外參(平移和旋轉共6個)。

誤差參數分析:攝像機模型採用針孔模型成像模型,由於中心軸安裝問題,這就造成了精度誤差,就是所謂的相機內參數誤差,使用一個3X3的矩陣表示(A) [fx 0 cx; 0 fy cy; 0 0 1].,有四個未知參數;另由於針孔成像採光效率不高,使用了透鏡,這就造成的畸變誤差:

徑向畸變:這是由於透鏡先天條件原因(透鏡形狀),成像儀中心(光學中心)的畸變為0,隨著向邊緣移動,畸變越厲害。這裡有3個參數,k1,k2,k3其中k3是選擇性參數。

切向畸變:這是攝像機安裝過程造成的,如當透鏡不完全平行於映像平面的時候產生的。

旋轉和平移主要針對外參數,旋轉3個角度和平移3個方向6個參數。

棋盤就不介紹了。主要是提取角點,便於後面計算,opencv函數都有函數。書上p423有原理介紹,感興趣的朋友可以參考書上內容。

opencv實現過程及主要函數介紹:

1.首先獲得資料來源(視頻或映像),我讀取的一段自己錄的視頻;

2.初始化單幀棋盤資料,如6X4,並對棋盤操作提取角點;

用到的函數說明: 

CVAPI(int) cvFindChessboardCorners( const void* image, CvSize pattern_size,                                    CvPoint2D32f* corners,                                    int* corner_count CV_DEFAULT(NULL),                                    int flags CV_DEFAULT(CV_CALIB_CB_ADAPTIVE_THRESH+CV_CALIB_CB_NORMALIZE_IMAGE) );

這個函數式找到內角點位置:

  • image

  • 輸入的棋盤圖,必須是8位的灰階或者彩色映像。

  • pattern_size

  • 棋盤圖中每行和每列角點的個數。

  • corners

  • 檢測到的角點

  • corner_count

  • 輸出,角點的個數。如果不是NULL,函數將檢測到的角點的個數儲存於此變數。

  • flags

  • 各種操作標誌,可以是0或者下面值的組合:

    • CV_CALIB_CB_ADAPTIVE_THRESH - 使用自適應閾值(通過平均映像亮度計算得到)將映像轉換為黑白圖,而不是一個固定的閾值。

    • CV_CALIB_CB_NORMALIZE_IMAGE - 在利用固定閾值或者自適應的閾值進行二值化之前,先使用cvNormalizeHist來均衡化映像亮度。

    • CV_CALIB_CB_FILTER_QUADS - 使用其他的準則(如輪廓面積,周長,方形形狀)來去除在輪廓檢測階段檢測到的錯誤方塊。

void cvFindCornerSubPix(const CvArr* image,CvPoint2D32f* corners,int count,CvSize win,CvSize zero_zone,CvTermCriteria criteria)
函數 cvFindCornerSubPix 通過迭代來發現具有子象素精度的角點位置:

image

輸入的映像,必須是8位的灰階或者彩色映像。

corners

輸入角點的初始座標,也儲存精確的輸出座標。

count

角點數目

win

搜尋視窗的一半尺寸。如果win=(5,5)那麼使用(5*2+1)×(5*2+1)=11×11大小的搜尋視窗

zero_zone

死區的一半尺寸,死區為不對搜尋區的中央位置做求和運算的地區。它是用來避免自相關矩陣出現的某些可能的奇異性。當值為(-1,-1)表示沒有死區。

criteria

求角點的迭代過程的終止條件。即角點位置的確定,要麼迭代數大於某個設定值,或者是精確懂達到某個設定值。criteria可以是最大迭代數目,或者是設定的精確度,也可以是它們的組合。

3.攝像機標定求參數,我們目前求內參和畸變參數進行映像校正;

用到的函數說明:
void cvCalibrateCamera2( const CvMat* object_points, const CvMat* image_points, const CvMat*point_counts, CvSize image_size, CvMat* intrinsic_matrix, CvMat* distortion_coeffs, CvMat* rotation_vectors=NULL, CvMat* translation_vectors=NULL, int flags=0 );

標定函數,求攝像機內參和外參數:

  • object_points

  • 定標點的全局座標,為3xN或者Nx3的矩陣,這裡N是所有視圖中點的總數。

  • 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 - 內參數矩陣包含fx,fy,cx和cy的初始值。否則,(cx, cy)被初始化到映像中心(這兒用到映像大小),焦距用最小平方差方式計算得到。注意,如果內部參數已知,沒有必要使用這個函數,使用cvFindExtrinsicCameraParams2則可。

    • CV_CALIB_FIX_PRINCIPAL_POINT - 主點在全域最佳化過程中不變,一直在中心位置或者在其他指定的位置(當CV_CALIB_USE_INTRINSIC_GUESS設定的時候)。

    • CV_CALIB_FIX_ASPECT_RATIO - 最佳化過程中認為fx和fy中只有一個獨立變數,保持比例fx/fy不變,fx/fy的值跟內參數矩陣初始化時的值一樣。在這種情況下, (fx, fy)的實際初始值或者從輸入記憶體矩陣中讀取(當CV_CALIB_USE_INTRINSIC_GUESS被指定時),或者採用估計值(後者情況中fx和fy可能被設定為任意值,只有比值被使用)。

    • CV_CALIB_ZERO_TANGENT_DIST – 切向形變參數(p1, p2)被設定為0,其值在最佳化過程中保持為0。

4.矯正,利用上步求得的參數對映像進行矯正。

用到的函數說明,有兩種方法進行矯正,下面都介紹一下:

a.使用cvInitUndistortMap()和cvRemap()來處理,前者用來計算畸變映射,後者把求得的映射應用到映像。

void cvInitUndistortMap( const CvMat* intrinsic_matrix, const CvMat* distortion_coeffs, CvArr* mapx, CvArr* mapy );
這個Function Compute畸變映射,其中intrinsic_matrix攝像機內參數矩陣(A) [fx 0 cx; 0 fy cy; 0 0 1].distortion_coeffs形變係數向量[k1, k2, p1, p2,k3],大小為5x1或者1x5。mapx為x座標的對應矩陣。mapy為y座標的對應矩陣。
void cvRemap( const CvArr* src, CvArr* dst,const CvArr* mapx, const CvArr* mapy,int flags=CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,CvScalar fillval=cvScalarAll(0) );

對映像進行普通幾何變換,求得矯正映像:

     src
     輸入映像.
dst
輸出映像.
  mapx
x座標的映射 (32fC1 image).
mapy
y座標的映射 (32fC1 image).
flags
插值方法和以下開關選項的組合:
  CV_WARP_FILL_OUTLIERS - 填充邊界外的像素. 如果輸出映像的部分象素落在變換後的邊界外,那麼它們的值設定為 fillval。

函數cvInitUndistortMap預先計算非形變對應-正確映像的每個像素在形變映像裡的座標。這個對應可以傳遞給cvRemap函數(跟輸入和輸出映像一起)。

b.使用cvUndistort2()這個函數一次完成所有事項,不推薦。

CVAPI(void) cvUndistort2( const CvArr* src, CvArr* dst,  const CvMat* camera_matrix,  const CvMat* distortion_coeffs,  const CvMat* new_camera_matrix CV_DEFAULT(0) );

函數說明:

    其中,src為輸入映像,dst為輸出映像.,camera_matrix攝像機內參數矩陣(A) [fx 0 cx; 0 fy cy; 0 0 1],distortion_coeffs形變係數向量[k1, k2, p1, p2,k3],大小為5x1或者1x5。

建議還是使用第一種演算法,因為計算畸變映射是一個耗時的操作,當畸變映射不變的時候,使用第一種效率更高。

本人實驗效果如下:

        
                                               

代碼這裡就不留了,opencv也有類似的源碼,有需要的朋友留下連絡方式可以發給你們,共勉!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.