OpenCV 5.0.0
Open Source Computer Vision
読み込み中...
検索中...
見つかりません
🤖 AIによる機械翻訳(非公式) — これは OpenCV 5.0.0 公式リファレンス(英語)を AI (Claude) で自動翻訳したものです。訳に誤りを含む場合があります。正確な情報は 公式英語版(原文) を参照してください。
アフィン変換

前のチュートリアル: リマッピング
次のチュートリアル: ヒストグラム均等化

原著者Ana Huamán
互換性OpenCV >= 3.0

目標

このチュートリアルでは、以下の方法を学ぶ:

  • OpenCVの関数 cv::warpAffine を使って、単純なリマッピング処理を実装する。
  • OpenCVの関数 cv::getRotationMatrix2D を使って \(2 \times 3\) の回転行列を取得する

理論

アフィン変換とは何か?

  1. 行列の乗算(線形変換)に続いて ベクトルの加算(平行移動)という形で表現できる変換。
  2. 上記から、アフィン変換は次のものを表現するために使用できる:

    1. 回転(線形変換)
    2. 平行移動(ベクトルの加算)
    3. 拡大縮小操作(線形変換)

    本質的に、アフィン変換は2つの画像間の 関係 を表すことがわかる。

  3. アフィン変換を表現する一般的な方法は、\(2 \times 3\) 行列を使用することである。

    \[ A = \begin{bmatrix} a_{00} & a_{01} \\ a_{10} & a_{11} \end{bmatrix}_{2 \times 2} B = \begin{bmatrix} b_{00} \\ b_{10} \end{bmatrix}_{2 \times 1} \]

    \[ M = \begin{bmatrix} A & B \end{bmatrix} = \begin{bmatrix} a_{00} & a_{01} & b_{00} \\ a_{10} & a_{11} & b_{10} \end{bmatrix}_{2 \times 3} \]

    \(A\) と \(B\) を用いて2Dベクトル \(X = \begin{bmatrix}x \\ y\end{bmatrix}\) を変換したい場合を考えると、次のようにして同じことができる:

    \(T = A \cdot \begin{bmatrix}x \\ y\end{bmatrix} + B\) または \(T = M \cdot [x, y, 1]^{T}\)

    \[T = \begin{bmatrix} a_{00}x + a_{01}y + b_{00} \\ a_{10}x + a_{11}y + b_{10} \end{bmatrix}\]

アフィン変換はどのように求めるか?

  1. We mentioned that an Affine Transformation is basically a relation between two images. The information about this relation can come, roughly, in two ways:
    1. \(X\) と \(T\) の両方がわかっており、それらが関係していることもわかっている。したがって、我々の課題は \(M\) を求めることである。
    2. \(M\) と \(X\) がわかっている。\(T\) を得るには \(T = M \cdot X\) を適用するだけでよい。\(M\) に関する情報は明示的(すなわち2×3行列を持っている)である場合もあれば、点同士の幾何学的な関係として与えられる場合もある。
  2. これをよりわかりやすく説明しよう(b)。\(M\) は2つの画像を関係づけるので、両方の画像において3つの点を関係づける最も単純なケースを分析できる。下の図を見てほしい:

点1、2、3(画像1で三角形を形成している)は画像2に写像され、依然として三角形を形成しているが、今や著しく変化している。これら3つの点(好きなように選んでよい)でアフィン変換を求めれば、見つかったこの関係を画像内のすべてのピクセルに適用できる。

コード

  • What does this program do?
    • 画像を読み込む
    • 画像にアフィン変換を適用する。この変換は3点の関係から得られる。その目的のために関数 cv::warpAffine を使用する。
    • 変換された画像に回転を適用する。この回転は画像の中心を基準とする。
    • ユーザーがプログラムを終了するまで待機する。

解説

  • 画像を読み込む。

  • アフィン変換: 上の行で説明したとおり、アフィン変換の関係式を導くには3点からなる2組の点が必要である。次を見てほしい:

    これらの点を描画してみると、点がどのように変化するかをより理解しやすくなる。それらの位置は、(理論セクションの)例示図に描かれているものとおおよそ同じである。3点で定義される三角形のサイズと向きが変化することに気づくだろう。

  • 両方の点の組がそろったので、OpenCVの関数 cv::getAffineTransform を使ってアフィン変換を計算する:

    出力として \(2 \times 3\) の行列が得られる(この場合は warp_mat

  • 次に、求めたアフィン変換を src 画像に適用する

    引数は次のとおり:

    • src: 入力画像
    • warp_dst: 出力画像
    • warp_mat: アフィン変換
    • warp_dst.size(): 出力画像の希望サイズ

    最初の変換画像が得られた。これは後ほど表示する。その前に、画像を回転させたい...

  • 回転: 画像を回転させるには、次の2つを知る必要がある:

    1. 画像を回転させる中心
    2. 回転させる角度。OpenCVでは正の角度は反時計回りである
    3. 省略可能: スケール係数

    これらのパラメータは次のスニペットで定義する:

  • OpenCVの関数 cv::getRotationMatrix2D で回転行列を生成する。これは \(2 \times 3\) の行列(この場合は rot_mat)を返す。

  • 求めた回転を、前の変換の出力に対して適用する:

  • 最後に、結果を2つのウィンドウに表示し、念のため元画像も表示する:

  • あとはユーザーがプログラムを終了するまで待つだけである

結果

  • 上記のコードをコンパイルした後、引数として画像のパスを与えることができる。例えば次のような画像の場合:

最初のアフィン変換を適用すると、次が得られる:

そして最後に、負の回転(負は時計回りを意味することを思い出してほしい)とスケール係数を適用すると、次が得られる: