본문 바로가기

Data_Analysis_Track_33/Python

Python_Deeplearning_pytorch_08(Image Augmentation)

CNN small datasets 학습

  • 학습할 Data의 개수가 많지 않을 때 CNN을 통한 모형 학습이 어려울 수 있음
      - 딥러닝은 많은 양의 데이터셋을 이용해 feature engineering 과정 없이 원하는 문제를 해결할 수 있다. => Point: 많은 데이터 양
  • Data 양이 많지 않아 딥러닝 모델의 학습에 어려움이 있을 때 사용 가능한 방법
        - Image augmentation 활용
            - Image에 다양한 효과를 주어 데이터양을 늘린다.
                - Train dataset은 전체 대상 이미지들을 샘플링한 것이기 때문에 모든 형태를 다 가지고 있지 않다. Data augmentation은 train set의 이미지에 다양한 효과를 주어 실제 데이터셋과의 간격을 줄인다.
                - 영상데이터의 경우 각 영상 데이터의 색변경, 이미지잘라내기, 회전시키기, 명암변경 등을 적용하여 이미지들을 추가로 만들어 data의 수를 늘린다.
            - 모델의 Overfitting을 개선시킨다.
            - pytorch image augmentation을 위한 클래스들
                - https://pytorch.org/vision/stable/transforms.html
  • Pre-trained network의 활용한 Transfer learning (전이학습)
            - 매우 큰 데이터셋으로 미리 Training한 모델을 이용해 모델을 정의한다.
            - 성능이 좋은모델을 다량의 데이터로 학습시킨 모델을 사용하므로 적은 데이터에도 좋은 성능을 낼 수있다.

 

Image Augmentation 예제

 

import

import torch
from torchvision import transforms

import cv2
import matplotlib.pyplot as plt

 

이미지 출력 함수

# 이미지 출력 함수
def image_show(img_path, transforms):
    """
    이미지 경로와 transforms를 받아서 적용한뒤 원본이미지와 처리된 이미지를 출력한다.
    transforms는 8번 적용시켜 출력한다.
    [parameter]
        img_path: str - transforms를 적용할 이미지 경로
        transforms: Transforms 객체. 단 ToTensor()가 첫번째 transforms로 정의되 있어야 한다.
    """
    # img_path의 이미지를 읽어서 RGB로 변환.
    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)    
        plt.imshow(result_img.permute(1, 2, 0)) # 변환image shape: (ch, h, w) -> matplotlib shape: (h, w, ch)

    plt.tight_layout()
    plt.show()

 

여러 종류 변환함수 실습

- 주석처리를 하나씩 제거하면서 실습해보기

