본문 바로가기
목차
Python

[PyTorch] Geometry-Others-Torchvision.transforms.v2.functional

by ds31x 2025. 6. 10.
728x90
반응형

torchvision.transforms.v2.functional 모듈에서 제공하는

이미지 데이터에 다양한 기하학적 및 픽셀 변환을 적용할 수 있는 함수들을 소개함.

 

관련 gist

https://gist.github.com/dsaint31x/8249e5a86fb93c64bf2df31c57009afd

 

dl_Geometry-others-torchvision.transforms.v2.functional.ipynb

dl_Geometry-others-torchvision.transforms.v2.functional.ipynb - dl_geometry-others-torchvision-transforms-v2-functional.ipynb

gist.github.com

 


0. Prerequisites

torchvision.transforms.v2.functional 모듈은,

  • 이미지 tensor 객체를 입력으로 받아
  • 해당 이미지에 직접 적용할 수 있는 다양한 이미지 변환 함수들을 제공함.

제공되는 함수들은
torchvision.transfroms.v2 의 Transform 클래스들과 달리,

  • 상태(state)를 가지지 않으며, 입력 텐서(이미지 등)를 인자로 직접 받아 변환된 텐서를 즉시 반환함.
  • 간단하고 직접적이며, 변환을 한 번만 적용하거나 사용자 정의 변환 함수 내에서 다른 함수들을 조합할 때 유용
  • 여러 변환을 순차적으로 적용하는 복잡한 파이프라인을 구축할 경우,
  • 각 함수 호출마다 반복적인 인자 전달이 필요하여 다소 불편할 수 있음.

colab에서 다음의 코드들을 수행시켜서 이미지를 다운로드하고 아래의 예제 코드를 수행할 수 있도로 함:

from torchvision.transforms.v2.functional import (
    crop,
    resized_crop,
    center_crop,
    five_crop,
    ten_crop,
)

img_path = "assets/astronaut.jpg"
img_url = "https://raw.githubusercontent.com/pytorch/vision/main/gallery/assets/astronaut.jpg"

!mkdir -p assets/coco/images
!curl -o assets/astronaut.jpg {img_url}

from torchvision.io import decode_image

original_img = decode_image(img_path)

print(f" {type(original_img) = }\n \
{original_img.dtype = }\n \
{original_img.shape = }")

 

다음은 이미지 출력을 위한 plot 함수임:

더보기
# https://github.com/pytorch/vision/tree/main/gallery/
# 위의 torchvision관련 예제들의 display를 위한 plot함수를 그대로 가져옴.

import matplotlib.pyplot as plt
import torch
from torchvision.utils import draw_bounding_boxes, draw_segmentation_masks
from torchvision import tv_tensors
from torchvision.transforms.v2 import functional as F


def plot(imgs, row_title=None, **imshow_kwargs):
    if not isinstance(imgs[0], list):
        # Make a 2d grid even if there's just 1 row
        imgs = [imgs]

    num_rows = len(imgs)
    num_cols = len(imgs[0])
    _, axs = plt.subplots(nrows=num_rows, ncols=num_cols, squeeze=False)
    for row_idx, row in enumerate(imgs):
        for col_idx, img in enumerate(row):
            boxes = None
            masks = None
            if isinstance(img, tuple):
                img, target = img
                if isinstance(target, dict):
                    boxes = target.get("boxes")
                    masks = target.get("masks")
                elif isinstance(target, tv_tensors.BoundingBoxes):
                    boxes = target
                else:
                    raise ValueError(f"Unexpected target type: {type(target)}")
            img = F.to_image(img)
            if img.dtype.is_floating_point and img.min() < 0:
                # Poor man's re-normalization for the colors to be OK-ish. This
                # is useful for images coming out of Normalize()
                img -= img.min()
                img /= img.max()

            img = F.to_dtype(img, torch.uint8, scale=True)
            if boxes is not None:
                img = draw_bounding_boxes(img, boxes, colors="yellow", width=3)
            if masks is not None:
                img = draw_segmentation_masks(img, masks.to(torch.bool), colors=["green"] * masks.shape[0], alpha=.65)

            ax = axs[row_idx, col_idx]
            ax.imshow(img.permute(1, 2, 0).numpy(), **imshow_kwargs)
            ax.set(xticklabels=[], yticklabels=[], xticks=[], yticks=[])

    if row_title is not None:
        for row_idx in range(num_rows):
            axs[row_idx, 0].set(ylabel=row_title[row_idx])

    plt.tight_layout()

