1

現在、2D イメージ内にオイラー角の 3D 表現を描画しようとしています (OpenGL または 3D グラフィック ウィンドウはありません)。画像出力は以下のようになります。

オイラー角

基本的に、回転行列または一連のオイラー角を取り、それらを上記のように 2D 画像に出力できる研究またはアルゴリズムを探しています。これは、OpenCV を使用する C++ アプリケーションに実装されます。オブジェクトの状態に基づいて、OpenCV ウィンドウにアノテーション情報を出力するために使用されます。

回転行列から単位ベクトルを分解し、それらの x、y コンポーネントを抽出して (0,0) からデカルト空間に線を引くことができるはずなので、これは考えすぎだと思います。私はこの考えで正しいですか?

編集:正投影を探しています。上の画像は正しいカメラ/視野角を持っていると想定できます。

どんな助けでも大歓迎です。

ありがとう、

編集: ソース コードの例は、私のレポで見つけることができます。ヘッダー: https://bitbucket.org/jluzwick/tennisspindetector/src/6261524425e8d80772a58fdda76921edb53b4d18/include/projection_matrix.h?at=master

クラス定義: https://bitbucket.org/jluzwick/tennisspindetector/src/6261524425e8d80772a58fdda76921edb53b4d18/src/projection_matrix.cpp?at=master

これは最良のコードではありませんが、機能し、受け入れられた回答で説明されている射影行列を取得するために必要な手順を示しています。

また、実際の射影行列の youtube vid もここにあります (スケールと変換が追加されています): http://www.youtube.com/watch?v=mSgTFBFb_68

4

2 に答える 2

2

これが私の2セントです。それが役に立てば幸い。

私が正しく理解している場合は、3D座標系を回転させてから、指定された2D平面に直交投影します( 2D平面は、元の回転していない3D座標系に対して定義されます)。

「 3D座標系の回転と射影」とは、「3 つの3D基底ベクトルを回転させて2D平面に直交投影し、平面の2D基底に対して2Dベクトルになるようにする」ことです。元の3Dベクトルをプライミングせず、結果の2Dベクトルをプライミングします。{ e1, e2, e3} = {e1..3}3D正規直交基底 (与えられている) とし、{e1', e2'} = {e1..2'}2D正規直交基底 (これを指定する必要があります) とします。定義)。基本的に、PR * v = v'となるような演算子PRを見つける必要があります。

線形代数、演算子、および行列表現について多くのことを話すことができますが、投稿するには長すぎます。次のように言えば十分です。

  1. 3D回転演算子と3D- >2D射影演算子の両方に、実数行列表現があります (線形変換; 2D3Dの部分空間です)。
  2. これらは結果として適用される 2 つの変換、つまりPR * v = P * R * v = v'であるため、回転行列Rと射影行列Pを見つける必要があります。明らかに、Rを使用してvを回転させた後、 Pを使用して結果ベクトルvRを射影できます。
  3. 回転行列Rは既にあるので、与えられた3x3行列であると見なします。簡単にするために、射影ベクトルvR = R * vについて説明します。
  4. 射影行列Pは、i番目の列がi番目の3D基底ベクトルeiの {e1..2'}基底への射影である2x3行列です。

3DベクトルvRが正規直交基底{e1..2'}で2D平面上の2Dベクトルv'に線形変換されるようなP射影行列を求めましょう。

2D平面は、それに垂直なベクトルによって簡単に定義できます。たとえば、OP の図から、2D平面 (紙の平面) には通常の単位ベクトルn = 1/sqrt(3) * ( 1, 1, 1 ) があるようです。このnで定義される2D平面で2D基底を見つける必要があります。2Dにある任意の 2 つの線形独立ベクトル平面はそのような基底を形成しますが、ここにはそのような基底が無数にあります。問題の幾何学から、簡単にするために、さらに 2 つの条件を課しましょう。まず、基底が正規直交であること。第二に、視覚的に魅力的である必要があります (ただし、これは多少主観的な条件です)。簡単にわかるように、そのような基底は、e1' = ( 1, 0 )' = x'軸 (水平、左から右への正の方向) およびe2' = ( 0, 1 )' = y'軸 (垂直、下から上への正の方向)。

この{e1', e2'} 2D基底を{e1..3} 3D基底で見つけてみましょう。

  1. e1 'e2'を元の基底でe1"e2"とします。この場合、e1"にはe3成分 ( z成分) がないことに注意し、 n dot e1" = 0という事実を使用すると、e1' = ( 1, 0 )' -> e1" = ( -1 /sqrt(2), 1/sqrt(2), 0 ) ( { e1..3}基底) ここで、ドットは内積を表します。
  2. 次に、e2" = nクロスe1" = ( -1/sqrt(6), -1/sqrt(6), 2/sqrt(6) ) . ここで、crossはクロス積を表します。

n = 1/sqrt(3) * ( 1, 1, 1 )で定義される2D平面の2x3射影行列Pは、次の式で与えられます。

( -1/sqrt(2)    1/sqrt(2)        0     )
( -1/sqrt(6)   -1/sqrt(6)    2/sqrt(6) )

ここで、1 列目、2 列目、3 列目は{e1..3} 3D基底を2D基底{e1..2'}に変換します。つまり、 3D基底からのe1 = ( 1, 0, 0 )は座標( -1/sqrt( 2)、-1/ sqrt (6) )などです。

結果を検証するために、いくつかの明らかなケースを確認できます。

  1. nは2D平面に直交するため、投影はありません。実際、P * n = P * ( 1, 1, 1 ) = 0です。
  2. e1e2、およびe3は、 {e1..2'} の表現、つまりP行列の対応する列に変換する必要があります。実際、P * e1 = P * ( 1, 0 ,0 ) = ( -1/sqrt(2), -1/sqrt(6) )などです。

問題を確定します。ここで、任意に選択された2D平面に対して3Dから2Dへの射影行列Pを作成しました。これで、以前に回転行列Rによって回転された任意のベクトルをこの平面に射影できるようになりました。たとえば、回転した元の基底{R * e1, R * e2, R * e3} . さらに、与えられたPRを乗算して、回転射影変換行列PR = P * Rを得ることができます。

PS C++ の実装は、宿題として残されています ;)。

于 2013-08-19T15:55:00.810 に答える
0

回転行列は簡単に表示できます。

回転行列は、法線、従法線、接線を使用して構築できます。

次のようにそれらを元に戻すことができるはずです:-

Bi-Normal (y') : matrix[0][0], matrix[0][1], matrix[0][2]
Normal    (z') : matrix[1][0], matrix[1][1], matrix[1][2]
Tangent   (x') : matrix[2][0], matrix[2][1], matrix[2][2]

透視変換を使用すると、透視 (x,y) = (x/z, y/z) を追加できます

示されているものと同様の正射投影プロジェクトを実現するには、別の固定回転行列を掛けて「カメラ」ビュー (右に 45°、次に上) に移動する必要があります。

次に、エンドポイント x(1,0,0)、y(0,1,0)、z(0,0,1) および center(0,0,0) を最終的な行列で乗算できます。 x、y 座標。

center は常に 0,0,0 に変換する必要があります

次に、これらの値をスケーリングして、2D キャンバスに描画できます。

于 2013-08-18T23:50:22.183 に答える