A.I
Image Augmentation 본문
다양한 Image Augmentation 방법¶
- Flipping¶
- 이미지를 대칭하는 기술로 좌우,상하로 이미지를 반전시키는 방법입니다.
- 물체 탐지(detection), 세그멘테이션(segmentation) 문제 등 정확한 정답 영역이 존재하는 문제는 라벨도 같이 좌우 반전을 해주어야 합니다.
- Gray scale¶
- 3가지 채널(channel)을 가진 RGB 이미지를 1개의 채널로 바꿔줍니다.
- RGB 각각의 채널마다 가중치(weight)를 주어 가중합(weighted sum)을 하였습니다. 사용된 가중치의 경우 합이 1이 됨을 알 수 있습니다.
- Saturation¶
- RGB 이미지를 HSV(Hue(색조), Saturation(채도), Value(명도)의 3가지 성분으로 색을 표현) 이미지로 변경
- S(saturation) 채널에 오프셋(offset)을 적용, 조금 더 이미지를 선명하게 만들어 줍니다.
- 그다음 다시 우리가 사용하는 RGB 색상 모델로 변경을 해줍니다.
- Brightness¶
- 밝기를 조절할 수도 있습니다. RGB에서 (255,255,255)는 흰색을, (0,0,0)은 검은색을 의미합니다.
- RGB 채널에서 값을 더해주면 밝아지고, 빼주면 어두워집니다. 이를 통해서 Brightness를 변경할 수 있습니다.
- Rotation¶
- 이미지의 각도를 변환해 줍니다. 90도의 경우 직사각형 형태가 유지되기 때문에 이미지의 크기만 조절해 주면 바로 사용할 수 있습니다.
- 90도 단위로 돌리지 않는 경우 직사각형 형태에서 기존 이미지로 채우지 못하는 영역을 어떻게 처리해야 할지 유의해야 합니다.
- Center Crop¶
- 이미지의 중앙을 기준으로 확대하는 방법입니다.
- 너무 작게 center crop을 할 경우 본래 가진 라벨과 맞지 않게 되는 상황이 발생할 수 있으니 주의가 필요합니다. 예를 들어 고양이 라벨의 이미지를 확대해 한 장 더 만들어내려면, 이미지 내에 고양이의 형상을 유지해야 하고 털만 보이는 이미지를 만들어서는 안 됩니다.
그 외에도 Gaussian noise, Contrast change, Sharpen, Affine transformation, Padding, Blurring등이 있습니다.
텐서플로우를 사용한 Image Augmentation (1) Flip¶
- pip install pillow
- wget https://aiffelstaticprd.blob.core.windows.net/media/documents/mycat.jpg
- mv mycat.jpg ~/aiffel/data_augmentation/images
In [1]:
import tensorflow as tf
from PIL import Image
import matplotlib.pyplot as plt
import os
sample_img_path = os.getenv('HOME')+'/aiffel/data_augmentation/images/mycat.jpg'
sample_img_path
Out[1]:
'/home/ssac24/aiffel/data_augmentation/images/mycat.jpg'
In [4]:
image = Image.open(sample_img_path).resize((600, 400)) # 이미지에 따라 숫자를 바꾸어 보세요.
image_tensor = tf.keras.preprocessing.image.img_to_array(image)
image
Out[4]:
Flip 해보기¶
Flip은 flip_left_right와 flip_up_down 두 가지로 좌우와 상하 반전이 있습니다.
In [5]:
flip_lr_tensor = tf.image.flip_left_right(image_tensor)
flip_ud_tensor = tf.image.flip_up_down(image_tensor)
flip_lr_image = tf.keras.preprocessing.image.array_to_img(flip_lr_tensor)
flip_ud_image = tf.keras.preprocessing.image.array_to_img(flip_ud_tensor)
plt.figure(figsize=(15, 15))
plt.subplot(1,3,1)
plt.title('Original image')
plt.imshow(image)
plt.subplot(1,3,2)
plt.title('flip_left_right')
plt.imshow(flip_lr_image)
plt.subplot(1,3,3)
plt.title('flip_up_down')
plt.imshow(flip_ud_image)
Out[5]:
<matplotlib.image.AxesImage at 0x7f81a80363d0>
In [7]:
plt.figure(figsize=(12, 16))
row = 4
for i in range(row):
flip_lr_tensor = tf.image.random_flip_left_right(image_tensor)
flip_ud_tensor = tf.image.random_flip_up_down(image_tensor)
flip_lr_image = tf.keras.preprocessing.image.array_to_img(flip_lr_tensor)
flip_ud_image = tf.keras.preprocessing.image.array_to_img(flip_ud_tensor)
plt.subplot(4,3,i*3+1)
plt.title('Original image')
plt.imshow(image)
plt.subplot(4,3,i*3+2)
plt.title('flip_left_right')
plt.imshow(flip_lr_image)
plt.subplot(4,3,i*3+3)
plt.title('flip_up_down')
plt.imshow(flip_ud_image)
텐서플로우를 사용한 Image Augmentation (2) Center Crop¶
central_fraction
은 얼마나 확대를 할지를 조절하는 매개변수입니다. 1.0은 원본이미지와 동일합니다. 중요한 점은 central_fraction의 범위를 원본이 인식되는 정도 내에서 랜덤하게 조절되도록 해야합니다.
In [8]:
plt.figure(figsize=(12, 15))
central_fractions = [1.0, 0.75, 0.5, 0.25, 0.1]
col = len(central_fractions)
for i, frac in enumerate(central_fractions):
cropped_tensor = tf.image.central_crop(image_tensor, frac)
cropped_img = tf.keras.preprocessing.image.array_to_img(cropped_tensor)
plt.subplot(1,col+1,i+1)
plt.title(f'Center crop: {frac}')
plt.imshow(cropped_img)
In [9]:
# tf.random.uniform을 사용해서 central_fraction 매개변수에 전달할 값을 만들고
# 이를 사용해 cropped_tensor를 만들어내는 random_central_crop() 함수
# normal distribution의 경우 mean, std를 통해서 분포를 조절할 수 있습니다.
def random_central_crop(image_tensor, range=(0, 1)):
central_fraction = tf.random.uniform([1], minval=range[0], maxval=range[1], dtype=tf.float32)
cropped_tensor = tf.image.central_crop(image_tensor, central_fraction)
return cropped_tensor
In [13]:
plt.figure(figsize=(12, 15))
col = 5
for i, frac in enumerate(central_fractions):
cropped_tensor =random_central_crop(image_tensor)
cropped_img = tf.keras.preprocessing.image.array_to_img(cropped_tensor)
plt.subplot(1,col+1,i+1)
plt.imshow(cropped_img)
텐서플로우를 사용한 Image Augmentation (3) random_crop¶
In [14]:
plt.figure(figsize=(15, 15))
random_crop_tensor = tf.image.random_crop(image_tensor, size = [200, 200, 3])
random_crop_image = tf.keras.preprocessing.image.array_to_img(random_crop_tensor)
plt.subplot(1,3,1)
plt.title('Original image')
plt.imshow(image)
plt.subplot(1,3,2)
plt.title('random_crop_image')
plt.imshow(random_crop_image)
Out[14]:
<matplotlib.image.AxesImage at 0x7f817c25fe90>
In [23]:
plt.figure(figsize=(12, 15))
col = 5
for i in range(5):
random_crop_tensor = tf.image.random_crop(image_tensor,[200,200,3])
random_crop_image = tf.keras.preprocessing.image.array_to_img(random_crop_tensor)
plt.subplot(1,col+1,i+1)
plt.imshow(random_crop_image)
텐서플로우를 사용한 Image Augmentation (3) random_brightness¶
In [20]:
plt.figure(figsize=(15, 15))
random_brightness_tensor= tf.image.random_brightness(image_tensor,max_delta = 200, seed=None)
# 이미지 텐서값의 범위가 0~255안의 값으로 이루어지게 범위조정
random_brightness_tensor = tf.clip_by_value(random_brightness_tensor, 0, 255)
brightness_image = tf.keras.preprocessing.image.array_to_img(random_brightness_tensor)
plt.subplot(1,3,1)
plt.title('Original image')
plt.imshow(image)
plt.subplot(1,3,2)
plt.title('brightness_image')
plt.imshow(brightness_image)
Out[20]:
<matplotlib.image.AxesImage at 0x7f816c7c9810>
In [21]:
plt.figure(figsize=(15, 15))
col = 5
for i in range(5):
random_bright_tensor = tf.image.random_brightness(image_tensor, max_delta=128)
random_bright_tensor = tf.clip_by_value(random_bright_tensor, 0, 255)
random_bright_image = tf.keras.preprocessing.image.array_to_img(random_bright_tensor)
plt.subplot(1,col+1,i+1)
plt.imshow(random_bright_image)
In [25]:
import numpy as np
import imgaug.augmenters as iaa
# imgaug에서는 배열을 이미지의 기본 형태로 사용하기때문에 PIL Image 데이터형을 넘파이(numpy) 배열로 변환하여 사용
image_arr = np.array(image)
augmentation 기법¶
- iaa.Affine()¶
- imgaug.augmenters의 Affine()은 아핀 변환(Affine transform)을 이미지에 적용합니다. 2D 변환의 일종인 아핀 변환은 이미지의 스케일(scale)을 조절하거나 평행이동, 또는 회전 등의 변환을 줄 수 있습니다.
- 2D 변환 (Transformations)
In [26]:
images = [image_arr, image_arr, image_arr, image_arr]
rotate = iaa.Affine(rotate=(-25, 25))
images_aug = rotate(images=images)
plt.figure(figsize=(13,13))
plt.imshow(np.hstack(images_aug))
Out[26]:
<matplotlib.image.AxesImage at 0x7f811c795590>
- iaa.Crop()¶
- Crop 하려는 원본 이미지의 비율을 매개변수로 사용하여 이미지를 생성합니다.
In [29]:
images = [image_arr, image_arr, image_arr, image_arr]
crop = iaa.Crop(percent=(0, 0.3))
images_aug = crop(images=images)
plt.figure(figsize=(13,13))
plt.imshow(np.hstack(images_aug))
Out[29]:
<matplotlib.image.AxesImage at 0x7f811c64ea90>
- iaa.Sequential()¶
- imgaug에서는 iaa.Sequential를 사용해서 여러 가지의 augmentation 기법을 순차적으로 적용할 수 있습니다.
In [30]:
# rotate와 crop의 조합
images = [image_arr, image_arr, image_arr, image_arr]
rotate_crop = iaa.Sequential([
iaa.Affine(rotate=(-25, 25)),
iaa.Crop(percent=(0, 0.2))
])
images_aug = rotate_crop(images=images)
plt.figure(figsize=(13,13))
plt.imshow(np.hstack(images_aug))
Out[30]:
<matplotlib.image.AxesImage at 0x7f811c5e7b50>
random_order¶
- random_order는 random으로 기법들의 순서를 바꾸어 사용할 수 있도록 지원
In [33]:
images = [image_arr, image_arr, image_arr, image_arr]
rotate_crop = iaa.Sequential([
iaa.Crop(percent=(0, 0.2)),
iaa.Affine(rotate=(-25, 25))
], random_order=True)
images_aug = rotate_crop(images=images)
plt.figure(figsize=(13,13))
plt.imshow(np.hstack(images_aug))
Out[33]:
<matplotlib.image.AxesImage at 0x7f811c4b20d0>
OneOf¶
- 색상에 변화를 줄 때 여러 변환이 불필요한 경우 선택지 중 하나의 기법만 적용되도록 할 수 있습니다.
In [34]:
images = [image_arr, image_arr, image_arr, image_arr]
seq = iaa.OneOf([
iaa.Grayscale(alpha=(0.0, 1.0)),
iaa.AddToSaturation((-50, 50))
])
images_aug = seq(images=images)
plt.figure(figsize=(13,13))
plt.imshow(np.hstack(images_aug))
Out[34]:
<matplotlib.image.AxesImage at 0x7f811c426810>
SomeTimes¶
- 확률에 따라 차등 적용할 수 있는 기법
In [42]:
images = [image_arr, image_arr, image_arr, image_arr]
seq = iaa.Sequential([
iaa.Sometimes(
0.6,
iaa.AddToSaturation((-50, 50))
),
iaa.Sometimes(
0.2,
iaa.Grayscale(alpha=(0.0, 1.0))
)
])
images_aug = seq(images=images)
plt.figure(figsize=(13,13))
plt.imshow(np.hstack(images_aug))
Out[42]:
<matplotlib.image.AxesImage at 0x7f811c071a10>
조합하여 1024장이 넘는 경우의 수 만들기¶
In [ ]:
seq = iaa.Sequential([
iaa.OneOf([
iaa.Grayscale(alpha=(0.0, 1.0)),
iaa.Sometimes(
0.5,
iaa.AddToSaturation((-50, 50))
)
]),
iaa.Sequential([
iaa.Crop(percent=(0, 0.2)),
iaa.Affine(rotate=(-25, 25)),
], random_order=True)
])
plt.figure(figsize=(10, 40))
for i in range(20):
images = [image_arr, image_arr, image_arr, image_arr, image_arr]
images_aug = seq(images=images)
plt.subplot(20,1,i+1)
plt.imshow(np.hstack(images_aug))
plt.show()
'Going Deeper' 카테고리의 다른 글
Segmentation (0) | 2021.04.15 |
---|---|
RetinaNet으로 자율주행 시스템 만들기 (0) | 2021.04.13 |
Object detection (0) | 2021.04.12 |
Data Augmentation (0) | 2021.04.12 |
GAN을 이용한 augmentation 기법 논문 (0) | 2021.04.08 |