在我的實驗專案中,我採用介於傳統標定和自標定之間的張正友棋盤格追蹤標定,該標定方法易於操作,標定精度高,還有一點opencv中的標定演算法也採用張正友標定法。在實驗專案開始之前,我看了《計算機視覺》馬頌德,張正友這本書,還看了張正友的棋盤標定**文(英文不好懂),理論知識就足以。接下來,我用matlab中的工具箱進行了攝像機標定,之所以先採用matlab是因為可以讓我們先了解相機標定原理和過程,同時標定精度高,在角點提取和畸變優化方面,功能強大,對計算出來的引數還可以進行迭代優化,關於matlab的相機標定大家可參考和
,同時matlab採用的是tasi兩部標定演算法。
接下來,我將重點放在相機標定中mfc介面的設計,opencv**的編寫上,在這之中遇到了許多小問題,希望對大家以後的開發有所借鑑。我的開發換進是vc6.0+opencv1.0(這種搭配應該是上個世紀的產物)。我將**的實現分為兩大模組,分別是實現攝像機開啟關閉截圖模組和標定模組(計算出內外引數,結果顯示在edit box中),總體的介面設計如下圖:
因為opencv1.0版本在win7系統中會出現一些問題,包括執行緒的建立,這些我會一一解答。
攝像機的開啟**如下:
void cimageshowdlg::onbutton1()
iplimage* m_frame;
m_frame=camera.queryframe();
cvvimage m_cvvimage;
m_cvvimage.copyof(m_frame,1);
if (true)
settimer(1,10,null); // 設定計時器,每10ms觸發一次事件
}
void cimageshowdlg::ontimer(uint nidevent)
}
接下來,就是攝像機的關閉,比較簡單。
void cimageshowdlg::onbutton2()
接下來就是,擷取符合要求的棋盤格,就是要判斷讀取到的幀角點提取數量是否符合要求,如果是,則儲存,**如下。
void cimageshowdlg::onbutton3()
; static int count=1;
sprintf(tmpfile,"%s\\%d.bmp",filename,count++);
sleep(2000);
cvsize board_size = cvsize(4,6); /* 定標板上每行、列的角點數 */
int board_n=board_size.width*board_size.height;//標定板上的內角點總數
cvpoint2d32f* image_points_buf = new cvpoint2d32f[board_n]; /* 快取每幅影象上檢測到的角點 */
int num= -1 ;//用於儲存角點個數。 所有變數定義後必須初始化,這是乙個程式設計優良習慣
int found=cvfindchessboardcorners( m_frame, board_size,image_points_buf, &num, cv_calib_cb_adaptive_thresh);
if (found==0)
else
}
下來是,攝像機標定演算法的**實現和將計算結果顯示在edit box中。
void cimageshowdlg::onimageshow()
int found=cvfindchessboardcorners( view.cvimage, board_size,
image_points_buf, &count, cv_calib_cb_adaptive_thresh);
if (found==0)
//cvfindchessboardcorners(要檢測的棋盤圖,圖中每行和每列的角點個數,檢測到的角點,輸出——角點個數,操作標誌)
//cv_calib_cb_adaptive_thresh - 使用自適應閾值(通過平均影象亮度計算得到)將影象轉換為黑白圖,而不是乙個固定的閾值。
//cv_calib_cb_filter_quads - 使用其他的準則(如輪廓面積,周長,方形形狀)來去除在輪廓檢測階段檢測到的錯誤方塊。
//返回值:如果所有角點都被檢測到且它們都被以一定順序排布(一行一行地,每行從左到右),函式返回非零值,
//否則在函式不能發現所有角點或者記錄它們地情況下,函式返回0
else
fout<
//引數(row,col,channel)
matriximage_points(1,image_points_seq.cvseq->total,2); /* 儲存提取的所有角點 */
matrixpoint_counts(1,sucesses,1); /* 每幅影象中角點的數量 */
/*內外引數*/
matrixintrinsic_matrix(3,3,1); /* 攝像機內引數矩陣 */
matrixdistortion_coeffs(1,4,1); /* 攝像機的4個畸變係數:k1,k2,p1,p2 */
matrixrotation_vectors(1,sucesses,3); /* 每幅影象的旋轉行向量 */
matrixtranslation_vectors(1,sucesses,3); /* 每幅影象的平移行向量 */
/* 初始化定標板上角點的三維座標 */
int i,j,t;
for (t=0;ttotal;i++)
/* 初始化每幅影象中的角點數量,這裡我們假設每幅影象中都可以看到完整的定標板 */
for (i=0;iimage_points2(1,point_counts(0,0,0),2); /* 儲存重新計算得到的投影點 */
fout
matrixrotation_matrix(3,3); /* 儲存每幅影象的旋轉矩陣 */
fout<
fout<
以上**是將所儲存的,計算出攝像機內外引數,並將結果儲存在txt檔案中,這主要方便後續將結果顯示在編輯框中。還有一點,雖然將標定結果存入了txt檔案中,但是若想在上述**中直接實現將標定結果顯示在編輯框中,是不可能的,你會發現編輯框中將出現亂碼(燙燙燙燙燙燙燙燙燙燙燙),解決方法是另寫乙個button控制項,究其原因是windows未將標定結果寫入外存,只是存入緩衝區中,故你將在txt檔案中看不到任何結果,但若關閉vc6.0,結果將出現在txt文字中。
接下來就是將標定結果顯示在編輯框中。
void cimageshowdlg::onreadintrinsic()
以上就是我對相機標定的理解,詳細**可看我的** 攝像機標定
利用攝像機所拍攝到的影象來還原空間中的物體。在這裡,不妨假設攝像機所拍攝到的影象與三維空間中的物體之間存在以下一種簡單的線性關係 像 m 物 這裡,矩陣m可以看成是攝像機成像的幾何模型。m中的引數就是攝像機引數。通常,這些引數是要通過實驗與計算來得到的。這個求解引數的過程就稱為攝像機標定。中文名 攝...
攝像機標定
攝像機鏡頭的畸變 由於攝像機光學系統並不是精確地按理想化的小孔成像原理工作,存在有透鏡畸 變,物體點在攝像機成像面上實際所成的像與理想成像之間存在有光學畸變誤差。主要的畸變誤差分為三類 徑向畸變 偏心畸變和薄稜鏡畸變。第一類只產生徑向 位置的偏差,後兩類則既產生徑向偏差,又產生切向偏差,下圖2 為無...
攝像機標定(一)
廣義來說,相機標定不單包括成像過程的幾何關係標定,還包括輻射關係的標定,本文只 幾何關係。相機標定是3d計算機視覺 computer vision 裡從2d影象中提取量測資訊的必要步驟。最初發展於攝影測量學 photogrammetry 後逐漸被大量應用於計算機視覺中。相機標定一般來說需要參照物或標...