4

findHomographyOpenCVの関数から返されたパースペクティブ変換行列を(C ++またはObjective-Cのいずれかで)iOSに変換したいと思いCATransform3Dます。コアグラフィックス側の「ワープ」効果を正確に再現するという点で、できるだけ近づけてほしい。サンプルコードをいただければ幸いです。

iOSのCATransform3D.hから:

/* Homogeneous three-dimensional transforms. */

struct CATransform3D
{
    CGFloat m11, m12, m13, m14;
    CGFloat m21, m22, m23, m24;
    CGFloat m31, m32, m33, m34;
    CGFloat m41, m42, m43, m44;
};

同様の質問:

CoreGraphicsを使用してホモグラフィマトリックスを適用する

opencvアフィン行列をCGAffineTransformに変換します

4

3 に答える 3

5

免責事項

私はこれを試したことがないので、塩の粒でそれを取る.

CATRansform3D は 4x4 マトリックスで、3 次元の同種ベクトル (4x1) を操作して、同じタイプの別のベクトルを生成します。レンダリングされると、4x1 ベクトルで表されるオブジェクトは、各要素が 4 番目の要素で分割され、3 番目の要素は、どのオブジェクトがどのオブジェクトの上に表示されるかを決定するためにのみ使用されると想定しています。これが正しいと仮定して...

推論

findHomography によって返される 3x3 行列は、2 次元の同次ベクトルで動作します。そのプロセスは4つのステップで考えることができます

  1. ホモグラフィの最初の列に x を掛けます
  2. ホモグラフィの 2 列目に y を掛けます。
  3. ホモグラフィの 3 列目に 1 を掛けます。
  4. 結果の 1 番目と 2 番目のベクトル要素は 3 番目で除算されます

このプロセスを 4x4 ベクトルで複製する必要があります。結果として得られるベクトルの 3 番目の要素は目的には意味がないと想定しています。

解決

このように行列を作成します (H はホモグラフィ行列です)

[H(0,0), H(0,1), 0, H(0,2),
 H(1,0), H(1,1), 0, H(1,2),
      0,      0, 1,      0
 H(2,0), H(2,1), 0, H(2,2)]

これは明らかに 1、2、および 3 を満たします。均質要素は常に最後の要素であるため、4 が満たされます。そのため、1 行下に移動する必要がある場合は、「同種の行」を使用します。3 行目の 1 は、ベクトルの z 成分を無傷で通過させるためのものです。

上記のすべては、混乱を避けるために行優先表記 (openCV など) で行われます。Tommy's answer を見て、列メジャーへの変換がどのように見えるかを確認できます (基本的には転置するだけです)。ただし、現時点では、Tommy と私はマトリックスの作成方法について意見が分かれていることに注意してください。

于 2013-01-22T23:29:04.837 に答える
4

ドキュメントを読んだところ、m11inCATransform3Dは in に相当し、 in はainCGAffineTransformm12相当bします。

以下のコメントのとおり、OpenCV が返す行列が 3x3 であることを理解しています (振り返ってみると、これは予想されるサイズです)。したがって、単位行列に相当する要素を他の要素に入力します。Hammer's answer によると、(通常は暗黙的な) 同次座標を扱う部分をその場所に保持し、他のすべてを ID でパディングする必要があります。

[余談: 私の最初の答えは間違っていました。私はコードを投稿しましたが、Hammer は投稿していないので、正しくなるように編集しました。この投稿は、決して私の回答だけではないことを反映するために、コミュニティ ウィキとしてマークされています]

だから私はあなたが欲しいと思う:

CATransform3D MatToTransform(Mat cvTransform)
{
    CATransform3D transform;

    transform.m11 = cvTransform.at<float>(0, 0);
    transform.m12 = cvTransform.at<float>(1, 0);
    transform.m13 = 0.0f;
    transform.m14 = cvTransform.at<float>(2, 0);

    transform.m21 = cvTransform.at<float>(0, 1);
    transform.m22 = cvTransform.at<float>(1, 1);
    transform.m23 = 0.0f;
    transform.m24 = cvTransform.at<float>(2, 1);

    transform.m31 = 0.0f;
    transform.m32 = 0.0f;
    transform.m33 = 1.0f;
    transform.m34 = 0.0f;

    transform.m41 = cvTransform.at<float>(0, 2);
    transform.m42 = cvTransform.at<float>(1, 2);
    transform.m43 = 0.0f;
    transform.m44 = cvTransform.at<float>(2, 2);

    return transform;
}

またはcvGetReal1D、C++ を除外する場合に使用します。

于 2013-01-22T21:08:45.160 に答える