根據相機成像模型,如果已知相機的內參矩陣、世界座標系中若干空間點的三維座標和空間點在影象中投影的二維座標,那麼可以計算出世界座標系到相機座標系的旋轉向量和平移向量。如圖所示,當知道點ci在世界座標系下的三維座標和這些點在影象中對應點的二維座標時,結合相機的內參矩陣和畸變係數,就可以計算出世界座標系變換到相機座標系的旋轉向量和平移向量。
在這種情況下,可以估計相機在世界座標系中的位姿。如果將世界座標系看成前一時刻的相機座標系姿態,ci在世界座標系下的三維座標看成ci在前一時刻相機座標系中的座標,就可以估計出前一時刻到當前時刻相機的運動變化,進而得到視覺里程計資訊。不過需要注意的是,由於單目相機沒有深度資訊,因此,如果ci的三維座標是真實物理尺度的三維座標,那麼估計出的平移向量就是真實的物理尺度,否則就是放縮後的平移向量。
從理論上來說,只要知道世界座標系中3個點的三維座標和對應影象中的座標,根據相機內參矩陣和畸變係數就可以解算世界座標系與相機座標系之間的轉換關係。這種利用3個空間點和影象點的解算方法稱為p3p方法。當然,如果點數大於3,那麼可以得到更加精確的旋轉向量和平移向量。當點數大於3時,計算旋轉向量和平移向量的方法稱為pnp方法。兩種方法在opencv4中都有相應的函式, p3p方法對應的是solvep3p( )函式, pnp方法對應的是solvepnp( )函式。由於solvepnp( )函式包含了solvep3p( )函式的功能,因此這裡只介紹solvepnp( )函式的使用方法。
原理:根據影象的情況反推出相機的運動情況
當前時刻相機座標系下空間三維點的座標(如果獲得的是世界座標系下的座標,需要先將座標轉換到相機座標系下)(此時刻得到的是3d座標),移動後,另乙個時刻,同樣的空間三維點的畫素座標(這一時刻得到的是2d座標)。如果相機連續運動,那麼依次估計下去可以得到相機在整個空間中的運動狀態,就實現了運動軌跡的估計,即乙個視覺里程計。這裡得到是旋轉是真實的,但平移的非真實的。
若將初始相機座標系(即第一時刻的相機座標系)看作是世界座標系,此時計算得到的r和t就是相機標定時得到的外參矩陣。
附:當前時刻相機座標系下空間三維點的座標可以通過兩幀影象之間的三角化獲得。
執行結果:
《opencv4快速入門》中的執行結果:
附上例**:
#include
#include
#include
using
namespace std;
using
namespace cv;
intmain()
}//輸入前文計算得到的內參矩陣和畸變矩陣
mat cameramatrix =
(mat_<
float
>(3
,3)<<
532.016297,0
,332.172519,0
,531.565159
,233.388075,0
,0,1
);mat distcoeffs =
(mat_<
float
>(1
,5)<<
-0.285188
,0.080097
,0.001274,-
0.002415
,0.106579);
//用pnp演算法計算旋轉和平移量
mat rvec, tvec;
solvepnp
(pointsets, imgpoints, cameramatrix, distcoeffs, rvec, tvec)
; cout <<
"世界座標系變換到相機座標系的旋轉向量:"
<< rvec << endl;
//旋轉向量轉換旋轉矩陣
mat r;
rodrigues
(rvec, r)
; cout <<
"旋轉向量轉換成旋轉矩陣:"
<< endl << r << endl;
mat t = tvec;
cout <<
"平移矩陣:"
<< endl << t << endl;
//用pnp+ransac演算法計算旋轉向量和平移向量
mat rvecransac, tvecransac;
solvepnpransac
(pointsets, imgpoints, cameramatrix, distcoeffs, rvecransac, tvecransac)
; mat rransac;
rodrigues
(rvecransac, rransac)
; cout <<
"旋轉向量轉換成旋轉矩陣:"
<< endl << rransac << endl;
waitkey(0
);return0;
}
每日一練day 1
1 關鍵字static 的作用?static關鍵字至少有下列n個作用 1 設定變數的儲存域,函式體內static變數的作用範圍為該函式體,不同於auto變數,該變數的記憶體只被分配一次,因此其值在下次呼叫時仍維持上次的值 2 限制變數的作用域,在模組內的static全域性變數可以被模組內所用函式訪問...
OpenCV4每日一練day9 單目相機標定
準備檔案 執行 gif 最終標定結果 附 include include include include using namespace std using namespace cv intmain size board size size 9 6 方格標定板內角點數目 行,列 vector img...
OpenCV4每日一練day12 雙目相機標定
檔案準備 執行結果 opencv4快速入門 中的執行結果 附上例 include include include include using namespace std using namespace cv 檢測棋盤格內角點在影象中座標的函式 void getimgspoints vector im...