Image Augmentation

이장한·2023년 10월 30일
0

딥러닝

목록 보기
11/20

1.CNN small datasets 학습

말 그대로, data의 수가 많지 않을 때에 관한 것이다.

그도 그럴게, 보통 cnn,딥러닝 등은 데이터가 천개 만개정도 될 때 쓰인다.

근데... 데이터가 없을 때도 cnn을 쓸 수 있지 않을까?

해서 나온 것이 바로 cnn small datasets이다.

2.첫번째 방법은 데이터량을 늘리는 것이다.

이와 관한 것이 바로 Image augmentation이다.

자세한 방법은 다음과 같다.

1.Train dataset은 전체 대상 이미지들을 샘플링한 것이기 때문에 모든
형태를 다 가지고 있지 않다. Data augmentation은 train set의 이미지에 다양한 효과를 주어 실제 데이터셋과의 간격을 줄인다.
2.영상데이터의 경우 각 영상 데이터의 색변경, 이미지잘라내기, 회전시키기, 명암변경 등을 적용하여 이미지들을 추가로 만들어 data의 수를 늘린다.

이런 방법은 모델의 overfitting을 개선시킨다는 점에서도 괄목할 만 하다.

그러나 한계가 있다.

푸들 1개에 대한 이미지를 100개로 뻥튀기를 시키든, 다른 강아지 이미지를

대체할 수는 없다는 한계가 있다.

당연히 다른 데이터가 많은 경우보다, 정확도 등이 떨어질 수 밖에 없다.

그래서

한정된 data에서 최대한 정확도를 높이자!

라는 것이 바로 Image augmentation의 목적이라고 볼 수 있다.

3.예제

from torchvision import transforms

에 Image augmentation에 관련된 것들이 있다.

이미지 출력 함수는 다음과 같다.

# 이미지 출력 함수
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)    
        #변환 image shape:(ch,h,w) ->matplotlib shape:(h,w,ch)
        plt.imshow(result_img.permute(1, 2, 0)) #permute는 0번 자리에 1번이, 1번 자리에 2번이 들어가게 할 수 있다.

    plt.tight_layout() #배치를 만든다.
    plt.show()

그런 다음, compose를 정의한다.

아래 코드는 여러가지 transforms 함수를 통해 이미지를 처리하는 코드이다.


#transforms.Compose([변환함수1,변환함수2,....]) #변환함수들에 순서대로 이미지를 넣어서 변환한다.
#이를 통해 이미지변환의 파이프라인을 구성한다.
#핵심은 순서대로 한다는 것이다. 그렇기 때문에 순서가 매우 중요하다.


