개요

ImageTransform은 이미지 전처리를 담당하는 클래스로, 학습 데이터의 다양성을 높여 모델의 일반화 성능을 향상시킵니다.


ImageTransform 클래스 구조

from torchvision import transforms
 
class ImageTransform:
    def __init__(self, resize, mean, std):
        """학습/검증용 변환 정의"""
        self.data_transform = {
            'train': transforms.Compose([...]),  # 증강 O
            'val': transforms.Compose([...])      # 증강 X
        }
    
    def __call__(self, img, phase):
        """입력 이미지에 변환 적용"""
        return self.data_transform[phase](img)

주요 구성 요소

요소역할
__init__train/val 변환 파이프라인 정의
data_transformphase별 변환 체인 저장 (딕셔너리)
__call__이미지를 받아 변환 적용 후 반환

Train vs Val 변환 차이

핵심 차이점

구분TrainValidation
목적다양한 데이터로 학습일관된 조건에서 평가
증강적용미적용
무작위성있음 (랜덤 변환)없음 (고정 변환)
크롭 방식RandomResizedCropCenterCrop

왜 이렇게 구분하나?

Train 모드:

  • 모델이 다양한 변형 이미지를 학습하여 일반화 능력 향상
  • 과적합(overfitting) 방지
  • 실제 환경의 다양한 상황 시뮬레이션 Val 모드:
  • 공정한 비교를 위해 매번 동일한 조건에서 평가
  • 무작위성이 있으면 평가 결과가 매번 달라짐
  • 모델의 실제 성능을 정확히 측정

Train 변환 파이프라인 (증강 적용)

'train': transforms.Compose([
    transforms.Resize(256),
    transforms.RandomResizedCrop(resize, scale=(0.5, 1.0)),
    transforms.RandomHorizontalFlip(),
    transforms.RandomRotation(45),
    transforms.ColorJitter(brightness=0.5, contrast=0.5, saturation=0.5),
    transforms.RandomGrayscale(p=0.1),
    transforms.ToTensor(),
    transforms.Normalize(mean, std)
])

1️. Resize(256)

transforms.Resize(256)
  • 역할: 이미지의 짧은 변을 256픽셀로 조정
  • 예시:
    • 입력: 1000×800 → 출력: 320×256
    • 입력: 600×900 → 출력: 256×384
  • 목적: 이후 크롭을 위한 여유 공간 확보

2️. RandomResizedCrop(resize, scale=(0.5, 1.0))

transforms.RandomResizedCrop(resize, scale=(0.5, 1.0))
  • 역할: 랜덤한 영역을 잘라내고 지정된 크기로 리사이즈
  • 동작:
    1. 이미지의 50%~100% 크기 영역을 랜덤 선택
    2. 선택된 영역을 resize 크기로 확대/축소
  • 효과:
    • 객체의 다양한 크기 학습 (줌인/줌아웃)
    • 위치 변화 학습

3️. RandomHorizontalFlip()

transforms.RandomHorizontalFlip()
  • 역할: 50% 확률로 좌우 반전
  • 효과: 좌우 대칭성 학습
  • 예시:
    • 왼쪽 바라보는 강아지 → 오른쪽 바라보는 강아지

4️. RandomRotation(45)

transforms.RandomRotation(45)
  • 역할: -45° ~ +45° 범위에서 랜덤 회전
  • 효과: 다양한 각도의 객체 학습
  • 주의: 너무 큰 각도는 이미지 왜곡 가능

5️. ColorJitter(brightness=0.5, contrast=0.5, saturation=0.5)

transforms.ColorJitter(brightness=0.5, contrast=0.5, saturation=0.5)
  • 역할: 색상 관련 속성을 랜덤하게 변경
  • 파라미터:
    • brightness=0.5: 밝기 ±50% 변경
    • contrast=0.5: 대비 ±50% 변경
    • saturation=0.5: 채도 ±50% 변경
  • 효과: 다양한 조명 환경 학습
    • 밝은 환경, 어두운 환경
    • 흐린 날씨, 맑은 날씨

6️. RandomGrayscale(p=0.1)