1. horizontal_flip(img)

  • 역할:
    • 입력 이미지를 수평 축(세로 방향 중심)을 기준으로 flip (뒤집음).
  • 사용 시점:
    • 이미지의 좌우 대칭성을 활용하여 data augmentation(데이터 증강)을 수행할 때 주로 사용됨.
    • Object Detection(객체 감지)나 Classification 등에서 모델이 객체의 좌우 방향에 관계없이 강건하게 예측하는데 도움을 줌.
  • 주요 파라미터:
    • img (Tensor): 변환을 적용할 입력 이미지 Tensor 객체.
# horizontal_flip 함수를 사용하여 이미지 수평 뒤집기
flipped_img_h = horizontal_flip(original_img)

# 결과 확인 (크기는 변하지 않음)
print(f"{original_img.shape    = }")
print(f"{flipped_img_h.shape   = }")

# Result
# original_img.shape    = torch.Size([3, 512, 512])
# flipped_img_h.shape   = torch.Size([3, 512, 512])


2. vertical_flip(img)

  • 역할:
    • 입력 이미지를 수직 축(가로 방향 중심)을 기준으로 flip.
  • 사용 시점:
    • 이미지의 상하 대칭성이 의미 있는 경우의 data augmentation에 사용됨.
  • 주요 파라미터:
    • img (Tensor): 변환을 적용할 입력 이미지 Tensor 객체.
# vertical_flip 함수를 사용하여 이미지 수직 뒤집기
flipped_img_v = vertical_flip(original_img)

# 결과 확인 (크기는 변하지 않음)
print(f"{original_img.shape    = }")
print(f"{flipped_img_v.shape   = }")

# Result
# original_img.shape    = torch.Size([3, 512, 512])
# flipped_img_v.shape   = torch.Size([3, 512, 512])


3. pad(img, padding, fill=0, padding_mode='constant')

  • 역할:
    • 입력 이미지의 가장자리에 padding.
    • 입력 이미지 크기를 늘림
  • 사용 시점:
    • 이미지의 크기를 일정하게 맞추거나,
    • Convolutional Neural Network에서 경계 픽셀의 정보를 더 많이 활용하기 위해 사용됨.
  • 주요 파라미터:
    • img (Tensor): 변환을 적용할 입력 이미지 Tensor 객체.
    • padding (int, tuple 또는 list): 추가할 패딩의 크기를 정의.
      • int: 네 방향(좌, 상, 우, 하)에 동일한 크기의 padding을 추가.
      • tuple 또는 list with 2 elements:
        • 좌/우, 상/하 방향에 동일한 크기의 padding을 추가.
        • [padding_left_right, padding_top_bottom].
      • tuple 또는 list with 4 elements:
        • 좌, 상, 우, 하 각 방향에 지정된 크기의 padding을 추가.
        • [padding_left, padding_top, padding_right, padding_bottom].
    • fill (int, float 또는 tuple/list of int/float):
      • 패딩 영역을 채울 numerical values.
      • 이미지의 channel 수와 일치하는 값 또는 값들의 리스트를 사용할 수 있음.
      • 기본값: 0.
    • padding_mode (str): 패딩을 채우는 방식.
      • 'constant': fill 값으로 padding.
      • 'edge': 이미지의 가장자리 픽셀 값으로 padding.
      • 'reflect': 이미지의 가장자리를 기준으로 반사된 값으로 padding (맨 가장자리 픽셀은 포함되지 않음).
      • 'symmetric': 이미지의 가장자리를 기준으로 대칭된 값으로 padding (맨 가장자리 픽셀도 포함).
      • 기본값:'constant'
# 패딩 크기 정의 (좌, 상, 우, 하 순서)
padding_size = [50, 50, 50, 50]

# pad 함수를 사용하여 이미지에 패딩 추가
padded_img = pad(
    original_img, 
    padding=padding_size, 
    fill=255,
    ) # 흰색(255)으로 채움

# 결과 확인 (패딩만큼 크기가 증가)
print(f"{original_img.shape = }")
print(f"{padded_img.shape   = }")

# Result
# original_img.shape = torch.Size([3, 512, 512])
# padded_img.shape   = torch.Size([3, 612, 612])


