48

ビデオ(または画像)に四角形(必ずしも正方形または長方形である必要はありません)を表す4つの同一平面上の点があり、それらの上に仮想立方体を表示できるようにしたいのですが、立方体の角が正確に角に立っています。ビデオクワッドの。

ポイントは同一平面上にあるため、単位正方形のコーナー([0,0] [0,1] [1,0] [1,1])とクワッドのビデオ座標の間のホモグラフィを計算できます。

このホモグラフィから、正しいカメラポーズを計算できるはずです。つまり、[R | t]ここで、Rは3x3の回転行列、tは3x1の並進ベクトルであり、仮想立方体はビデオクワッド上にあります。

私は多くの解決策を読み(そのうちのいくつかはSOで)、それらを実装しようとしましたが、それらはいくつかの「単純な」場合(ビデオクワッドが正方形の場合など)でのみ機能するようですが、ほとんどの場合は機能しません。

これが私が試した方法です(それらのほとんどは同じ原理に基づいており、翻訳の計算のみがわずかに異なります)。Kをカメラからの固有行列、Hをホモグラフィとします。計算します:

A = K-1 * H

a1、a2、a3をAの列ベクトル、r1、r2、r3を回転行列Rの列ベクトルとします。

r1 = a1 / ||a1||
r2 = a2 / ||a2||
r3 = r1 x r2
t = a3 / sqrt(||a1||*||a2||)

問題は、これがほとんどの場合機能しないことです。結果を確認するために、RとtをOpenCVのsolvePnPメソッドで得られたものと比較しました(次の3Dポイント[0,0,0] [0,1,0] [1,0,0] [1,1 、0])。

同じように立方体を表示しているので、どの場合でもsolvePnPが正しい結果を提供しますが、ホモグラフィから得られたポーズはほとんど間違っていることに気付きました。

理論的には、私のポイントは同一平面上にあるため、ホモグラフィからポーズを計算することは可能ですが、Hからポーズを計算する正しい方法を見つけることができませんでした。

私が間違っていることについての洞察はありますか?

@Jav_Rockのメソッドを試した後に編集する

こんにちはJav_Rock、あなたの答えに感謝します、私はあなたのアプローチ(そして他の多くのものも同様に)を試しました、それは多かれ少なかれ大丈夫のようです。それでも、4つの同一平面上の点に基づいてポーズを計算するときに、まだいくつかの問題が発生します。結果を確認するために、solvePnPの結果と比較します(反復再射影エラー最小化アプローチにより、はるかに優れています)。

次に例を示します。

キューブ

  • 黄色い立方体:PNPを解く
  • ブラックキューブ:Jav_Rockのテクニック
  • シアン(およびパープル)キューブ:まったく同じ結果が得られた他のいくつかの手法

ご覧のとおり、黒い立方体は多かれ少なかれ問題ありませんが、ベクトルは正規直交しているように見えますが、バランスが取れていないようです。

EDIT2:(正規直交性を強制するために)計算後にv3を正規化しましたが、いくつかの問題も解決しているようです。

4

7 に答える 7

32

ホモグラフィをお持ちの場合は、次のようにカメラのポーズを計算できます。

void cameraPoseFromHomography(const Mat& H, Mat& pose)
{
    pose = Mat::eye(3, 4, CV_32FC1);      // 3x4 matrix, the camera pose
    float norm1 = (float)norm(H.col(0));  
    float norm2 = (float)norm(H.col(1));  
    float tnorm = (norm1 + norm2) / 2.0f; // Normalization value

    Mat p1 = H.col(0);       // Pointer to first column of H
    Mat p2 = pose.col(0);    // Pointer to first column of pose (empty)

    cv::normalize(p1, p2);   // Normalize the rotation, and copies the column to pose

    p1 = H.col(1);           // Pointer to second column of H
    p2 = pose.col(1);        // Pointer to second column of pose (empty)

    cv::normalize(p1, p2);   // Normalize the rotation and copies the column to pose

    p1 = pose.col(0);
    p2 = pose.col(1);

    Mat p3 = p1.cross(p2);   // Computes the cross-product of p1 and p2
    Mat c2 = pose.col(2);    // Pointer to third column of pose
    p3.copyTo(c2);       // Third column is the crossproduct of columns one and two

    pose.col(3) = H.col(2) / tnorm;  //vector t [R|t] is the last column of pose
}

この方法は私からうまくいきます。幸運を。

于 2012-05-28T07:54:59.273 に答える
11

