15

ウェブカメラを使用して、既知のグローバル位置を持つ 4 つのフィデューシャルの画像からグローバル ポーズ推定値を取得しようとしています。

多くのstackexchangeの質問といくつかの論文をチェックしましたが、正しい解決策が得られないようです. 私が得た位置番号は再現可能ですが、カメラの動きに直線的に比例するものではありません。参考までに、C++ OpenCV 2.1 を使用しています。

このリンクには、私の座標系と以下で使用されるテスト データが描かれています。

% Input to solvePnP():
imagePoints =     [ 481, 831; % [x, y] format
                    520, 504;
                   1114, 828;
                   1106, 507]
objectPoints = [0.11, 1.15, 0; % [x, y, z] format
                0.11, 1.37, 0; 
                0.40, 1.15, 0;
                0.40, 1.37, 0]

% camera intrinsics for Logitech C910
cameraMat = [1913.71011, 0.00000,    1311.03556;
             0.00000,    1909.60756, 953.81594;
             0.00000,    0.00000,    1.00000]
distCoeffs = [0, 0, 0, 0, 0]

% output of solvePnP():
tVec = [-0.3515;
         0.8928; 
         0.1997]

rVec = [2.5279;
       -0.09793;
        0.2050]
% using Rodrigues to convert back to rotation matrix:

rMat = [0.9853, -0.1159,  0.1248;
       -0.0242, -0.8206, -0.5708;
        0.1686,  0.5594, -0.8114]

これまでのところ、これらの数値に何か問題があるとわかる人はいますか? たとえば、MatLAB (上記のコードは m ファイルに適しています) などでチェックインしていただければ幸いです。

この時点から、rMat と tvec からグローバル ポーズを取得する方法がわかりません。この質問で読んだことから、rMat と tvec からポーズを取得するには、次のようにします。

position = transpose(rMat) * tVec   % matrix multiplication

しかし、私が読んだ他の情報源から、それはそれほど単純ではないと思われます。

実世界の座標でカメラの位置を取得するには、何をする必要がありますか? これが実装の問題かどうかはわかりませんが (理論上の問題である可能性が最も高い)、OpenCV で solvePnP 関数をうまく使用したことがある人にこの質問に答えてもらいたいと思いますが、アイデアも大歓迎です!

どうぞよろしくお願いいたします。

4

3 に答える 3

12

私はこれを少し前に解決しました。1年の遅れをお詫びします。

私が使用していた python OpenCV 2.1 と新しいバージョン 3.0.0-dev では、グローバル フレームでカメラのポーズを取得するには、次の手順を実行する必要があることを確認しました。

_, rVec, tVec = cv2.solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs)
Rt = cv2.Rodrigues(rvec)
R = Rt.transpose()
pos = -R * tVec

ここで、pos は、グローバル フレーム (objectPoints が表現されているのと同じフレーム) で表現されたカメラの位置です。R は、姿勢を格納するのに適した形式の姿勢行列 DCM です。オイラー角が必要な場合は、以下を使用して、XYZ 回転シーケンスを指定して DCM をオイラー角に変換できます。

roll = atan2(-R[2][1], R[2][2])
pitch = asin(R[2][0])
yaw = atan2(-R[1][0], R[0][0])
于 2015-01-09T10:09:11.040 に答える
4

グローバル ポーズとは、OpenGL で使用できる 4x4 カメラ ポーズ マトリックスを意味する場合、私はこのようにします。

CvMat* ToOpenGLCos( const CvMat* tVec, const CvMat* rVec )
{
    //** flip COS 180 degree around x-axis **//

    // Rodrigues to rotation matrix
    CvMat* extRotAsMatrix = cvCreateMat(3,3,CV_32FC1);
    cvRodrigues2(rVec,extRotAsMatrix);

    // Simply merge rotation matrix and translation vector to 4x4 matrix 
    CvMat* world2CameraTransformation = CreateTransformationMatrixH(tVec,
    extRotAsMatrix );

    // Create correction rotation matrix (180 deg x-axis)
    CvMat* correctionMatrix = cvCreateMat(4,4,CV_32FC1);
    /* 1.00000   0.00000   0.00000   0.00000
       0.00000  -1.00000  -0.00000   0.00000
       0.00000   0.00000  -1.00000   0.00000
       0.00000   0.00000   0.00000   1.00000 */
    cvmSet(correctionMatrix,0,0,1.0); cvmSet(correctionMatrix,0,1,0.0);
    ... 

    // Flip it
    CvMat* world2CameraTransformationOpenGL = cvCreateMat(4,4,CV_32FC1);
    cvMatMul(correctionMatrix,world2CameraTransformation,   world2CameraTransformationOpenGL);

    CvMat* camera2WorldTransformationOpenGL = cvCreateMat(4,4,CV_32FC1);
    cvInv(world2CameraTransformationOpenGL,camera2WorldTransformationOpenGL,
    CV_LU );

    cvReleaseMat( &world2CameraTransformationOpenGL );
    ...

    return camera2WorldTransformationOpenGL;
}

OpenCV と OpenGL/VTK/etc のため、座標系の反転が必要だと思います。この図に示すように、異なる座標系を使用します。OpenGL および OpenCV 座標系

まあ、それはこのように機能しますが、誰かがより良い説明を持っているかもしれません.

于 2013-12-04T11:21:14.700 に答える
2

カメラの位置は {- transpose( r ) * t } になります。それでおしまい。

そして、cv::solvePnp を除いてすべて正しく実行しました。私が正しく覚えていれば、cv::solvePnp は変換用に (4 x 1) ベクトルを与えます。 x 、 y 、 z を w 座標で除算する必要があります。

于 2013-04-30T18:20:15.157 に答える