4. rotate(img, angle, interpolation=InterpolationMode.NEAREST, expand=False, center=None, fill=0)

  • 역할:
    • 입력 이미지를 지정된 각도만큼 회전.
    • rotation center를 지정할 수 있으며,
    • 회전 후 이미지 크기가 커질 수 있음 (이미지가 잘리지 않기 위해서)
  • 사용 시점:
    • data augmentation에서 많이 이용됨.
  • 주요 파라미터:
    • img (Tensor): 변환을 적용할 입력 이미지 Tesnor 객체.
    • angle (float 또는 int): 회전 각도 (degree 단위, ccw).
    • interpolation (InterpolationMode): 회전 시 픽셀 값을 계산하는 interpolation(보간) 방식.
      • InterpolationMode.NEAREST (기본값).
      • InterpolationMode.BILINEAR
      • InterpolationMode.BICUBIC
    • expand (bool): 회전 후 이미지 전체가 포함될 수 있도록 출력 이미지 크기를 확장할지 여부.
      • False (기본값)
      • False 인 경우 회전 후 이미지의 일부가 잘릴 수 있음.
    • center (tuple of float, optional): 회전 중심 (x, y).
      • None이면 자동으로 이미지 중앙을 계산하여 이를 중심으로 회전.
      • None이 기본값.
    • fill (int, float 또는 tuple/list of int/float):
      • 회전 후 이미지 영역 밖으로 벗어나는 부분을 채울 값.
      • 0 이 기본값.
# rotate 함수를 사용하여 이미지 45도 회전
rotated_img = rotate(
    original_img, 
    angle=45,
    expand=True,
    center=None,
    fill=0,
    )

# 결과 확인 (expand=False일 경우 크기는 변하지 않음, 하지만 일부 영역이 잘리는 등의 손실발생할 수 있음)
print(f"{original_img.shape = }")
print(f"{rotated_img.shape  = }")

# Result
# original_img.shape = torch.Size([3, 512, 512])
# rotated_img.shape  = torch.Size([3, 726, 726])


5. affine(img, angle, translate, scale, shear, interpolation=InterpolationMode.NEAREST, fill=0, center=None)

  • 역할:
    • 입력 이미지에 affine transform을 적용.
    • 회전(angle), 이동(translate), 크기 조절(scale), 기울이기(shear)와 같은 선형 변환의 조합에 해당.
  • 사용 시점:
    • 이미지에 복합적인 기하학적 변형을 적용하여 data augmentation을 할 때 주로 이용됨.
  • 주요 파라미터:
    • img (Tensor): 변환을 적용할 입력 이미지 Tensor 객체.
    • angle (float 또는 int): 회전 각도 (degree 단위, ccw).
    • translate (list 또는 tuple of int): 이미지의 픽셀 이동 거리 (dx, dy).
    • scale (float): 이미지 크기 조절 비율.
    • shear (float 또는 list/tuple of float): shear 각도.
      • float 하나면 x축만 shearing
      • [sx, sy]면 x, y축 각각을 shearing.
    • interpolation (InterpolationMode): 변환 시 픽셀 값을 계산하는 interpolation 방식.
      • InterpolationMode.NEAREST (기본값).
      • InterpolationMode.BILINEAR
      • InterpolationMode.BICUBIC
      • fill (int, float 또는 tuple/list of int/float):
      • 변환 후 이미지 영역에 없던 영역이 이미지에 들어올 경우 채울 값.
      • 0 이 기본값.
    • center (tuple of float, optional): affine transform 의 중심 (x, y).
      • None이면 자동으로 이미지 중앙을 계산하여 이를 중심으로 변환.
      • None 이 기본값.
# 아핀 변환 파라미터 정의
angle     = 30       # rotation degree
translate = [50, 50] # x, y 방향 이동
scale     = 0.8      # 크기 조절 비율
shear     = [0, 0]   # x, y 방향 기울기

# affine 함수를 사용하여 아핀 변환 적용
affine_img = affine(
    original_img, 
    angle=angle, 
    translate=translate, 
    scale=scale, 
    shear=shear,
    )

# 결과 확인 (변환에 따라 크기 변할 수 있음)
print(f"{original_img.shape = }")
print(f"{affine_img.shape   = }")

# Result
# original_img.shape = torch.Size([3, 512, 512])
# affine_img.shape   = torch.Size([3, 512, 512])