transform = transforms.Compose([
    
    #ndarray, PIL.Image 타입 ->torch.tensor
    #-(height,width,channel) ->(c,h,w)와 같이 바꿔준다.
    transforms.ToTensor()
    
    
    ###########################
    # 좌우/상하 반전. 
    ###########################
    #대부분의 변환함수는 랜덤성을 추가한다. (항상 일정하게 바뀌지 않도록 처리한다.)
    #이렇게 하는 이유는 최대한 더 많은 데이터를 추가해야 하기 때문이다.
#     , transforms.RandomHorizontalFlip(p=0.5) #반전 확률이다.
#     , transforms.RandomVerticalFlip(p=0.5) #위아래 반전 확률이다.
    
    ###########################
    # 회전
    # 회전 각도를지정한다. - 회전범위:-정수~+정수(-180 ~ +180)
    ###########################
    # , transforms.RandomRotation(degrees=180)
    #위와 같이 하면 모든 이미지가 180도 회전된 것이 아니라, -180부터 180의 범위 사이에서 회전이 된 것을 알 수 있다.
    
    
    ###########################
    # affine 이동 변환들
    #  회전, 이동, 전단 변환 처리를 한번에 할 수 있다.
    ###########################
    
    #RandomAffine은 랜덤으로 affine을 하기 때문에 적용이 되지 않을 경우도 있다.
    # , transforms.RandomAffine(degrees=(0,0), #회전(최소:-20,최대:20)/(0,0)은 회전을 시키지 않겠다는 이야기.
    #                           translate=(0.1,0.3), #좌우/상하 이동 (실수:비율)
     #                          shear=(0.0, 0.0), #전단 변환(평행사변형 형식으로 변환하는 것이다.)
      #                         scale=(1.2,1.2), #이동 후 resize하는 것이다.
       #                       )
    
    ###########################
    # 가우시안 블러
    # 잡음을 없에주는 역활.
    #kernel_size/sigma(표준편차)가 클 수록, 이미지가 흐려진다. 잡음을 더 많이 제거한다.
    #sigma - 실수값 하나: 고정, tuple: 범위 사이에서 random하게 결정.
    ###########################
#     , transforms.GaussianBlur(kernel_size=(17,17), sigma=(1, 5))
    
    ########################### 
    # 선명도 (Sharpen)
    #sharpness_factor:1-원본고 동일,1초과:sharpen
    # p: 적용될 가능성.(확률)
    ###########################
 #    , transforms.RandomAdjustSharpness(sharpness_factor=5, p=0.5) 
    ###########################
    # 색관련 변환
    #  밝기, 대비, 채도, 색 변환 처리
    # tuple로 하면 변화 비율을 (min,max로 하게 된다.)
    # 특히 ColorJitter를 쓰면 이미지를 많이 바꿀 수 있게 된다.
    ###########################
    # , transforms.ColorJitter(brightness=(0.5, 1.2), #밝기 조정
    #                        contrast=(0.8, 1.2), #대비 조정
    #                        saturation=(0.5, 1.5), #채도 조정
   #                        hue=(-0.2, 0.2)) #색 조정---조정하고 싶지 않다면 (0.0,0.0)
    #                        #hue 같은 경우는 범위가 -0.5~0.5이다.
    
    
    #########################
    # Grayscale----화면을 회색으로!
    #########################
#     , transforms.RandomGrayscale(p=0.25)
    
    ############################
    # 반전 - 확률 지정할 수 있다.
    # 픽셀값을 반전. 0<->255, 1<->254
    #p는 확률이다.
    ############################
#    , transforms.RandomInvert(p=0.7)
    
    
    ###########################
    # Center 영역 Crop
    #정수는 h와 w를 같게 하고,
    #튜플((200,100))은 h:200, w:100 같은 경우이다.
    #지정한 영역을 확대해서 보여준다.
    ###########################
#     , transforms.CenterCrop(150)
    
    ############################
    # RandomCrop - Crop 영역을 random하게 선택한다.
    ############################
#     , transforms.RandomCrop(150)

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

])
#위의 함수들에서 몇가지를 골라서 이미지를 변환시킬 수 있다.
#transform을 통해 이미지를 받아와서 변환시킨 것을 image_show을 통해 show 한다.
img_path = 'test_img/image.jpg'
image_show(img_path, transform)

4.실행되는 함수의 수를 조절하고 싶을 때

RandomApply() - 여러개 중 Random하게 여러개를 선택해서 적용한다.
RandomChoice() - 여러개 중 하나를 적용한다.

아래에 자세한 코드가 있다.


#####################################
# RandomApply() - 여러개 중 Random하게 여러개를 선택해서 적용한다. 선택 확률을 선택할 수 있다.
# RandomChoice() - 여러개 중 하나를 적용한다.
#####################################
transform2 = transforms.Compose([
    transforms.ToTensor() #1
    , transforms.RandomApply([ #4개의 함수들을 각각 90프로의 확률로 실행시킨다.
        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()
#     , transforms.RandomChoice([ #여기 안에 있는 함수들 중 1개만 실행.
#         transforms.RandomRotation(45), 
#         transforms.RandomHorizontalFlip(),
#         transforms.RandomVerticalFlip(),
#     ])
#     , transforms.Resize((224, 224), antialias=True)
# ])

image_show('test_img/cat.jpg', transform2)
profile
기술을 통해 세상을 이롭게 하리라

0개의 댓글