scikit-imageのお勉強 第4回 transformモジュール ~拡大縮小・回転・アフィン変換~
scikit-imageの便利機能の備忘録シリーズ。
これまでの回はコチラ。
第1回 dataモジュールとioモジュール ~画像の入出力~
今回は第4回です。transform
モジュールについてメモしていきます。
transformモジュール
回転などの変換に関するモジュールです。
公式ページ:Module: transform — skimage v0.14.0 docs
よく使いそうな機能は以下の4種類。
リサイズ・リスケール
transform.resize
transform.rescale
回転
transform.rotate
スワール(渦巻き化)
transform.swirl
アフィン変換
transform.AffineTransform
+transform.warp
他に画像ピラミッド、Hough変換(特徴抽出の一種)やradon変換(断層画像の変換)なども利用できます。 この中で、今回は画像ピラミッドのみ取り上げます。
画像ピラミッド
transform.pyramid_reduce
transform.pyramid_expand
transform.pyramid_gaussian
いつも通り、テスト画像をdata
モジュールで読み込んでおきます。
今回、拡大縮小が見やすいようにimage_show
関数をちょっと改変しました。
・code
%matplotlib inline import matplotlib.pyplot as plt from skimage import transform, data def image_show(img): h,w,c = img.shape plt.figure(figsize=[float(w/100),float(h/100)]) plt.title(f'w={w}, h={h}') plt.imshow(img) plt.xticks([]) plt.yticks([]) plt.show() rocket = data.rocket() image_show(rocket)
リサイズ・リスケール
transform.resize
で指定の画像サイズにリサイズできます。
第1引数:画像データ
第2引数:リサイズ後の画像サイズ(タプル)
第3以降の引数:mode, anti_aliasingなど
・code
# 元画像表示 image_show(rocket) # 画像の縮小 # mode='reflect'、anti_aliasing=True にする resize_img = transform.resize(rocket,(200,500),mode='reflect',anti_aliasing=True) image_show(resize_img) # 画像の拡大 # modeはどれでも適用可 resize_img = transform.resize(rocket,(800,800),mode='constant',anti_aliasing=True) image_show(resize_img)
・元画像
・縮小画像
・拡大画像
transform.rescale
は特定の倍率に画像を拡大・縮小するための関数です。
第1引数:画像データ
第2引数:倍率(拡大なら>1、縮小なら<1)
第3以降の引数:mode, anti_aliasingなど
・code
# 元画像表示 image_show(rocket) # 画像の縮小 # mode='reflect'、anti_aliasing=Trueにする # multichannelは明示(True/False) rescale_img = transform.rescale(rocket,0.2,mode='reflect',anti_aliasing=True,multichannel=True) image_show(rescale_img) # 画像の拡大 # modeはどれでも適用可 # multichannelは明示(True/False) rescale_img = transform.rescale(rocket,1.5,mode='constant',anti_aliasing=True,multichannel=True) image_show(rescale_img)
・元画像
・縮小画像
・拡大画像
回転
画像の回転はtransform.rotate
で行います。回転の際にリサイズするかどうかを選べます。
第1引数:画像データ
第2引数:角度(時計回り方向)
第3以降の引数:resizeなど
・code
# 元画像の表示 image_show(rocket) # リサイズなしの回転 rotate_img = transform.rotate(rocket,90,resize=False) image_show(rotate_img) # リサイズありの回転 rotate_img = transform.rotate(rocket,90,resize=True) image_show(rotate_img)
・元画像
・リサイズなしの回転
・リサイズありの回転
スワール(渦巻き化)
画像に渦巻き加工を入れる関数としてtransform.swirl
というものがあります。
第1引数:画像データ
第2以降の引数:mode, strengthなど
strengthを変えることで渦の強さを調節できます。
・code
for i in range(1,11,3): print(f'strength={i}') swirl_img = transform.swirl(rocket,mode='reflect',strength=i) image_show(swirl_img)
・元画像
・strength=1
・strength=4
・strength=7
・strength=10
アフィン変換
アフィン変換をマスターすると拡大縮小・平行移動・反転・回転・剪断変形などなんでもできて便利です。
「アフィン変換とは平行移動と線形変換を組み合わせた変換」のこと。(中略) 具体的には、線形変換(拡大縮小、剪断、回転)、平行移動があり、これらの組み合わせで表現される。
scikit-imageでのアフィン変換のやり方は、ここまで説明してきた変換とは手順が違うので注意が必要です。
1. transform.AffineTransform
クラスのインスタンスを作成
2. transform.warp
で画像に上記インスタンスの効果を適用
それぞれのクラス・関数の引数は以下の通りです。
transform.AffineTransform
の引数
scale:拡大縮小(縦・横のタプルで与える、マイナスで反転)
translation:平行移動(縦・横のタプルで与える)
rotation:回転
shear:剪断変形
反転・回転・剪断変形は画像が画面からはみ出ることが多いので、適宜translation
を組み合わせて使います。
transform.warp
の引数
第1引数:画像データ
第2引数: transform.AffineTransform
クラス等のインスタンス
・code
# 元画像の表示 image_show(rocket) # 拡大縮小のみ at = transform.AffineTransform(scale=(1.2,1.2)) warp_img = transform.warp(rocket,at) image_show(warp_img) # 平行移動のみ at = transform.AffineTransform(translation=(-30,-50)) warp_img = transform.warp(rocket,at) image_show(warp_img) #反転と平行移動 at = transform.AffineTransform(scale=(-1,1),translation=(640, 0)) warp_img = transform.warp(rocket,at) image_show(warp_img) # 回転と平行移動 at = transform.AffineTransform(rotation=0.5,translation=(300,-100)) warp_img = transform.warp(rocket,at) image_show(warp_img) # 剪断変形と拡大縮小、平行移動 at = transform.AffineTransform(shear=1,scale=(1.5,1.5),translation=(30,30)) warp_img = transform.warp(rocket,at) image_show(warp_img)
・元画像
・縮小
・平行移動
・反転と平行移動
・回転と平行移動
・剪断変形と拡大縮小、平行移動
おまけ:画像ピラミッド
画像ピラミッドに関してはOpenCVのTutorialページがわかりやすいです。
画像ピラミッド — OpenCV-Python Tutorials 1 documentation
例えば画像中で何かを探すとき(例えば顔)、画像中にどのような大きさで現れるか分かりません。そのような状況では様々な解像度の画像を用意し、全画像に対して物体検出を試みます。これらの異なる解像度を持つ画像の集合を画像ピラミッド(最大解像度の画像を下に、最小解像度の画像を上に積むとピラミッドのようになるからです)と呼びます。
画像ピラミッドの関数には、transform.pyramid_reduce
、transform.pyramid_expand
やジェネレーターとして機能するtransform.pyramid_gaussian
などがあります。
・code
#pyramidシリーズ image_show(rocket) pyramid_img = transform.pyramid_reduce(rocket,downscale=5,multichannel=True) image_show(pyramid_img) pyramid_img = transform.pyramid_expand(rocket,upscale=1.5,multichannel=True) image_show(pyramid_img)
・元画像
・transform.pyramid_reduce
・transform.pyramid_expand
これらは普通の拡大縮小とあまり変わらないですね。
次のようにジェネレーターを使うと画像ピラミッドっぽさが出ます。
・code
pyramid_gen = transform.pyramid_gaussian(rocket,downscale=2,multichannel=True) for i in range(5): pyramid_img = next(pyramid_gen) image_show(pyramid_img)
・1回目
・2回目
・3回目
・4回目
・5回目
今回はここまで。
2018/9/10訂正
アフィン変換の説明のところで引数に誤植があったため修正しました。