# transforms.Compose([변환함수1, 변환함수2, ....]) # 변환함수들애 순서대로 이미지를 넣어서 변환. => 변환 파이프라인을 구성.
transform = transforms.Compose([
    # - ndarray, PIL.Image 타입 -> torch.Tensor
    # - (height, width, channel)  -> (channel, height, width)
    # - pixcel 값들을 0 ~ 1 사이로 scaling 처리.(min max scaling)
    transforms.ToTensor()
    # 대부분 변환함수 -> 랜덤성을 추가. (항상 일정하게 바뀌지 않도록 처리한다.)
    ###########################
    # 좌우/상하 반전. 
    ###########################
    # , transforms.RandomHorizontalFlip(p=0.5) # 0.5: 반전확률, 좌우대칭반전
    # , transforms.RandomVerticalFlip(p=0.5)     # 상하대칭반전
    
    ###########################
    # 회전
    # 회전각도: 정수 - 회전범위: -정수 ~ +정수
    ###########################
    # , transforms.RandomRotation(degrees=180) # (-180 ~ +180)
    
    ###########################
    # affine 이동 변환들
    #  회전, 이동, 전단 변환 처리
    ###########################
    # , transforms.RandomAffine(degrees=(0,0),        # 회전 (최소, 최대) - 필수입력
    #                           translate=(0.1,0.3),  # 좌우/상하 이동. (실수:비율)
    #                           shear=(0.8, 1.2),     # 전단변환
    #                           scale=(0.5,1.2),      # 이동후 resize
    #                          )
    
    ###########################
    # 가우시안 블러
    ###########################
    # , transforms.GaussianBlur(kernel_size=(17,17), sigma=(1, 5)) # kernel_size/sigma(표준편차)가 클수록 blur효과가 강해진다. -> 흐려짐 + 잡음 더 많이 제거
                                                                   #   sigma - 실수값 하나: 고정, tuple() 범위사이에 랜덤하게 결정. (1, 5) 1 ~ 5
    ########################### 
    # 선명도 (Sharpen)
    # sharpness_factor: 1 - 원본과 동일, 1미만 - blur, 1초과 - sharpen
    # p: 적용될 가능성(확률)
    ###########################
    # , transforms.RandomAdjustSharpness(sharpness_factor=5, p=0.5)
    ###########################
    # 색관련 변환
    #  밝기, 대비, 채도, 색 변환 처리
    # 값: 실수 - 0.x [1 - 0.x ~ 1 + 0.x]
    #     tuple - 변화 비율 [min ~ max]
    #     1: 원본
    #     지정된 범위내에서 랜덤하게 선택.
    ###########################
    # , transforms.ColorJitter(brightness=(0.5, 1.2), # 밝기 조정, (1.0, 1.0)으로 설정시 밝기는 변하지 않는다.
    #                        contrast=(0.8, 1.2),     # 대비 조정
    #                        saturation=(0.5, 1.5),   # 채도 조정, (1.0, 1.0)으로 설정시 밝기는 변하지 않는다.
    #                        hue=(-0.2, 0.2))         # 색 조정, (-0.5이상 ~ 0.5이하), (0.0, 0.0)으로 설정시 밝기는 변하지 않는다.
    
    #########################
    # Grayscale로 변환 -> (3-채널, h, w)
    #########################
    # , transforms.RandomGrayscale(p=0.25)
    
    ############################
    # 반전 - 확률 지정할 수 있다.
    # 픽셀값을 반전. ex) 0 <-> 255, 1 -> 254. 
    ############################
    # , transforms.RandomInvert(p=0.7)
    
    
    ###########################
    # Center 영역 Crop
    # 정수(150) - h:150, w:150
    # 튜플((200, 100)) - h:200, w:100
    ###########################
    # , transforms.CenterCrop(150)
    
    ############################
    # RandomCrop - Crop 영역을 random하게 선택한다.
    ############################
    # , transforms.RandomCrop(150)

    ###########################
    # RandomResizedCrop - Random한 영역을 Crop후 지정한 종횡비 resize 한다.
    ###########################
    # , transforms.RandomResizedCrop(180,              # resize 크기
    #                                scale=(0.3, 0.7), # crop 비율
    #                                ratio=(0.5, 1.5)  # resize시 종횡비
    #                               )
    ##############################
    # 이미지를 부분적으로 삭제한다. (픽셀값을 0으로 변경)
    # p=확률, scale=() 삭제 크기범위, ratio=() 삭제 종횡비 범위 => 지정된 튜플 비율에서 random 하게 선택되 변경됨
    # occlusion(폐색-가려지는 문제)문제에서의 한계를 해결. https://deepapple.tistory.com/8
    ###############################
    , transforms.RandomErasing()

])

img_path = 'test_img/image.jpg'
image_show(img_path, transform)

 

 

- RandomApply() - 여러개 중 Random하게 여러개를 선택해서 적용한다. 선택 확률을 선택할 수 있다.
- RandomChoice() - 여러개 중 하나를 적용한다.

#####################################
# RandomApply() - 여러개 중 Random하게 여러개를 선택해서 적용한다. 선택 확률을 선택할 수 있다.
# RandomChoice() - 여러개 중 하나를 적용한다.
#####################################
transform2 = transforms.Compose([
    transforms.ToTensor()                           # 1
    , transforms.RandomApply([
        transforms.RandomHorizontalFlip(),          # 2
        transforms.RandomVerticalFlip(),            # 3
        transforms.RandomRotation(45),              # 4
        transforms.RandomCrop((200,200)),           # 5
    ], p = 0.9)
    , transforms.Resize((224, 224), antialias=True) # 6
]) # 6개중 2 ~ 6개

transform2 = transforms.Compose([
    transforms.ToTensor()                           # 1
    , transforms.RandomChoice([
        transforms.RandomRotation(45),              # 2
        transforms.RandomHorizontalFlip(),          # 3
        transforms.RandomVerticalFlip(),            # 4
    ])
    , transforms.Resize((224, 224), antialias=True) # 5
]) # 5개중 3개

image_show('test_img/cat.jpg', transform2)