6. perspective(img, startpoints, endpoints, interpolation=InterpolationMode.BILINEAR, fill=0)

  • 역할:
    • 입력 이미지에 perspective transformation(원근 변환)을 수행.
    • 이미지의 네 모서리 좌표(startpoints)를 새로운 위치(endpoints)로 이동시켜 perspective transformation을 표현.
  • 사용 시점: 실제 카메라에서 촬영될 때 발생하는 원근 왜곡을 모방하여 데이터 증강을 수행하거나, 이미지의 특정 평면을 바로잡을 때 사용됩니다.
  • 주요 파라미터:
    • img (Tensor): 변환을 적용할 입력 이미지 Tensor 객체.
    • startpoints (list of list of float): 원본 이미지의 네 모서리 좌표
      • [[x1, y1], [x2, y2], [x3, y3], [x4, y4]].
      • 좌표는 이미지 좌상단을 (0, 0)으로 기준으로 표현됨.
    • endpoints (list of list of float): 변환될 새로운 모서리 좌표
      • [[x1', y1'], [x2', y2'], [x3', y3'], [x4', y4']].
    • interpolation (InterpolationMode): 변환 시 픽셀 값을 계산하는 interpolation 방식.
      • InterpolationMode.NEAREST
      • InterpolationMode.BILINEAR (기본값)
      • InterpolationMode.BICUBIC
    • fill (int, float 또는 tuple/list of int/float):
      • 변환 후 이미지 영역에 없던 영역이 이미지에 들어올 경우 채울 값.
      • 0 이 기본값.
# 원본 이미지의 네 모서리 좌표
startpoints = [[0, 0], [original_img.shape[2], 0], [original_img.shape[2], original_img.shape[1]], [0, original_img.shape[1]]]
# 변환될 새로운 모서리 좌표 (예시: 오른쪽 하단이 확대되는 느낌)
endpoints = [[0, 0], [original_img.shape[2], 0], [original_img.shape[2] - 50, original_img.shape[1] - 50], [50, original_img.shape[1] - 50]]

# perspective 함수를 사용하여 원근 변환 적용
perspective_img = perspective(original_img, startpoints, endpoints)

# 결과 확인 (변환에 따라 크기 변할 수 있음)
print(f"{original_img.shape    = }")
print(f"{perspective_img.shape = }")

# Result
# original_img.shape    = torch.Size([3, 512, 512])
# perspective_img.shape = torch.Size([3, 512, 512])


7. elastic(inpt, displacement, interpolation=InterpolationMode.BILINEAR, fill=None)

  • 역할:
    • 입력 이미지에 elastic transfrom(탄성 변환)을 적용.
    • 이 함수는 각 픽셀의 변위 벡터를 정의하는 displacement 텐서를 argument로 요구함: 사용이 어려움.
  • 사용 시점:
    • 이미지에 비선형적이고 국소적인 왜곡을 적용하여 데이터 증강을 수행할 때 사용됨.
    • 일반적으로 alphasigma 파라미터를 사용하는 ElasticTransform 클래스를 통해 간접적으로 호출됨.
  • 주요 파라미터:
    • inpt (Tensor): 변환을 적용할 입력 이미지 텐서입니다.
    • displacement (Tensor): 각 픽셀의 displacement vector(변위 벡터)를 나타내는 Tensor객체.
      • shape가 (N, H, W, 2) 이며, 각 요소는 해당 픽셀의 (dx, dy) 변위.
      • 확인 필요. (H,W,2)도 된다고 하는데 이는 동작안함.
    • interpolation (InterpolationMode): 변환 시 픽셀 값을 계산하는 interpolation 방식.
      • InterpolationMode.NEAREST
      • InterpolationMode.BILINEAR (기본값)
      • InterpolationMode.BICUBIC
    • fill (Optional[List[float]]):
      • 변환 후 이미지 영역에 없던 영역이 이미지에 들어올 경우 채울 값.
      • None이면 입력 이미지의 가장자리 픽셀 값으로 채워짐.
      • None기본값
displacement 계산이 용이하지 않으므로
가급적 ElasticTransform 클래스를 사용할 것.

같이보면 좋은 자료들

https://docs.pytorch.org/vision/main/transforms.html#others

 

Transforming and augmenting images — Torchvision main documentation

Shortcuts

docs.pytorch.org

 

 

728x90