久久99国产亚洲高清观看首页 ,亚洲国产激情一区二区三区,欧洲精品免费一区二区三区,国产10000部拍拍拍免费视频

世界熱點!OpenCV之攝像機標定

來源:QT教程     時間:2023-04-21 00:05:52

最近方向定下來是雙目立體視覺,主要是做重建這塊的研究。大致過程是圖像獲取->攝像機標定->特征提取->匹配->三維重建,當然開始可以進行圖像預處理,矯正,后期可以進行點云的進一步處理,如渲染表面使其更接近于現(xiàn)實物體。

圖像獲取相對來說比較簡單,用相機拍攝目標物(大型場景或特定小型的室內(nèi)物體)。但有兩點需要注意:

1、雙目重建所需的圖像一般為兩張,角度相差不應過大,否則公共部分太少以至于重建效果不佳;整個過程簡便,成本也不高,但缺陷是只有兩張圖像的點云所表示的物體信息不會很全面;


(相關(guān)資料圖)

2、標定所需的圖像又是另外拍攝的,用張正友標定法的話,把印有黑白棋盤格的圖像粘至硬紙板上,然后左右攝像機各自進行拍攝,理論上獲得角度(圖像)越多,最終標定結(jié)果越精確;標定板見下圖:

這里主要結(jié)合OpenCV對左右攝像機標定做一個簡單的介紹,望朋友們指正,一起交流、進步。

攝像機的標定問題是機器視覺領域的入門問題,可以分為傳統(tǒng)的攝像機定標方法和攝像機自定標方法。定標的方法有很多中常見的有:Tsai(傳統(tǒng))和張正友(介于傳統(tǒng)和自定標)等,

攝像機成像模型和四個坐標系(通用原理)。

攝像機模型采用經(jīng)典的小孔模型,如圖中Oc(光心),像面π表示的是視野平面,其到光心的距離為f(鏡頭焦距)。

四個坐標系分別為:世界坐標系(Ow),攝像機坐標系(Oc),圖像物理坐標系(O1,單位mm),圖像像素坐標系(O,位于視野平面的左上角,單位pix)。

空間某點P到其像點p的坐標轉(zhuǎn)換過程主要是通過這四套坐標系的三次轉(zhuǎn)換實現(xiàn)的,首先將世界坐標系進行平移和轉(zhuǎn)換得到攝像機坐標系,然后根據(jù)三角幾何變換得到圖像物理坐標系,最后根據(jù)像素和公制單位的比率得到圖像像素坐標系。(實際的應用過程是這個的逆過程,即由像素長度獲知實際的長度)。

ps:通過攝像頭的標定,可以得到視野平面上的mm/pix分辨率,對于視野平面以外的物體還是需要通過坐標轉(zhuǎn)換得到視野平面上。

轉(zhuǎn)化的過程和公式參見:攝像機標定原理(關(guān)鍵是三個坐標系).ppt

2 張正友算法的原理

zhang法通過對一定標板在不同方向多次(三次以上)完整拍照,不需要知道定標板的運動方式。直接獲得相機的內(nèi)參(參考文獻上矩陣A)和畸變系數(shù)。該標定方法精度高于自定標法,且不需要高精度的定位儀器。

ZHANG的算法包含兩個模型:一.經(jīng)典針孔模型,包含四個坐標系,二畸變模型(這個來源未知)

公式三項依次表示,徑向畸變,切線畸變,薄棱鏡畸變。OPENCV中函數(shù)只能給出k1,k2,p1,p2。

還存在另外一種畸變模型,見《攝像機標定算法庫的設計和試驗驗證》一文26 page。

張正友標定有matlab的工具箱TOOLBOX_CAL,以及OpenCV庫,下面是C++結(jié)合OpenCV的代碼:

1 #include "cvut.h"  2 #include 3 #include 4 #include 5 using namespace cvut;  6 using namespace std;  7 void main()   8 {  9      ifstream fin("calibdata.txt"); 10      ofstream fout("calibration_result.txt");  11      //****************開始提取角點***********************// 12      cout<<"開始提取角點………………"; 13      int image_count=0;  14      CvSize image_size;  15      CvSize board_size = cvSize(5,7);    16      CvPoint2D32f * image_points_buf = 17                 new CvPoint2D32f[board_size.width*board_size.height];   18      Seqimage_points_seq;  19      string filename; 20      while (std::getline(fin,filename)) 21      { 22           cout<<"
 將鼠標焦點移到標定圖像所在窗口" 23           <<"并輸入回車進行下一幅圖像的角點提取 
