2013-03-20 41 views
5

我使用的OpenCV和了openFrameworks(即OpenGL的)來計算一個相機的OpenGL從圖像(世界變換和投影矩陣)(和以後,若干圖像爲三角測量)。確定外在相機與opencv世界空間對象

對於OpenCV中的目的,「平面圖」變成與0,0,0世界的中心的對象(即棋盤)。 世界/地板的位置是已知的,所以我需要獲得投影信息(失真係數,fov等)和相機的外部座標。

2D input coordinates

我已映射這些平面佈置圖的點的視圖位到在歸一化的視圖空間我的2D圖像([0,0]是左上。[1,1]是右下)。因爲它需要,所以我轉換到xy平面(不確定這裏如果z-up是負面的或正面的...),因爲它需要opencv爲平面

ofMatrix4x4 gWorldToCalibration(
    1, 0, 0, 0, 
    0, 0, 1, 0, 
    0, 1, 0, 0, 
    0, 0, 0, 1 
    ); 

我將1,1作爲ImageSize傳遞給calibrateCamera。 標誌CV_CALIB_FIX_ASPECT_RATIO|V_CALIB_FIX_K4|CV_CALIB_FIX_K5 calibrateCamera成功運行,給了我一個小錯誤(通常約爲0.003)。

使用calibrationMatrixValues我得到一個合理的FOV,通常50度左右,所以我敢肯定的內在特性是正確的。

現在來計算相機的外在世界空間變換...我不相信我需要使用solvePnP,因爲我只有一個對象(儘管我之前嘗試過所有這些,並且回來的時候也是這樣結果)

// rot and trans output... 
cv::Mat& RotationVector = ObjectRotations[0]; 
cv::Mat& TranslationVector = ObjectTranslations[0]; 

// convert rotation to matrix 
cv::Mat expandedRotationVector; 
cv::Rodrigues(RotationVector, expandedRotationVector); 

// merge translation and rotation into a model-view matrix 
cv::Mat Rt = cv::Mat::zeros(4, 4, CV_64FC1); 
for (int y = 0; y < 3; y++) 
    for (int x = 0; x < 3; x++) 
     Rt.at<double>(y, x) = expandedRotationVector.at<double>(y, x); 
Rt.at<double>(0, 3) = TranslationVector.at<double>(0, 0); 
Rt.at<double>(1, 3) = TranslationVector.at<double>(1, 0); 
Rt.at<double>(2, 3) = TranslationVector.at<double>(2, 0); 
Rt.at<double>(3, 3) = 1.0; 

現在,我已經有了一個旋轉&變換矩陣,但它是列爲主(我相信作爲對象是完全傾斜,如果我不轉,以上代碼看起來列爲主向我)

// convert to openframeworks matrix AND transpose at the same time 
ofMatrix4x4 ModelView; 
for (int r=0; r<4; r++) 
    for (int c=0; c<4; c++) 
     ModelView(r,c) = Rt.at<double>(c, r); 

使用矩陣的逆矩陣將我的平面換回到我的座標空間(y向上)。

// swap y & z planes so y is up 
ofMatrix4x4 gCalibrationToWorld = gWorldToCalibration.getInverse(); 
ModelView *= gCalibrationToWorld; 

不知道如果我需要做到這一點...我沒有否定了飛機,當我把它們放進校準......

// invert y and z planes for -/+ differences between opencv and opengl 
ofMatrix4x4 InvertHandednessMatrix(
    1, 0, 0, 0, 
    0, -1, 0, 0, 
    0, 0, -1, 0, 
    0, 0, 0, 1 
    ); 
ModelView *= InvertHandednessMatrix; 

最後,模型視圖對象-relative對照相機和我要反轉它是攝像機相對於到物體(0,0,0)

ModelView = ModelView.getInverse(); 

output 3D view

這會導致相機位置錯誤,並且旋轉錯誤。這不是遙遠,相機是Y平面的右側,翻譯並不瘋狂,我認爲這是正確的方式了....只是不正確呢。 繪製藍色圓圈是我期待相機的地方。

我已經經歷了大量的答案,文檔十幾次,但沒有發現任何正確的,我敢肯定,我已經涵蓋了所有我需要的空間轉換明智的,但也許我'錯過了明顯的東西? 或以錯誤的順序做某事?

