9

OpenCV でアフィン変換を行っていますが、その動作を直感的に理解するのに苦労しています。具体的には、特定の目的の結果を得るためにマップ マトリックスのパラメーターを指定する方法を教えてください。

質問を設定するために、私が使用している手順は、最初にワープマトリックスを定義してから変換を行うことです。

OpenCV の 2 つのルーチンは次のとおりです (Bradski & Kaehler による優れた本 OpenCV の例を使用しています)。

cvGetAffineTransorm(srcTri, dstTri, warp_matrix);
cvWarpAffine(src, dst, warp_mat);

ワープ マトリックスを定義するには、srcTri次のdstTriように定義します。

CvPoint2D32f srcTri[3], dstTri[3];

srcTri[3]次のように入力されます。

srcTri[0].x = 0;
srcTri[0].y = 0;
srcTri[1].x = src->width - 1;
srcTri[1].y = 0;
srcTri[2].x = 0;
srcTri[2].y = src->height -1;

これは基本的に、画像の左上の点、右上の点、および左下の点で、行列の開始点となります。この部分は私には理にかなっています。

しかし、dstTri[3]just の値は紛らわしいです。少なくとも、1 つのポイントを変更すると、期待した結果が得られません。

たとえば、次のように使用すると、次のようになりますdstTri[3]

dstTri[0].x = 0;
dstTri[0].y = 0;
dstTri[1].x = src->width - 1;
dstTri[1].y = 0;
dstTri[2].x = 0;
dstTri[2].y = 100;

src ポイントと dst ポイントの唯一の違いは、左下のポイントが 100 ピクセル右に移動することです。直感的には、画像の下の部分を100ピクセル右にずらした方がいい気がしますが、そうではありません。

また、 に使用するのとまったく同じ値をdstTri[3]に使用するsrcTri[3]と、変換によってまったく同じ画像が生成されると思いますが、そうではありません。

明らかに、ここで何が起こっているのか理解できません。srcTri[]では、 からへのマッピングは何をdstTri[]表しているのでしょうか。

4

1 に答える 1

15

アフィン変換の数学的説明は次のとおりです。これは、2D ベクトルに愚かな変換を適用するサイズ 3x3 のマトリックスです: X 軸のスケール、scaleY、回転、傾斜、x 軸と y の変換。これらは 6 つの変換であるため、3x3 マトリックスには 6 つの要素があります。一番下の行は常に [0 0 1] です。なんで?一番下の行は x 軸と y 軸の透視変換を表し、アフィン変換には透視変換が含まれないためです。(パースペクティブ ワーピングを適用する場合は、ホモグラフィを使用します: 3x3 マトリックスも使用します)

アフィン行列に挿入する 6 つの値とそれが行う 6 つの変換との関係は何ですか? この 3x3 行列を次のように見てみましょう

e*Zx*cos(a), -q1*sin(a)  ,  dx,
e*q2*sin(a),     Z y*cos(a),  dy,
0       ,            0  ,   1
  1. dxと
  2. dy 要素は、x 軸と y 軸の平行移動です (画像を上下左右に移動するだけです)。
  3. Zx は、X 軸の画像に適用する相対的なスケール (ズーム) です。
  4. Zy は y 軸について上記と同じです
  5. a は画像の回転角度です。'a' で回転させたい場合は、行列の 4 つの異なる場所に sin()、cos() を挿入する必要があるため、これは注意が必要です。
  6. 「q」はスキュー パラメータです。めったに使用されません。画像が横に歪む原因になります (q1 は y 軸が x 軸に影響し、q2 は x 軸が y 軸に影響します)。
  7. おまけ: 'e' パラメータは実際には変換ではありません。値は 1、-1 です。1 の場合は何も起こりませんが、-1 の場合は画像が水平方向に反転されます。画像を垂直に反転するためにも使用できますが、このタイプの変換はめったに使用されません。

非常に重要な注意!!!!!

上記の説明は数学的なものです。行列に右から列ベクトルを掛けると仮定します。私が覚えている限り、Matlab は逆乗算 (左からの行ベクトル) を使用するため、この行列を転置する必要があります。openCV は通常の乗算​​を使用していると確信していますが、確認する必要があります。平行移動行列のみを入力するだけです (x は 10 ピクセル、y は 1 ずつシフト)。

1,0,10
0,1,1
0,0,1

通常のシフトが表示された場合はすべて問題ありませんが、たわごとが表示された場合は、マトリックスを次のように転置します。

1,0,0
0,1,0
10,1,1
于 2012-05-21T06:27:36.277 に答える