ほとんどの畳み込みニューラルネットワーク(CNN)を使用した深層学習アーキテクチャは、正方形の画像を入力画像としている。このため、正方形でない画像が入力されたとき、次のような処理を施して、正方形に変更しておく必要がある。
- 画像の長辺と短辺を指定したサイズ(例:299×299)になるように拡大縮小する。このとき、長辺と短辺の縮尺率が異なるので、画像中のオブジェクトの縦横の比率が変化する。オブジェクトの比率が画像判別に重要な場合は、この方法が不適である。
- 画像の短辺が長辺と同じ長さになるように延長し、延長して得られた空白領域を黒などの色で塗りつぶす。あるいは、空白領域に、他の写真の一部を貼り付けるなどで対応することもできる。
- 画像の短辺に合わせて、長辺ではみ出している部分を切り落とす。この場合、画像判別に重要な領域が半分になったり、切り出した正方形に含まれなかったりする場合が起こり得る。
画像を正方形に拡大縮小する方法
画像の長辺と短辺の比率を考慮せずに、強制的に指定されたサイズの正方形に拡大縮小するには、特別な前処理を行う必要がない。PyTorch や Keras などのフレームワークではすでにこのような関数が用意されている。また、画像処理でよく使われている OpenCV を使用して拡大縮小する場合は、resize
メソッドを使用して、サイズを変更する。
import cv2
img = cv2.imread('sample.jpg')
img = cv2.resize(img, dsize=(299, 299))
短辺を長辺に揃える方法
次のサンプルコードは、入力画像の短辺と長辺の差を計算して、画像がなるべく真ん中に配置されるように、短辺を上下あるいは左右を延長する。短辺の延長によってできた空白領域を黒 (0, 0, 0)
一色で塗りつぶしている。
import cv2
def preprocess(img):
h, w, c = img.shape
longest_edge = max(h, w)
top = 0
bottom = 0
left = 0
right = 0
if h < longest_edge:
diff_h = longest_edge - h
top = diff_h // 2
bottom = diff_h - top
elif w < longest_edge:
diff_w = longest_edge - w
left = diff_w // 2
right = diff_w - left
else:
pass
img = cv2.copyMakeBorder(img, top, bottom, left, right,
cv2.BORDER_CONSTANT, value=[0, 0, 0])
return img
img = cv2.imread('sample.jpg')
img = preprocess(img)
img = cv2.resize(img, dsize=(299, 299))
処理前 | 処理後 |
---|---|
ここでは、短辺を長辺に合わせて延長してできた領域を黒で塗りつぶした。しかし、この場合、機械は上下または左右に生じた黒の領域に情報が含まれていないと簡単にわかり、学習効果が薄いと考えられる。そのため、このような領域に一色で塗りつぶすのではなく、一色にノイズを加えたり、ほかの写真の一部をここに埋め込んだりすることもある。
画像の短辺に合わせて正方形を切り出す方法
次のサンプルコードは、画像の長辺の長さが短編の長さと同じなるように、余分な領域を切り落とす例である。この例では、画像の中央から左右あるいは上下にはみ出している部分を切り落としている。
import cv2
def crop_squre(img):
h, w, c = img.shape
x = w if h > w else h
y = x
top = int((h - y) / 2)
bottom = top + y
left = int((w - x) / 2)
right = left + x
img = img[top:bottom, left:right]
return img
img = cv2.imread('sample.jpg')
img = crop_square(img)
#img = cv2.resize(img, dsize=(299, 299))
処理前 | 処理後 |
---|---|