이미지 프로세서
이미지 프로세서
이미지 프로세서는 이미지를 픽셀 값, 즉 이미지의 색상과 크기를 나타내는 텐서로 변환합니다. 픽셀 값은 비전 모델의 입력이 됩니다. 사전 훈련 모델이 올바른 입력을 받도록, 이미지 프로세서는 이미지가 사전 훈련에 사용된 이미지와 정확히 동일한 형태가 되도록 다음 연산을 수행할 수 있습니다.
출처: 문서
본문
이미지 프로세서는 이미지를 픽셀 값, 즉 이미지의 색상과 크기를 나타내는 텐서로 변환합니다. 픽셀 값은 비전 모델의 입력이 됩니다. 사전 훈련 모델이 올바른 입력을 받도록, 이미지 프로세서는 이미지가 모델이 사전 훈련된 이미지와 정확히 동일한 형태가 되도록 다음 연산을 수행할 수 있습니다.
- 이미지를 중심 자르기(center-crop) 또는 크기 조정(resize)하기
- 픽셀 값을 정규화하거나 재조정(rescale)하기
Hugging Face Hub 또는 로컬 디렉터리의 비전 모델에서 from_pretrained()을 사용해 이미지 프로세서의 설정(이미지 크기, 정규화 및 재조정 여부 등)을 로드합니다. 각 사전 훈련 모델의 설정은 preprocessor_config.json 파일에 저장됩니다.
from transformers import AutoImageProcessor
image_processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224")
이미지를 이미지 프로세서에 전달해 픽셀 값으로 변환하고, PyTorch 텐서를 반환하도록 return_tensors="pt"를 설정합니다. 입력을 출력해 이미지가 텐서로 어떻게 보이는지 확인해 보세요.
from PIL import Image
import requests
url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/image_processor_example.png"
image = Image.open(requests.get(url, stream=True).raw).convert("RGB")
inputs = image_processor(image, return_tensors="pt")
이 가이드는 이미지 프로세서 클래스와 비전 모델을 위한 이미지 전처리 방법을 다룹니다.
이미지 프로세서 클래스
이미지 프로세서는 두 개의 백엔드를 가진 백엔드 기반 아키텍처를 사용합니다.
- TorchvisionBackend — 기본 torchvision 기반 구현입니다. GPU 가속을 지원하며 torch.Tensor 입력의 배치에서 PIL 백엔드보다 최대 33배 빠릅니다. 모든 모델이 이 백엔드를 지원하며, 최신 모델은 이 백엔드만 지원합니다.
- PilBackend — PIL/NumPy 대안입니다. 이식성이 있으며 CPU 전용입니다. 구형 모델에서만 사용할 수 있으며, 원본 구현의 정확한 수치 출력을 재현할 때 유용합니다.
로드된 프로세서의 활성 백엔드는 backend 속성(예: processor.backend == "torchvision")으로 확인할 수 있습니다. 각 이미지 프로세서는 from_pretrained() 및 save_pretrained() 메서드를 제공하는 ImageProcessingMixin을 서브클래스로 가집니다.
이미지 프로세서를 로드하는 방법은 AutoImageProcessor를 사용하거나 모델별 클래스에서 직접 로드하는 두 가지가 있습니다.
AutoClass API는 이미지 프로세서가 연결된 모델을 직접 지정하지 않고도 이미지 프로세서를 로드할 수 있는 편리한 메서드를 제공합니다.
backend 인자와 함께 from_pretrained()을 사용해 백엔드를 선택합니다. backend를 생략하면(기본값) torchvision이 설치되어 있을 때 torchvision을 선택하고, 그렇지 않으면 PIL을 사용합니다. backend="pil"은 구형 모델에서만 지원되며, 최신 모델은 torchvision 백엔드만 노출한다는 점에 유의하세요.
[!NOTE] 소수의 구형 모델(Chameleon, Flava, Idefics3, SmolVLM)은 Lanczos 보간을 사용합니다. 이들의 기본 백엔드는 torchvision 버전에 따라 달라집니다. torchvision > 0.27에서는 Lanczos가 기본적으로 지원되어 이 모델들은 기본적으로 torchvision을 사용합니다. 더 오래된 torchvision 버전은 BICUBIC으로 대체되므로, 원본 출력을 보존하기 위해 기본값은 PIL입니다. 기본값을 덮어쓰려면
backend="torchvision"을 명시적으로 전달하세요.
from transformers import AutoImageProcessor
# 기본값: 가능하면 torchvision을, 그렇지 않으면 pil을 선택함
image_processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224")
# torchvision 백엔드를 명시적으로 요청
image_processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224", backend="torchvision")
# PIL 백엔드를 명시적으로 요청 (지원하는 모델만)
image_processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224", backend="pil")
각 이미지 프로세서는 특정 사전 훈련 비전 모델과 연결되며, 그 설정에는 모델이 기대하는 크기와 정규화 파라미터가 포함됩니다.
모델별 클래스에서 직접 torchvision 백엔드 프로세서를 로드합니다.
from transformers import ViTImageProcessor
image_processor = ViTImageProcessor.from_pretrained("google/vit-base-patch16-224")
이를 지원하는 모델의 경우, Pil 접미사가 붙은 클래스로 PIL 백엔드를 로드할 수 있습니다. 이는 원본 구현과 정확한 수치적 일치가 필요할 때 유용합니다.
from transformers import ViTImageProcessorPil
image_processor = ViTImageProcessorPil.from_pretrained("google/vit-base-patch16-224")
Torchvision 백엔드 프로세서
TorchvisionBackend는 기본 백엔드입니다. torchvision이 설치되어 있는지 확인한 다음, backend="torchvision"으로 로드합니다(또는 torchvision이 사용 가능할 때 자동으로 선택되므로 backend를 생략해도 됩니다).
from transformers import AutoImageProcessor
processor = AutoImageProcessor.from_pretrained("facebook/detr-resnet-50", backend="torchvision")
device 인자로 처리가 수행될 장치를 제어합니다. 입력이 텐서인 경우 입력과 동일한 장치에서 처리가 수행되고, 그렇지 않으면 CPU로 대체됩니다. 아래 예시는 가속기에서 처리를 실행합니다.
import torch
from torchvision.io import read_image
from transformers import DetrImageProcessor
device = torch.accelerator.current_accelerator().type if torch.accelerator.is_available() else "cpu"
images = read_image("image.jpg")
processor = DetrImageProcessor.from_pretrained("facebook/detr-resnet-50")
images_processed = processor(images, return_tensors="pt", device=device)
벤치마크
벤치마크는 NVIDIA A10G Tensor Core GPU를 갖춘 AWS EC2 g5.2xlarge 인스턴스에서 얻은 것입니다.
동적 해상도
대부분의 이미지 프로세서는 모든 이미지를 하나의 고정 해상도로 크기 조정합니다. 동적 해상도(dynamic resolution)는 일부 모델이 원본 종횡비를 유지하고 전처리된 데이터의 양이 이미지에 따라 늘어나도록 하여, 작은 아이콘보다 세부 사진에서 더 많은 패치를 얻고 모델이 볼 것이 있는 곳에 계산을 집중하게 합니다.
이미지를 어떻게 분할하는지는 모델별로 다릅니다. 일부 모델은 min_patches, max_patches 같은 파라미터로 경계가 정해진 가변 개수의 고정 크기 패치로 이미지를 자릅니다. 다른 모델은 미리 정의된 종횡비 목록에서 선택하거나 픽셀 예산에서 파생하여 이미지에 가장 잘 맞는 해상도로 크기를 조정합니다.
파라미터, 기본값, 출력 형태는 모델의 문서 페이지를 참조하세요.
전처리
Transformers의 비전 모델은 입력을 픽셀 값의 PyTorch 텐서로 기대합니다. 이미지 프로세서는 이미지를 픽셀 값으로 변환하며, 픽셀 값은 배치 크기, 채널 수, 높이, 너비로 나타냅니다. 이를 위해 이미지가 (중심 자르기와 함께) 크기 조정되고, 픽셀 값은 모델이 기대하는 값으로 정규화 및 재조정됩니다.
이미지 전처리(image preprocessing)는 *이미지 증강(image augmentation)*과 동일하지 않습니다. 이미지 증강은 새로운 훈련 예시를 만들거나 과적합을 방지하기 위해 이미지에 (밝기, 색상, 회전 등) 변경을 가합니다. 이미지 전처리는 사전 훈련 모델이 기대하는 입력 형식과 일치시키기 위해 이미지에 변경을 가합니다.
일반적으로 이미지는 (성능 향상을 위해) 증강된 다음 모델에 전달되기 전에 전처리됩니다. 증강에는 어떤 라이브러리든(Albumentations, Kornia) 사용하고, 전처리에는 이미지 프로세서를 사용할 수 있습니다.
이 가이드는 증강에 torchvision transforms 모듈을 사용합니다.
먼저 food101 데이터셋에서 작은 샘플을 로드합니다.
from datasets import load_dataset
dataset = load_dataset("ethz/food101", split="train[:100]")
transforms 모듈에서 Compose API를 사용해 RandomResizedCrop과 ColorJitter을 연결합니다. 이러한 변환은 이미지를 무작위로 자르고 크기를 조정하며, 이미지의 색상을 무작위로 조정합니다.
무작위로 자를 이미지 크기는 이미지 프로세서에서 가져올 수 있습니다. 일부 모델은 정확한 높이와 너비를 기대하는 반면, 다른 모델은 shortest_edge만 필요합니다.
from torchvision.transforms import RandomResizedCrop, ColorJitter, Compose
size = (
image_processor.size["shortest_edge"]
if "shortest_edge" in image_processor.size
else (image_processor.size["height"], image_processor.size["width"])
)
_transforms = Compose([RandomResizedCrop(size), ColorJitter(brightness=0.5, hue=0.5)])
이미지에 변환을 적용하고 RGB 형식으로 변환합니다. 그런 다음 증강된 이미지를 이미지 프로세서에 전달해 픽셀 값을 반환합니다.
증강 단계에서 RandomResizedCrop이 이미 이미지 크기를 조정했으므로 do_resize 파라미터는 False로 설정됩니다. 이미지를 증강하지 않으면 이미지 프로세서가 image_mean과 image_std 값으로 이미지를 자동으로 크기 조정하고 정규화합니다. 이 값들은 전처리 설정 파일에서 찾을 수 있습니다.
def transforms(examples):
images = [_transforms(img.convert("RGB")) for img in examples["image"]]
examples["pixel_values"] = image_processor(images, do_resize=False, return_tensors="pt")["pixel_values"]
return examples
set_transform을 사용해 결합된 증강 및 전처리 함수를 전체 데이터셋에 즉시 적용합니다.
dataset.set_transform(transforms)
이미지가 어떻게 증강되고 전처리되었는지 확인하려면 픽셀 값을 다시 이미지로 변환합니다.
import numpy as np
import matplotlib.pyplot as plt
img = dataset[0]["pixel_values"]
plt.imshow(img.permute(1, 2, 0))
객체 탐지나 분할 같은 다른 비전 작업의 경우, 이미지 프로세서는 모델의 원시 출력을 경계 상자(bounding box)나 분할 맵(segmentation map) 같은 의미 있는 예측으로 변환하는 후처리 메서드를 포함합니다.
패딩
DETR 같은 일부 모델은 훈련 중 스케일 증강을 적용하여 배치 내 이미지 크기가 서로 달라질 수 있습니다. 크기가 다른 이미지는 함께 배치할 수 없습니다.
이 문제를 해결하려면 특수 패딩 토큰 0으로 이미지를 패딩합니다. pad 메서드를 사용해 이미지를 패딩하고, 커스텀 collate 함수를 정의해 함께 배치합니다.
def collate_fn(batch):
pixel_values = [item["pixel_values"] for item in batch]
encoding = image_processor.pad(pixel_values, return_tensors="pt")
labels = [item["labels"] for item in batch]
batch = {}
batch["pixel_values"] = encoding["pixel_values"]
batch["pixel_mask"] = encoding["pixel_mask"]
batch["labels"] = labels
return batch