transforms.RandomGrayscale(p=0.1)
  • 역할: 10% 확률로 흑백 변환 (RGB 채널 수 유지)
  • 주의: 완전히 흑백으로 변환되지만 채널은 3개 유지 (R=G=B)
  • 효과: 색상에 과도하게 의존하지 않도록 학습

7️. ToTensor()

transforms.ToTensor()
  • 역할: PIL Image 또는 numpy.ndarray를 PyTorch Tensor로 변환
  • 변환 내용:
    • 데이터 타입: uint8 (0255) → float32 (0.01.0)
    • 차원 순서: (H, W, C)(C, H, W)
    • 범위: [0, 255][0.0, 1.0] (자동 스케일링) 변환 예시:
PIL Image (H×W×C)          Tensor (C×H×W)
[0, 255, 128]       →      [0.0, 1.0, 0.502]
(224, 224, 3)       →      (3, 224, 224)

8️. Normalize(mean, std)

transforms.Normalize(mean, std)
  • 역할: 평균과 표준편차로 정규화
  • 공식: output = (input - mean) / std
  • 일반적인 값 (ImageNet 기준):
    mean = [0.485, 0.456, 0.406]  # RGB 각 채널std = [0.229, 0.224, 0.225]
  • 효과:
    • 학습 안정성 향상
    • 그래디언트 소실/폭발 방지
    • 사전학습 모델과 동일한 분포로 맞춤 정규화 예시:
# R 채널 예시
input = 0.8
normalized = (0.8 - 0.485) / 0.229 = 1.376

Val 변환 파이프라인 (증강 미적용)

'val': transforms.Compose([
    transforms.Resize(256),
    transforms.CenterCrop(resize),
    transforms.ToTensor(),
    transforms.Normalize(mean, std)
])

주요 차이점

변환TrainVal
크롭RandomResizedCropCenterCrop
반전RandomHorizontalFlip
회전RandomRotation
색상ColorJitter
흑백RandomGrayscale

CenterCrop(resize)

transforms.CenterCrop(resize)
  • 역할: 이미지 중앙 영역을 정확히 잘라냄
  • 특징: 항상 동일한 위치 크롭 (무작위성 없음)
  • 목적: 평가 시 일관성 유지

call 메서드: 변환 실행

def __call__(self, img, phase):
    """입력 이미지에 변환 적용"""
    return self.data_transform[phase](img)

동작 원리

  1. phase 파라미터로 변환 선택
    • phase='train' → 증강 적용
    • phase='val' → 증강 미적용
  2. Compose 체인 실행
    # 내부 동작 (의사 코드)
    img = transforms.Resize(256)(img)
    img = transforms.RandomResizedCrop(resize)(img)
    img = transforms.RandomHorizontalFlip()(img)
    # ... (이어서)
    return img
  3. 호출 예시
    transform = ImageTransform(224, mean, std)
     
    # 학습용 변환
    train_img = transform(original_img, 'train')  # 증강 O
     
    # 검증용 변환
    val_img = transform(original_img, 'val')      # 증강 X

전체 변환 흐름도

입력 이미지 (PIL Image)
        ↓
    [phase 선택]
        ↓
┌───────┴───────┐
│               │
▼               ▼
[Train]         [Val]
│               │
Resize          Resize
RandomCrop      CenterCrop
Flip            (증강 없음)
Rotation        
ColorJitter     
Grayscale       
│               │
└───────┬───────┘
        ↓
    ToTensor
        ↓
    Normalize
        ↓
출력 텐서 (C×H×W, float32)

핵심 포인트 정리

Transform의 역할

  1. 전처리: 이미지를 모델 입력 형태로 변환
  2. 증강: 학습 데이터의 다양성 확보
  3. 정규화: 학습 안정성 향상

Train vs Val 구분 이유

  • Train: 다양한 변형으로 일반화 능력 향상
  • Val: 일관된 조건으로 공정한 평가

변환 순서의 중요성

1. Resize → 크기 조정
2. Crop → 필요 영역 추출
3. Augmentation → 증강 적용
4. ToTensor → 텐서 변환
5. Normalize → 정규화 (마지막!)

실제 사용 위치

  • Transform 생성: create_dataloaders() 함수에서
  • Transform 저장: Dataset.__init__() 메서드에서
  • Transform 실행: Dataset.__getitem__() 메서드에서 ✨