본문 바로가기

Data Science/ML & DL

Image Augmentation | 1. 이미지에 효과를 주어 CNN small datasets의 데이터를 늘려보자

Data 양이 많지 않아 딥러닝 모델의 학습에 어려움이 있을 때 사용 가능한 방법

1) Image augmentation 활용
        - Image에 다양한 효과를 주어 데이터양을 늘린다.

2) Pre-trained network의 활용한 Transfer learning (전이학습)
        - 매우 큰 데이터셋으로 미리 Training한 모델을 이용해 모델을 정의한다.
        - 성능이 좋은모델을 다량의 데이터로 학습시킨 모델을 사용하므로 적은 데이터에도 좋은 성능을 낼 수있다.


⭐Summary

dataset객체에  1.전처리 함수  2. transform함수를 적용함으로써 데이터를 처리할 수 있다.
- transforms.Compose([함수, 함수, 함수, ...])형식으로 적용할 함수(image augmentation함수)를  정의하고 적용하면, dataset이 이미지를 하나씩 불러와 적용할 수 있다.
- tranforms.RandomApply ([함수, 함수, 함수, ...])는 설정할 함수안에서 임의로 몇개의 함수가 선택되어 실행되는것이고,  tranforms.choice([함수, 함수, 함수, ...])는 하나의 함수가 실행되는 것이다.

- torch, torchvision - transform 라이브러리 ,cv2,plt불러오기

- 이미지 출력 함수 정의
def  image_show(img_path, transforms):
       for i in range(2, 10): # plot의 index (2번째~9번째 axis에 이미지를 출력)
       result_img = transforms (img) # 원본이미지를 transform함수에 넣어서 변경된 결과를 받는다.
       plt.subplot(3, 3, i) # 변환한 이미지 plot에 할당
       plt.imshow(result_img.permute(1, 2, 0))

- transforms.Compose([변환함수1, 변환함수2, …])  변환함수들에 순서대로 이미지를 넣어서 변환 => 변환 파이프라인을 구성 
- transforms.ToTensor()를 변환함수 나열 전 맨 앞에 위치해야함.

- 변환함수
반전+회전+이동
RandomHorizontalFlip
RandomVerticalFlip
Ramdomrotation
RandomAffine

블러/선명도
GaussianBlur
RandomAdjustSharpness

색채/그레이/색반전
ColorJitter
RandomGrayscale
RandomInver

크롭(자르기)
CenterCrop 중앙크롭
RandomCrop 랜덤크롭
andomResizedCrop 랜덤크롭+ 종횡비 resize

이미지부분삭제-가리기
RandomErasing()

 


Image augmentation

언제 사용? 데이터 양이 많지 않을 때

  • 데이터 양이 많지 않아 딥러닝 모델의 학습 어려움 → 이미지에 다양한 효과를 주어 데이터양을 늘린다.
  • train dataset은 전체 대상 이미지들을 샘플링 → 모든 형태를 다 가지고 잇는 것이 X.
  • Data augmentation은 train set의 이미지에 다양한 효과를 줘서 실제 데이터셋과의 간격을 줄
  • 영상데이터의 경우 :영상데이터의 색변경 , 이미지잘라내기, 회전시키기, 명암변경

효과 ? 모델의 Overfitting을 개선

 

 

예제

1. 라이브러리를 불러온다.

import torch
from torchvision import transforms

import cv2
import matplotlib.pyplot as plt

 

2. 이미지 출력함수를 정의한다

파라미터로 이미지 경로와 transforms(변환 함수 파이프라인)를 받아서 적용한뒤 원본이미지와 처리된 이미지를 출력한다.

  1. 이미지를 읽는다 - imread : 이미지 경로를 주고 cv2.imread(img_path) 읽은 이미지를 cv2.COLOR_BGR2RGB로 변환한다
  2. figsize를 설정하고 subplot을 3*3짜리를 만들고 1에 해당 이미지를 넣는다
  3. 반복문을 돌려서 2~9번째 영역에 이미지를 넣고, 원본이미지를 transform함수에 넣어 변경 결과를 받음
#이미지 출력함수
def image_show(img_path, transforms):
    
    img = cv2.cvtColor(cv2.imread(img_path), cv2.COLOR_BGR2RGB)
    plt.rcParams['font.family'] = 'gulim'

    plt.figure(figsize=(15, 12))
    plt.subplot(3, 3, 1)
    plt.imshow(img)
    plt.title('원본')

    for i in range(2, 10): # plot의 index (2번째~9번째 axis에 이미지를 출력)
        result_img = transforms (img) # 원본이미지를 transform함수에 넣어서 변경된 결과를 받는다.
        plt.subplot(3, 3, i)   # 변환image shape : (ch, h, w) -> matplotlib shape :(h,w,ch)
        plt.imshow(result_img.permute(1, 2, 0)) 

    plt.tight_layout()
    plt.show()
<파라미터 정의>
img_path: str - transforms를 적용할 이미지 경로
transforms: Transforms 객체.

 

3. 이미지출력함수에 들어갈 "변환 함수", 즉 transforms 파라미터를 정의한다

  • ToTensor()가 첫번째 transforms로 정의 후, 변환함수들을 순서대로 정의한다
  • compose 함수는 앞의 함수의 출력값이 다음 함수의 입력값이 되므로,  이미지를 넣으면 순차적으로 변환이 이루어지는 변환 파이프라인이 생성된다.
transforms = transforms.Compose([

transforms.Totensor() ,  변환함수 1, 변환함수 2, …)]
# 변환함수들에 순서대로 이미지를 넣어서 변환 => 변환 파이프라인을 구성
# ToTensor()가 첫번째 transforms로 정의
    # - ndarray, PIL.image 타입 -> torch.Tensor
    # - (height, width, channel) -> (channel, height, width)
    # - pixel값들을 0~1 사이로 scaling 처리 (min max scaling)

 

변환함수의 종류
대부분 변환함수에는 랜덤성을 추가해서 항상 일정하게 바뀌지 않도록 처리한다.

 

  • 좌우/상하 반전

 

  • 회전 : 180도 안에서 30,20,170 등 임의적으로 각도 변환

  • affine 이동 변환 - 회전, 이동, 전단 변환 처리 + 크기 변환(작게하거나 키우거나)

  • 가우시안 블러

  • RamdomAdjustSharpness - 선명도

  • ColorJitter : 색관련 변환

 

  • 색반전 : RandomInvert

  • Crop 


    1) Centercrop

 

    2) RandomCrop

 3) RandomResizedCrop

  • RandomErasing()

4. transforms.RandomChoice([변환함수1, 변환함수2, ...]) 를 이용여러변환함수를 랜덤으로 실행한다.
RandomApply() - 여러개 중 Random하게 여러개를 선택해서 적용한다. 선택 확률을 선택할 수 있다.
RandomChoice() - 여러개 중 하나를 적용한다.