딥러닝/컴퓨터비전

[컴퓨터비전] 데이터 증강 종류 및 코드 (Pytorch, Albumentations, Imgaug)

johyeongseob 2024. 12. 6. 21:20

데이터 증강 (Data Augmentation)

 데이터 증강은 데이터 수를 늘려, Overfitting을 방지하고, 모델이 Generalization을 갖도록 한다. 이미지에서 데이터 증강에는 다양한 종류가 있다. 아래 그림은 MNIST(28px*28px)를 이용한 이미지 증강 예시이다. 하나씩 살펴보자. 코드는 Pytorch 기준이다.

 

Pytorch의 torchvision 제공

import torchvision.transforms as transforms

 

1. 뒤집기(Flip)

horizon = transforms.RandomHorizontalFlip(p=1)
vertical = transforms.RandomVerticalFlip(p=1)

 

 P는 Probability로 이미지 증강을 적용할 확률값이다. 흔히, stochastic transformation 이라고도 한다. 100장의 이미지가 있다고 가정하자. P=1이면 100장 모두 이미지 증강을 적용한다. P=0.5이면 100장 중 랜덤으로 50장만 이미지 증강을 적용한다.

 

2. 회전 (Rotation)

rotation = transforms.RandomRotation(degrees=(45, 45))

 

 여기는 P가 없다. 앞으로 이미지 증강 중 P가 없으면 모든 이미지에 이미지 증강 (rotation)이 적용된다. Degree는 회전범위이다. Degree=(0, 180)이면 모든 이미지가 0도부터 180도까지 랜덤으로 각도가 정해져서 해당 각도만큼 이미지가 회전한다. 특정 각도로 회전을 원한다면 Degree=(n, n)으로 지정할 수 있다. Degree=(45, 45)이면 모든 이미지가 45도 만큼 회전한다.

 

3. 크기 (Scaling)

cropresize = transforms.Compose([transforms.CenterCrop(size=(80, 80)), transforms.Resize(size=(100, 100))])
paddingresize = transforms.Compose([transforms.Pad(padding=10), transforms.Resize(size=(100, 100))])

 

 설명은 크기라고 적었지만, 두 개는 개별적인 데이터 증강으로 하나는 Crop이며 나머지는 Padding이다. Crop은 이미지를 확대하며 사용자가 원하는 크기만큼 자를 수 있다. 반대로 패딩은 중앙을 기준으로만 상하좌우 픽셀값(pixel=0, 검은색)을 추가할 수 있다. 예시 코드에서는 Crop은 중앙으로 80% 확대하였고, Padding은 상하좌우 10px을 추가하였다.

 

4. 밝기, 대비, 채도, 색조 (Brightness, Contrast, Saturation, Hue)

contrast = transforms.ColorJitter(contrast=(1.5, 1.5))
bright = transforms.ColorJitter(brightness=(1.5, 1.5))

 

 네 가지 이미지 증강 방법은 ColorJitter를 사용하면 되며, 하이퍼파라미터로 네 가지 중 하나를 선택하면된다. Contrast는 대비 범위이다. 1은 기존이미지의 대비이다. 1보다 낮으면 명암의 구분이 낮아지며, 1보다 높으면 명암의 구분이 명확해진다. Contrast=(0.5, 1.5)이면 랜덤으로 대비값을 정해, 이미지에 적용한다.

 

5. 이동 (Shift)

shifting = transforms.RandomAffine(degrees=0, translate=(0.1, 0.1))

 

이미지를 중앙 기준으로 랜덤으로 상하좌우 이동한다. Translate=(a, b)는 상하 a 범위 내, 좌우 b 범위 내로 이동범위를 결정한다. Translate=(0.1, 0.1)이면 상하좌우 10% 범위 내로 이미지가 이동한다.

 

6. 가우시안 블러 (Gaussian Blur)

gaussianblur = transforms.GaussianBlur(kernel_size=(5, 5), sigma=(0.5, 0.5))

 

이미지를 흐릿하게 한다. 블러의 장점은 노이즈 (Noise)가 있을 때, 노이즈를 감소시킨다. 대신, 선명도(Sharpness)도 감소한다. Kernel_size는 window 크기이며, Sigma는 강도이다.

 

 

Albumentations 제공

import albumentations as A

 

만약 이미지를 DataLoader로 옮긴다면 아래 코드를 활용하자. Albumentations는 Numpy에서 작업이 실행되고, Torchvision은 Image에서 작업이 이루어진다.

class AlbumentationsTransform:
    def __init__(self, transform):
        self.transform = transform

    def __call__(self, img):
        img_np = np.array(img)
        augmented = self.transform(image=img_np)['image']
        return Image.fromarray(augmented)

 

7. 가우시안 노이즈 (Gaussian Nosie)

gaussnoise = AlbumentationsTransform(A.GaussNoise(var_limit=(200.0, 200.0), p=1.0))

 

이미지에 노이즈를 추가한다.

 

8. 변형 (Distortion)

elastic = AlbumentationsTransform(A.ElasticTransform(alpha=5, sigma=20, p=1))
optical = AlbumentationsTransform(A.OpticalDistortion(distort_limit=0.5, shift_limit=0.00, p=1))

 

이미지를 찌부러트린다. Optical distortion은 주로 카메라로 찍을 때, 흔들리는 현상을 재현하였다.

 

 

Imgaug의 iaa 제공

import imgaug.augmenters as iaa

 

Iaa 또한 Numpy에서 작업이 이루어진다. 다만 Albumentations와 코드가 일부 달라 여기서도 참고 코드를 추가한다.

class ImgaugTransform:
    def __init__(self, augmentation):
        self.augmentation = augmentation

    def __call__(self, img):
        img_np = np.array(img)
        augmented_img_np = self.augmentation(image=img_np)
        return Image.fromarray(augmented_img_np)

 

9. 코드블럭 제거 (Dropout)

dropout = ImgaugTransform(iaa.CoarseDropout(p=0.1, size_percent=0.3))

 

P는 이미지에서 어느정도 픽셀을 제거할 지 결정한다. 28px*28px 이미지면 78.4(784*0.1) 개의 픽셀이 사라진다. Size_percent는 블럭의 크기이다. Percent가 높을수록 큰 블럭들이 적게 형성되어 Dropout을 진행한다.