更新1 - 世界空天飛機... 我已經改變了我的世界空間地板平面XY(Z高達)來匹配OpenCV的輸入。 (gWorldToCalibration現在是一個單位矩陣)。 旋轉仍然是錯誤的,和投影輸出是一樣的,但是我覺得翻譯現在是正確的(這當然是上的標記正確的一面) 3D view on XY plane

UPDATE2 - 實時影像尺寸 我m正在進入相機校準中的圖像大小;看到我正在使用1,1是標準化的,但imageSize參數是整數,我認爲這可能是重要的...我想它是(紅色框是投影的視圖空間點與z相交的地方= 0 floor plane) 沒有任何失真校正,這裏是結果(唯一改變的是從1,1到640,480的圖像大小,我將標準化的輸入視圖空間座標乘以640,480) enter image description here 我打算嘗試並添加失真校正,以查看它是否排好 ...

+0

您確定可以看到相機的位置,但不是可視化外部相機矩陣的平移分量嗎? – user502144 2013-03-20 22:51:26

+0

我不確定是否錯誤地閱讀了您的評論,但最終的模型視圖矩陣(我相信是/應該是凸輪pos)設置爲ofCamera全局變換。可視化如下;綠+ Y,藍+ z,紅+ x。 – 2013-03-21 00:30:58

+0

網格在0,0,0附近消失。我可能已經得到外在和相機轉換錯誤?但這就是倒置的原因。 – 2013-03-21 00:32:14

回答

0

現在至少我把我的編輯2(ImageSize必須是大於1,1的東西)作爲修正,因爲它產生的結果非常多,更像我期待的。

我可能會把事情顛倒過來,但是這會產生相當不錯的結果。

+0

嗨!我有類似的問題,但是..從編輯它不是很清楚..最後是什麼你一步一步的程序? – nkint 2013-09-04 18:16:09

+0

該問題的解決方案是不規範我的圖像座標,所以,而不是浮動和圖像1,1我用像素座標和1920,1080。我不相信我需要改變別的。 – 2013-09-06 10:38:20

0

首先要檢查的是驗證在給定估計的內部和外部相機矩陣的圖像上標記是否被正確重新投影。然後,您可以在全局框架中查找相機位置,並查看它是否與標記位置一致。 (使用OpenCV中的座標系。)這樣做完成後,沒有太多可能出錯的事情。既然你想要點在xz平面上,你只需要一次座標轉換。正如我所看到的,您可以使用gWorldToCalibration矩陣來完成此任務。然後將變換應用到標記和相機位置,並驗證標記是否在正確的位置。那麼相機的位置也是正確的(除非座標系統出現問題,但可以很容易地修正)。

+2

標記從攝像機重新映射到顯然位於錯誤位置的光線(藍線)。綠色多邊形是對N米的射線投影,紅色是我碰到y = 0平面的位置(在這種情況下是無意義的)。但我想你的意思是重新投影到視圖/圖像空間中,我將在早上這樣做!也可以將所有東西都轉換爲z =向上以刪除一個步驟... – 2013-03-21 00:37:27

+0

是的,我的意思是在校準後立即重新投影圖像。這可以通過乘以由標記座標獲得的內在和外在矩陣(在用於校準的座標系中)來完成。 – user502144 2013-03-21 05:13:21

+0

我的結果不好...我製作了一個4x4的內在矩陣(0,0,0,1爲其他列/行),並從calibrateCamera的cameraMatrix中複製剩餘的內容。我使用'rT'作爲外部矩陣(這是否正確?)並乘以我的標準化輸入視圖座標。 每個重新投影的世界位置都有相似的數量... ('4.0,1.7,5.5','4.3,1.6,6.0','4.7,1.5,6.0','4.8,1.6,5.5' ) 我的外在翻譯是'1.4,4.3,6.3'。我不禁想到這些值是鏈接的....我在做重新投影測試嗎? – 2013-03-21 16:06:29

0

我想你應該採取逆gWorldToCalibration

ofMatrix4x4 gCalibrationToWorld = gWorldToCalibration.getInverse(); 

這裏我貼的代碼,你想要什麼OpenCV- to OpenGL COS這是做更多或更少。它在C中,但在C++中應該類似。

相關問題