[E検定]主な画像データの拡張手法(Data Augmentation)

機械学習でよく使われる主な画像データの拡張手法について紹介します。E検定でも出題範囲になっています。pytonで実装方法に関しても紹介します。拡張手法は以下があります。

概要

機械学習はよいモデルを作成するためによいデータをいかにあつめるかが重要になります。データを集める方法としてもともとある画像から新しい画像を作成する手法があります。ここでは以下の画像拡張方法についての概要とpythonでの実装方法を説明します。

● horizontal flip 画像を水平方向に回転させる
● vertical flip 画像を垂直方向に回転させる
● random crop 一枚の画像から指定された大きさでランダムに切り出す
● scale augmentation 画像のスケールを変化させてから切り出しを行う
● random rotation 画像をランダムに回転させる
● cutout 画像の一部にマスクをかける
● random erasing 画像内の箇所をランダムに選び画像を消去する
● elastic distortion 画像をいくつかの領域に細分化しそれぞれランダムに移動させる

サンプルの画像は以下を使用します。

拡張手法

horizontal flip

画像を水平方向に回転させます。以下で実装方法を紹介します。

from PIL import Imageimport numpy as npimport matplotlib.pyplot as pltif __name__ == '__main__': img = np.asarray(Image.open("C:/minecraft.jpg"), dtype=np.uint8) img = img[:, ::-1, :] plt.imshow(img) plt.savefig("minecraft_revised.jpg") pass

以下が実行結果です。

vertical flip

画像を垂直方向に回転させます。以下で実装方法を紹介します。

from PIL import Imageimport numpy as npimport matplotlib.pyplot as pltif __name__ == '__main__': img = np.asarray(Image.open("C:/minecraft.jpg"), dtype=np.uint8) img = img[::-1, :, :] plt.imshow(img) plt.savefig("minecraft_vertical_revised.jpg") pass

以下が実行結果です。

random crop

一枚の画像から指定された大きさでランダムに切り出します。以下で実装方法を紹介します。

from PIL import Imageimport numpy as npimport matplotlib.pyplot as pltdef random_crop(image, crop_size=(400, 400)): h, w, _ = image.shape top = np.random.randint(0, h - crop_size[0]) left = np.random.randint(0, w - crop_size[1]) bottom = top + crop_size[0] right = left + crop_size[1] image = image[top:bottom, left:right, :] return imageif __name__ == '__main__': img = np.asarray(Image.open("C:/minecraft.jpg"), dtype=np.uint8) img = random_crop(img) plt.imshow(img) plt.savefig("minecraft_random_crop_revised.jpg") pass

以下が実行結果です。

scale augmentation

画像のスケールを変化させてから切り出しを行います。以下で実装方法を紹介します。

from PIL import Imagefrom scipy.ndimage.interpolation import rotateimport numpy as npimport matplotlib.pyplot as pltdef random_crop(image, crop_size=(400, 400)): h, w, _ = image.shape top = np.random.randint(0, h - crop_size[0]) left = np.random.randint(0, w - crop_size[1]) bottom = top + crop_size[0] right = left + crop_size[1] image = image[top:bottom, left:right, :] return imagedef scale_augmentation(image, scale_range=(256, 400), crop_size=224): scale_size = np.random.randint(*scale_range) image = np.array(Image.fromarray(image).resize((scale_range), resample=2)) image = random_crop(image, (crop_size, crop_size)) return imageif __name__ == '__main__': img = np.asarray(Image.open("C:/minecraft.jpg"), dtype=np.uint8) img = scale_augmentation(img) plt.imshow(img) plt.savefig("minecraft_scale_augmentation.jpg") pass

以下が実行結果です。

random rotation

画像をランダムに回転させます。以下で実装方法を紹介しています。

from scipy.ndimage.interpolation import rotatefrom PIL import Imagefrom scipy.ndimage.interpolation import rotateimport numpy as npimport matplotlib.pyplot as pltdef random_rotation(image, angle_range=(0, 180)): h, w, _ = image.shape angle = np.random.randint(*angle_range) image = rotate(image, angle) image = np.array(Image.fromarray(image).resize((h, w), resample=2)) return imageif __name__ == '__main__': img = np.asarray(Image.open("C:/minecraft.jpg"), dtype=np.uint8) img = random_rotation(img) plt.imshow(img) plt.savefig("minecraft_random_rotation.jpg") pass

以下が実行結果です。

cutout

画像の一部にマスクをかけます。以下で実装方法を紹介しています。

from PIL import Imageimport numpy as npimport matplotlib.pyplot as pltdef cutout(image_origin, mask_size): image = np.copy(image_origin) mask_value = image.mean() h, w, _ = image.shape top = np.random.randint(0 - mask_size // 2, h - mask_size) left = np.random.randint(0 - mask_size // 2, w - mask_size) bottom = top + mask_size right = left + mask_size if top < 0:  top = 0 if left < 0:  left = 0 image[top:bottom, left:right, :].fill(mask_value) return imageif __name__ == '__main__': img = np.asarray(Image.open("C:/minecraft.jpg"), dtype=np.uint8) img = cutout(img,300) plt.imshow(img) plt.savefig("minecraft_random_cutout.jpg") pass

以下が実行結果です。

random erasing

画像内の箇所をランダムに選び画像を消去する

from PIL import Imagefrom scipy.ndimage.interpolation import rotateimport numpy as npimport matplotlib.pyplot as pltdef random_erasing(img, p=0.5, sl=0.02, sh=0.4, r1=0.3, r2=3.3): target_img = img.copy() if p < np.random.rand():  return target_img H, W, _ = target_img.shape S = H * W while True:  Se = np.random.uniform(sl, sh) * S  re = np.random.uniform(r1, r2)  He = int(np.sqrt(Se * re))  We = int(np.sqrt(Se / re))  xe = np.random.randint(0, W)  ye = np.random.randint(0, H)  if xe + We <= W and ye + He <= H:break mask = np.random.randint(0, 255, (He, We, 3)) target_img[ye:ye + He, xe:xe + We, :] = mask return target_imgif __name__ == '__main__': img = np.asarray(Image.open("C:/minecraft.jpg"), dtype=np.uint8) img = random_erasing(img) plt.imshow(img) plt.savefig("minecraft_random_erasing.jpg") pass

以下が実行結果です。

elastic distortion

画像をいくつかの領域に細分化しそれぞれランダムに移動させます。

まとめ

機械学習でよく使われる主な画像データの拡張手法について紹介しました。

NO IMAGE
最新情報をチェックしよう!