12

如何從每個相機的視圖中獲取每個使用OpenCV的相機的旋轉矩陣,平移向量以及某些縮放因子?對於每張圖片,我都有幾個特徵點的圖像座標。並非所有的特徵點都可以在所有圖片中看到。 我想將對象的特徵點的計算出的3D座標映射到稍微不同的對象以將第二對象的形狀與第一對象對齊。來自特徵點的OpenCV外置相機

我聽說有可能使用cv::calibrateCamera(...)但我不能完全通過它...

是否有人有那種問題的經驗?

+0

目前尚不清楚上面,如果你知道3D世界,你觀察點的座標在不同的圖像。如果是這種情況,這是一個Perspective-n-point問題,您可以使用此處提供的EPnP算法來校準每個攝像機的參數:http://cvlab.epfl.ch/software/EPnP/index.php。否則,請參閱下面的答案。 – Rulle

+1

拍攝對象的三維座標未知。 –

+0

如果物體上的點的三維座標是_unknown_,我不認爲cv :: calibrateCamera會起作用,因爲它似乎假定物體點是_known_。 – Rulle

回答

11

我在OpenCV中遇到了和你一樣的問題。我有一個立體圖像對,我想計算攝像機的外部參數和所有觀察點的世界座標。此問題已在此處處理:

Berthold K. P. Horn。相對定位重新審視。 Berthold K. P. Horn。人工智能實驗室,麻省理工學院,545技術...

http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.64.4700

但是,我沒能找到一個合適的實現這個問題(也許你會發現一個)的。由於時間限制,我沒有時間去理解本文中的所有數學算法並自己實現,所以我想出了一個適用於我的快速而骯髒的解決方案。我將解釋我做了什麼來解決它:

假設我們有兩個攝像頭,其中第一個攝像頭有外部參數RT = Matx :: eye()。現在對第二臺攝像機的旋轉R進行猜測。對於在兩幅圖像中觀察到的每一對圖像點,我們計算它們在世界座標中相應光線的方向,並將它們存儲在二維陣列中(編輯:假定內部相機參數已知)。我們可以做到這一點,因爲我們假設我們知道每個相機的方向。現在我們建立一個超定線性系統,其中C是第二臺相機的中心。我爲你提供以計算功能:

Mat buildA(Matx<double, 3, 3> &R, Array<Vec3d, 2> dirs) 
{ 
    CV_Assert(dirs.size(0) == 2); 
    int pointCount = dirs.size(1); 
    Mat A(pointCount, 3, DataType<double>::type); 
    Vec3d *a = (Vec3d *)A.data; 
    for (int i = 0; i < pointCount; i++) 
    { 
     a[i] = dirs(0, i).cross(toVec(R*dirs(1, i))); 
     double length = norm(a[i]); 
     if (length == 0.0) 
     { 
      CV_Assert(false); 
     } 
     else 
     { 
      a[i] *= (1.0/length); 
     } 
    } 
    return A; 
} 

然後調用CV :: SVD :: solveZ(A)會給你規範1的這個系統最小二乘的解決方案。這樣,您可以獲得第二臺相機的旋轉和平移。然而,由於我只是猜測了第二個相機的旋轉,我對它的旋轉進行了幾次猜測(使用cx :: Rodrigues計算旋轉矩陣的3x1向量Ω參數化),然後我通過用數字雅可比在Levenberg-Marquardt優化器中反覆求解AC = 0。它適用於我,但它有點骯髒,所以如果你有時間,我鼓勵你實施論文中解釋的內容。

編輯:

這裏是評價殘留的載體,列文伯格 - 馬夸特優化的程序:

void Stereo::eval(Mat &X, Mat &residues, Mat &weights) 
{ 

     Matx<double, 3, 3> R2Ref = getRot(X); // Map the 3x1 euler angle to a rotation matrix 
     Mat A = buildA(R2Ref, _dirs); // Compute the A matrix that measures the distance between ray pairs 
     Vec3d c; 
     Mat cMat(c, false); 
     SVD::solveZ(A, cMat); // Find the optimum camera centre of the second camera at distance 1 from the first camera 
     residues = A*cMat; // Compute the output vector whose length we are minimizing 
    weights.setTo(1.0); 
} 

順便說一句,我搜索多一點在互聯網上發現其他一些可用於計算相機之間相對方向的代碼。我還沒有嘗試過任何代碼還,但它似乎有用:

http://www9.in.tum.de/praktika/ppbv.WS02/doc/html/reference/cpp/toc_tools_stereo.html

http://lear.inrialpes.fr/people/triggs/src/

http://www.maths.lth.se/vision/downloads/

+0

非常感謝您的回答。我想我理解你寫的和編碼的內容,這將幫助我找到解決我的問題的可能解決方案。但是我相信'cv :: calibrateCamera(...)'與你提出的很相似。他們描述算法如下: –

+0

1.首先,它計算初始固有參數(該選項僅適用於平面校準模式)或從輸入參數中讀取它們。失真係數最初都設置爲零(除非指定了一些CV_CALIB_FIX_K?)。 2.初始相機姿態估計好像內在參數已經知道。這是通過使用FindExtrinsicCameraParams2 –

+0

3.然後運行全局Levenberg-Marquardt優化算法以最小化重投影誤差,即觀察到的特徵點imagePoints和投影之間的平方距離的總和(使用當前的攝像機參數估計和姿勢)對象點objectPoints;請參閱ProjectPoints2。 –

2

這些靜態相機是否需要校準以備將來用作立體聲對?在這種情況下,您會想要使用cv::stereoCalibrate()函數。 OpenCV包含一些示例代碼,其中之一是stereo_calib.cpp,可能值得研究。

+0

感謝您的回答,但我對使用立體聲對沒有興趣。我有一個攝像頭,用來從不同側面查看同一個物體。然後,每張圖片中標記的特徵點應該幫助我計算一個稍微變形的虛擬對象的對應點的新位置。然後虛擬物體應該具有與被拍攝的真實物體一樣的確切幾何形狀。 順便說一下'cv :: calibrateCamera(...)'在計算過程中使用'cv :: stereoCalibrate()'。 –

+0

好吧,你的單鏡頭校準(即你知道的內在參數 - 焦距,像素歪斜,原理點,失真係數)? – Chris

+0

我可以估計它們,但實際值是未知的。 –