Jav_Rockによって提案された答えは、3次元空間でのカメラポーズの有効な解決策を提供していません。

ホモグラフィによって誘発される樹木次元の変換と回転を推定するために、複数のアプローチが存在します。それらの1つは、ホモグラフィを分解するための閉じた式を提供しますが、それらは非常に複雑です。また、ソリューションは決してユニークではありません。

幸い、OpenCV 3はすでにこの分解を実装しています(decomposeHomographyMat)。ホモグラフィと正しくスケーリングされた組み込み行列が与えられると、この関数は4つの可能な回転と平行移動のセットを提供します。

于 2015-07-09T15:43:19.093 に答える
9

誰かが@Jav_Rockによって書かれた関数のPython移植を必要とする場合に備えて:

def cameraPoseFromHomography(H):
    H1 = H[:, 0]
    H2 = H[:, 1]
    H3 = np.cross(H1, H2)

    norm1 = np.linalg.norm(H1)
    norm2 = np.linalg.norm(H2)
    tnorm = (norm1 + norm2) / 2.0;

    T = H[:, 2] / tnorm
    return np.mat([H1, H2, H3, T])

私のタスクではうまく機能します。

于 2014-11-25T23:47:19.600 に答える
9

ホモグラフィ行列から[R|T]を計算することは、Jav_Rockの答えよりも少し複雑です。

OpenCV 3.0には、4つの潜在的なソリューションを返すcv::decomposeHomographyMatというメソッドがあります。そのうちの1つは正しいです。ただし、OpenCVは正しいものを選択する方法を提供していませんでした。

私は現在これに取り組んでおり、おそらく今月後半に私のコードをここに投稿する予定です。

于 2015-05-14T05:43:56.890 に答える
0

画像上の正方形を含む飛行機には、カメラのレーンエージェントが消えています。この線の方程式はAx+ B y + C=0です。

あなたの飛行機の法線は(A、B、C)です!

p00、p01、p10、p11を、カメラの固有のパラメータを適用した後の点の座標であり、均質な形式であるとします。たとえば、p00 =(x00、y00,1)

消失線は次のように計算できます。

  • ダウン=p00クロスp01;
  • 左=p00クロスp10;
  • 右=p01クロスp11;
  • up = p10 cross p11;
  • v1=左クロス右;
  • v2=アップクロスダウン;
  • vanish_line = v1 cross v2;

標準のベクトル外積で交差する場所

于 2016-07-18T14:17:03.367 に答える
0

この機能を使用できます。私のために働きます。

def find_pose_from_homography(H, K):
    '''
    function for pose prediction of the camera from the homography matrix, given the intrinsics 
    
    :param H(np.array): size(3x3) homography matrix
    :param K(np.array): size(3x3) intrinsics of camera
    :Return t: size (3 x 1) vector of the translation of the transformation
    :Return R: size (3 x 3) matrix of the rotation of the transformation (orthogonal matrix)
    '''
    
    
    #to disambiguate two rotation marices corresponding to the translation matrices (t and -t), 
    #multiply H by the sign of the z-comp on the t-matrix to enforce the contraint that z-compoment of point
    #in-front must be positive and thus obtain a unique rotational matrix
    H=H*np.sign(H[2,2])

    h1,h2,h3 = H[:,0].reshape(-1,1), H[:,1].reshape(-1,1) , H[:,2].reshape(-1,1)
    
    R_ = np.hstack((h1,h2,np.cross(h1,h2,axis=0))).reshape(3,3)
    
    U, S, V = np.linalg.svd(R_)
    
    R = U@np.array([[1,0,0],
                   [0,1,0],
                    [0,0,np.linalg.det(U@V.T)]])@V.T
    
    t = (h3/np.linalg.norm(h1)).reshape(-1,1)
    
    return R,t
于 2020-12-20T19:53:48.533 に答える
-1

これは、回転行列を正規化し、結果を3x4に転置する、DmitriyVoloshynによって提出されたものに基づくPythonバージョンです。

def cameraPoseFromHomography(H):  
    norm1 = np.linalg.norm(H[:, 0])
    norm2 = np.linalg.norm(H[:, 1])
    tnorm = (norm1 + norm2) / 2.0;

    H1 = H[:, 0] / norm1
    H2 = H[:, 1] / norm2
    H3 = np.cross(H1, H2)
    T = H[:, 2] / tnorm

    return np.array([H1, H2, H3, T]).transpose()
于 2015-03-09T01:54:40.707 に答える