end0tknr's kipple - web写経開発

太宰府天満宮の狛犬って、妙にカワイイ

Pillow for python による Affine変換 (拡大縮小,移動,回転,せん断)

Affine層とSoftmax-with-Loss層の計算グラフとnumpy for python実装 - end0tknr's kipple - web写経開発

上記のentryでは、ニューラルネットワークのアフィン層を使用していますが、 今回は、画像処理のAffine変換。

どうやら、Affine変換とは、ニューラルネットワークでも 画像処理でも、以下のような行列式を指すみたい。

 \large{
\begin{pmatrix} x' \\\ y' \end{pmatrix} =

\begin{pmatrix} a b \\\ c d \end{pmatrix}
\begin{pmatrix} x \\\ y \end{pmatrix} +
\begin{pmatrix} e \\\ f \end{pmatrix}
}

また、上記は、以下のようにも表現できます。

 \large{
\begin{pmatrix} x' \\\ y' \\\ 1 \end{pmatrix} =

\begin{pmatrix} a b e \\\ c d f \\\ 0 0 1 \end{pmatrix}
\begin{pmatrix} x \\\ y \\\ 1 \end{pmatrix}
}

画像の拡大縮小等を行う場合、 上記のa ~ fは以下のようになります。

{ 拡大縮小 \begin{pmatrix} S_x 0 0 \\\ 0 S_y 0 \\\ 0 0 1 \end{pmatrix}}
{ 平行移動 \begin{pmatrix} 0 0 T_x \\\ 0 0 T_y \\\ 0 0 1 \end{pmatrix}}
{ 回  転 \begin{pmatrix} cosθ -sinθ 0 \\\ sinθ cosθ 0\\\ 0  0  1\end{pmatrix}}
{ せん断 \begin{pmatrix} 1 tanθ_x 0 \\\ tanθ_y 1 0 \\\ 0 0 1 \end{pmatrix}}

これをpythonで実装すると、以下の通りです

# coding: utf-8

from PIL import Image
import numpy as np

def main():
    img_file_path = "./marble.png"
    img = Image.open(img_file_path)
    
    # アフィン変換行列
    affine_tuple = (0.5, 0,   0,
                    0,   0.5, 0,
                    0,   0,   1)
    # Image.AFFINE は、Pillow v.9.1から 
    # Image.Transform.AFFINE になっているようです
    # https://pillow.readthedocs.io/en/latest/releasenotes/9.1.0.html
    new_img = img.transform(
        img.size,
        Image.AFFINE,
        #Image.Transform.AFFINE,
        affine_tuple )
    new_img.show()

if __name__ == '__main__':
    main()