Python

【OpenCV】画像の平行移動・回転処理(アフィン変換)

ここでは、アフィン変換についてまとめています。

 

アフィン変換とは?

Wikipedia では、以下のように説明されています。

アフィン変換とは、線型変換(回転、拡大縮小、剪断(せん断))と平行移動の組み合わせである。
いくつかの線型変換の組合せは一つの線型変換として得られる。

なんのこっちゃ・・・って感じですよね(笑)
分かり易くするために、アフィン変換の簡単な例を以下の図に示します。

アフィン変換の例

画像の拡大縮小、回転、平行移動などを「行列」を使って変換することをアフィン変換と呼びます。

x,y座標の2次元データをアフィン変換するには、変換前の座標を(x, y)、変換後の座標を(x', y')とすると、
回転や剪断変形用の 2行2列の行列と、平行移動用に 2行1列の行列を使って、次の式で表現されます。

アフィン変換の式

この式は行列の項とベクトルの項に分かれていますが、線形変換を行列だけにまとめて表現することもできます。
拡大縮小、回転、剪断変形、平行移動を1つの3x3の行列にまとめると次のようになります。

同次座標系

この表現を同次座標系と言います。

同次座標系の3行目は無駄なようにも見えるのですが、この意味の無いような1行を追加する事で、
平行移動も同じ行列の積で表現できます。
また、逆行列を使う事で、アフィン変換後の座標からアフィン変換前の座標も求める事ができるようになります。

OpenCV では、この変換行列を定義してアフィン変換を行います

それでは実際に Python を使ってアフィン変換を行ってみましょう。
ここでは最も簡単な画像の平行移動と回転を紹介いたします。

 

OpenCV でアフィン変換:平行移動

OpenCV でアフィン変換の平行移動を行う場合は、
warpAffine(<元画像データ>, <変換行列>, <サイズ>) 関数を使用します。

元画像データは、これまで通りの numpy 配列で指定し、
変換行列は同次座標系を使用します。今回は平行移動ですので、txty を指定します。

  • 1~2行目:必要なパッケージを読み込みます
  • 4行目:元画像を読み込んでいます
  • 5行目:元画像のサイズ(高さ、幅)を取得しています
  • 6行目:平行移動させる画素数を指定しています。ここでは x軸で30画素、y軸で30画素移動させます
  • 8行目:同次座標系の行列を定義します。今回は回転させないので、a,d=1、b,c=0 とします
  • 9行目:OpenCV の warpAffine() を使って平行移動させます
  • 11~13行目:平行移動した画像を表示させます
左側:アフィン変換前の元画像 / 右側:アフィン変換(平行移動)後の画像

左側:アフィン変換前の元画像 / 右側:アフィン変換(平行移動)後の画像

ポイント

同次座標系の行列(マトリクス)は、numpy を使って作成します。

SANACHAN
SANACHAN
OpenCVを使って、平行移動の画像処理が行えました。

参考

画像の表示(11~13行目)については、「画像の表示と保存」にまとめています。

 

OpenCV でアフィン変換:回転

次に、OpenCV を使って画像を回転させる方法を紹介いたします。
回転を行う場合も warpAffine() 関数を使いますが、与える行列の作成に
getRotationMatrix2D(<中心座標>, <回転角度>, <スケール>) を使用します。

  •  1~5行目は、平行移動の説明と同じです
  • 7行目:getRotationMatrix2D() を使って、回転用の行列を生成します
    中心座標は画像の幅・高さの半分、回転角度は40度、スケールは 1 (変更なし)を指定
  • 8行目以降も、平行移動の説明と同じです
左側:元画像 、右側:アフィン変換(回転)後の画像

左側:元画像 、右側:アフィン変換(回転)後の画像

ポイント

回転角度を正の数で指定した場合、「反時計回り」の回転となります。

 

まとめ

OpenCV を使ってアフィン変換を行うには、以下の2ステップで完結します。

  1. 同次座標系で使用する行列を作成
  2. warpAffine() 関数に元画像データと行列を引数に渡して呼出す

 

こちらの記事もよく読まれています

  • この記事を書いた人
  • 最新記事
SANACHAN

SANACHAN

「生涯一エンジニア」を掲げ、大手グローバル企業でSE/PGとして8年勤め、キャリアアップ転職した現役のエンジニアです。世にあるメジャーな全プログラム言語(コボル除く)を自由に扱えます。一児の父。自分のため、家族のため、日々勉強してます。システムエンジニア、プログラミングに関する情報を蓄積している雑記帳です。

-Python
-, ,