PyTorchで画像縮小アルゴリズム
pytorch で area average な画像縮小を試してみる.
概要
画像のサイズを変更する画像補間手法は多々存在する. しかしながら,一般によく知られている bilinear や bicubic,nearest-neighbor を 使って画像縮小をすると,巨大な画像を小さくする場合ではジャギーが目立つ. したがって,綺麗に画像縮小を行いたい場合は area average を用いるのがよい. 本稿では pytorch で画像縮小を行う方法について簡単なコードで見ていく.
area averageとは
area average は, サンプリング点同士の間を等分して得られる領域の平均の画素値を計算するアルゴリズムである. bilinearやbicubic は入力画像中でサンプリング点座標近傍の4点や16点しか見ない. 一方で,area average であればサンプリング点がたとえば100画素ぶん離れていれば 100x100 の領域の平均値を出力画素の画素値とする.
要するに average pooling である. サンプリング点が離れれば離れるほど, bicubic よりも area を使うほうが良い感じになる.
pytorchの画像リサイズ関数
pytorch では画像をリサイズするための torch.nn.functional.interpolate()
が用意されている.
使用できるアルゴリズムは,現時点(ver1.5.1)では
nearest
linear
bilinear
bicubic
trilinear
area
であり,おそらく area
が area average に該当する.
pytorch 最新版documentation
適当に動かして確認する
まずは画像を適当に用意する.3024x3024のデカイ画像を用意した. デカくて載らないので圧縮済みのものを載せておく.
コード
import numpy as np import cv2 import torch import torch.nn.functional as F if __name__ == '__main__': img = cv2.imread('curry.png',cv2.IMREAD_COLOR) # pytorchに持ってくる (1,C,H,W) tensor = torch.from_numpy(img.astype(np.float32)).permute(2,0,1)[None,:,:,:] # area average での縮小 out = F.interpolate(tensor,size=(256,256),mode='area') ndarr = out[0].permute(1,2,0).numpy().astype(np.uint8) cv2.imwrite('out_area.png',ndarr) # bicubic での縮小 out = F.interpolate(tensor,size=(256,256),mode='bicubic',align_corners=False).clamp(0.0,255.0) ndarr = out[0].permute(1,2,0).numpy().astype(np.uint8) cv2.imwrite('out_cubic.png',ndarr)
結果
この写真ではよくわからないかもしれないが, 皿のフチの部分がbicubicはジャギっているのがわかる. 128x128 などもっと低解像度に縮小すればより顕著に現れる.
著作権の関係で載せないが,アニメや漫画の画像であればよりわかりやすくこの現象が見てとれる.
結論
深層学習などで画像を縮小して読み込まなければいけない場合, bicubicなどを使うのではなく area average を使うべきである.