"; 24           image_count++; 25           int count; 26           Imageview(filename);  27           if (image_count == 1) 28           { 29                image_size.width = view.size().width; 30                image_size.height = view.size().height; 31           } 32           if (0 == cvFindChessboardCorners( view.cvimage, board_size, 33                 image_points_buf, &count, CV_CALIB_CB_ADAPTIVE_THRESH )) 34           { 35                 cout<<"can not find chessboard corners!
"; 36                 exit(1); 37           } 38           else 39          { 40            Imageview_gray(view.size(),8,1); 41            rgb2gray(view,view_gray); 42            cvFindCornerSubPix( view_gray.cvimage,  43            image_points_buf, count, cvSize(11,11), 44            cvSize(-1,-1),  45            cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 )); 46            image_points_seq.push_back(image_points_buf,count); 47            cvDrawChessboardCorners( view.cvimage, board_size,  48                     image_points_buf, count, 1); 49            view.show("calib"); 50            cvWaitKey();  51            view.close(); 52          } 53      }//角點提取循環(huán) 54      delete []image_points_buf;  55      cout<<"角點提取完成!
"<object_points(1, 59                 board_size.width*board_size.height*image_count,3); 60      Matriximage_points(1,image_points_seq.cvseq->total,2); 61      Matrixpoint_counts(1,image_count,1); 62      Matrixintrinsic_matrix(3,3,1); 63      Matrixdistortion_coeffs(1,4,1); 64      Matrixrotation_vectors(1,image_count,3); 65      Matrixtranslation_vectors(1,image_count,3); 66      int i,j,t; 67      for (t=0;ttotal,str,10); 81      cout<total;i++) 83      { 84             image_points(0,i,0) = image_points_seq[i].x; 85             image_points(0,i,1) = image_points_seq[i].y; 86      } 87      for (i=0;iimage_points2(1,point_counts(0,0,0),2);135      int temp_num  = point_counts(0,0,0); 136      cout<<"	每幅圖像的定標誤差:
";137      fout<<"每幅圖像的定標誤差:
";138      for (i=0;irotation_vector(3,1);176      Matrixrotation_matrix(3,3);177      fout<<"相機內(nèi)參數(shù)矩陣:
";178      fout<

這段程序可以直接運行,本人是在vs2010+OpenCV2.4.0環(huán)境下,配置在前面文章中有介紹。標定板圖像序列名稱放在文件"calibdata.txt"中,每行一幅圖像名,路勁問題這里就不論述了。如

image/chess1.jpg image/chess2.jpg

……

最后標定結(jié)果存儲在"calibration_result.txt"中,命令行窗口也會顯示一些信息。觀察結(jié)果會發(fā)現(xiàn),攝像機內(nèi)參數(shù)矩陣M1和畸變系數(shù)k1,k2,p1,p2是直接調(diào)用OpenCV中標定函數(shù)求解出的,以及每幅圖像相對于對應攝像機成像平面的旋轉(zhuǎn)矩陣R"(或旋轉(zhuǎn)向量)和平移向量t",而不是世界坐標系相對于攝像機坐標系,也不是兩部攝像機之間的空間關(guān)系。而對于外參[R t],一直都是很抽象的問題。

在重建的過程中,主要需要兩個元素:

1、攝像機內(nèi)M1、外參數(shù)M2(或者說是投影矩陣M=M1*M2)

2、左右成像平面上的匹配特征點對

最后通過視差原理計算出物體上特征點對應的空間點坐標,得到最終點云。

當然,有興趣的可以繼續(xù)學習、研究下去,外參可以通過圖像上的點和預先得到的世界坐標系下的物體上的空間點坐標,利用一系列數(shù)學關(guān)系計算。

在實際操作中,可以在重建過程進行自標定,即不用分別進行標定求得攝像機參數(shù),而是直接通過特征點對計算投影矩陣,后面步驟同上。當然自標定得到的結(jié)果精度不是很高,目前較多的是上面所述的張正友標定法,介于傳統(tǒng)與自標定之間。

【領 QT開發(fā)教程 學習資料, 點擊下方鏈接莬費領取↓↓ ,先碼住不迷路~】

點擊這里:

標簽:

精彩放送
房產(chǎn)
頭條