Augmentation on bounding boxes

slave·2023년 3월 12일
0

Albumentations Library를 활용한 augmentation을 계속 사용하던 중 object detection에서 bounding box를 가지고 있는 경우에 하는 augmentation과 그냥 단순히 computer vision problem에서 image를 가지고 augmentation을 하는 것이 달라서 기록차 포스트를 적어본다.


Simle image

import albumentations as A
from albumentations.pytorch.transforms import ToTensorV2

def get_transforms():
    return A.Compose([
        A.Resize(height=256, width=256),
        A.RandomRotate90(),
        A.HorizontalFlip(p=0.5),
        A.VerticalFlip(p=0.5),
        A.OneOf([
            A.RandomBrightnessContrast(brightness_limit=0.2, contrast_limit=0.2),
            A.RandomGamma(),
            A.RandomBrightness(),
            A.RandomContrast(),
        ], p=0.5),
        A.OneOf([
            A.Blur(),
            A.GaussianBlur(),
            A.MotionBlur(),
        ], p=0.2),
        A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)),
        ToTensorV2(),
    ])

Image with bounding boxes

import albumentations as A
from albumentations.pytorch.transforms import ToTensorV2

def get_transforms():
    return A.Compose(
        [
            A.RandomSizedCrop(min_max_height=(800, 800), height=1024, width=1024, p=0.5),
            A.OneOf([
                A.HueSaturationValue(hue_shift_limit=0.2, sat_shift_limit= 0.2, 
                                     val_shift_limit=0.2, p=0.9),
                A.RandomBrightnessContrast(brightness_limit=0.2, 
                                           contrast_limit=0.2, p=0.9),
            ],p=0.9),
            A.ToGray(p=0.01),
            A.HorizontalFlip(p=0.5),
            A.VerticalFlip(p=0.5),
            A.Resize(height=512, width=512, p=1),
            A.Cutout(num_holes=8, max_h_size=64, max_w_size=64, fill_value=0, p=0.5),
            ToTensorV2(p=1.0),
        ], 
        p=1.0, 
        bbox_params=A.BboxParams(
            format='pascal_voc',
            min_area=0, 
            min_visibility=0,
            label_fields=['labels']
        )
    )

이후에 Custom Dataset에서 transforms을 정의하고, transforms = get_transforms()를 적으면 Data augmentation을 할 수 있다.

Bounding Box가 있는 경우와 없는 경우의 차이는 간단한데 bbox_params를 추가해주는 것이다.

  • format: bounding box의 format을 지정해주는 것으로 여기서는 'pascal_voc'를 사용했다. 'pascal_voc'는 bounding box의 coordinates를 (xmin, ymin, xmax, ymax)로 지정한다. 이외에도 'coco' format 방식도 자주 사용되는데 (xmin, ymin, width, height)을 사용한다. 이것 말고도 'yolo' 등 또 있다.
  • min_area: bounding Box라고 정의(인식)하기 위한 box의 최소 크기를 지정한다. min_area보다 작은 크기의 box들은 remove됨.
  • min_visibility: image에서 bounding box가 차지하고 있어야 하는 minimum fraction을 지정한다. min_visibility보다 less visible하면 remove됨.
  • label_fields: A list of fields that contain the labels for each bounding box. 여기서 말하는 field는 dictionary의 key에 해당하며 specific piece of information을 담고있다.

Dataset에서 transforms를 실제로 적용할 때는 아래처럼 bouding box를 포함하고 있는 경우에는 image 뿐만 아니라 bboxes, labels도 parameter로 보내줘야 한다.

sample = self.transforms(image = image)
sample = self.transforms(**{
	'image': image,
    'bboxes': boxes,
    'labels': labels
})

추가적으로 ToTensorV2()에 대해서 알아보자.

ToTensorV2()
ToTensorV2() converts the image from the original format (e.g. numpy array) to a PyTorch tensor format, which has a shape of (channels, height, width). Therefore, if the original image shape was (height, width, channels), then the output shape after ToTensorV2 would be (channels, height, width) as you mentioned (ToTensorV2()가 image의 shape을 바꿔주는 것을 꼭 인지하고 있자).

보통 torchvision의 transforms에서는 Normalize를 사용할 때 반드시 데이터를 min_max scale(0~1)로 만들어주어야 하기 때문에 ToTensor를 먼저 사용한 후에 Normalize를 적용하는데 albumentation의 Normalize는 scaling과 normalize를 동시에 처리한다는 차이점이 있다.

albumentations에서는 ToTensor 대신 ToTensorV2를 사용하는데 ToTesorV2는 ToTensor와 마찬가지로 tensor형변환, channel dimension을 첫번째 차원으로 가져오는 역할을 하지만 min_max scaling은 하지 않는다는 것을 명심하자. (추가로 자료형 문제 때문에 albumentations에서 ToTensorV2를 Normalize 보다 앞에서 사용하면 에러가 발생한다.)

정리

  • torchvision transforms 에서는 Normalize 이전에 ToTensor를 사용할 것.
  • albumentations 에서는 Normalize 이후에 ToTensorV2를 사용할 것.

틀리거나 애매한 부분은 댓글 달아주시면 감사하겠습니다.

profile
~2024.2.29(공군)

0개의 댓글