Skip to main content

Faster R-CNN — Two-stage 객체 탐지의 표준

Faster R-CNN은 Region Proposal Network(RPN)를 도입하여 영역 제안과 분류를 단일 네트워크로 통합한 Two-stage 탐지 모델입니다. YOLO보다 느리지만 정밀도가 높아 연구와 정밀 탐지에 활용됩니다.

핵심 아이디어

R-CNN 계열은 “어디에 객체가 있을까?”(영역 제안)와 “무슨 객체인가?”(분류)를 2단계로 나누어 수행합니다. Faster R-CNN은 영역 제안을 별도의 알고리즘(Selective Search) 대신 학습 가능한 RPN으로 대체하여 속도와 성능을 모두 개선했습니다.

동작 방식

RPN (Region Proposal Network)

RPN은 특징맵 위를 슬라이딩하며 각 위치에서 앵커(Anchor) 박스들이 객체인지 배경인지 판단합니다. 객체일 가능성이 높은 영역을 제안(Proposal)합니다.

RoI Pooling

제안된 영역은 크기가 제각각이므로, RoI Pooling으로 고정 크기(예: 7x7)로 변환한 뒤 분류와 박스 회귀를 수행합니다.

구현

torchvision Faster R-CNN

import torch
import torchvision
from torchvision.models.detection import fasterrcnn_resnet50_fpn_v2
from torchvision.models.detection.faster_rcnn import FastRCNNPredictor

# 사전학습 Faster R-CNN 로드
model = fasterrcnn_resnet50_fpn_v2(weights='DEFAULT')

# 분류 헤드를 커스텀 클래스 수로 교체
num_classes = 4  # 배경 포함
in_features = model.roi_heads.box_predictor.cls_score.in_features
model.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)

# 추론
model.eval()
dummy = torch.randn(1, 3, 800, 800)
predictions = model(dummy)

# 예측 결과 구조
for pred in predictions:
    print(f"박스: {pred['boxes'].shape}")    # [N, 4]
    print(f"레이블: {pred['labels'].shape}")  # [N]
    print(f"점수: {pred['scores'].shape}")    # [N]

커스텀 데이터셋 학습

from torch.utils.data import Dataset, DataLoader
import cv2
import json

class DetectionDataset(Dataset):
    """COCO 형식의 탐지 데이터셋입니다."""

    def __init__(self, image_dir, annotation_file, transforms=None):
        with open(annotation_file) as f:
            self.coco = json.load(f)
        self.image_dir = image_dir
        self.transforms = transforms
        self.images = self.coco['images']

    def __len__(self):
        return len(self.images)

    def __getitem__(self, idx):
        img_info = self.images[idx]
        img_path = f"{self.image_dir}/{img_info['file_name']}"
        image = cv2.imread(img_path)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        image = torch.from_numpy(image).permute(2, 0, 1).float() / 255.0

        # 해당 이미지의 어노테이션
        anns = [a for a in self.coco['annotations'] if a['image_id'] == img_info['id']]

        boxes = []
        labels = []
        for ann in anns:
            x, y, w, h = ann['bbox']
            boxes.append([x, y, x + w, y + h])
            labels.append(ann['category_id'])

        target = {
            'boxes': torch.tensor(boxes, dtype=torch.float32),
            'labels': torch.tensor(labels, dtype=torch.int64),
        }

        return image, target

# 학습 루프
model.train()
optimizer = torch.optim.SGD(model.parameters(), lr=0.005, momentum=0.9, weight_decay=0.0005)

for images, targets in train_loader:
    images = [img.to(device) for img in images]
    targets = [{k: v.to(device) for k, v in t.items()} for t in targets]

    loss_dict = model(images, targets)
    losses = sum(loss for loss in loss_dict.values())

    optimizer.zero_grad()
    losses.backward()
    optimizer.step()

관련 기술 비교

비교 항목R-CNNFast R-CNNFaster R-CNN
영역 제안Selective SearchSelective SearchRPN (학습 가능)
특징 추출개별 CNN공유 CNN공유 CNN
속도매우 느림느림보통
End-to-End불가부분완전
소형 객체가 많거나, 밀집된 객체를 정밀하게 탐지해야 할 때 Faster R-CNN이 유리할 수 있습니다. 그러나 최신 YOLO 모델들이 이 격차를 많이 줄였으며, 실무에서는 속도 때문에 YOLO를 더 자주 선택합니다.
Feature Pyramid Network(FPN)는 다중 스케일 특징맵을 구성하여 크기가 다른 객체를 효과적으로 탐지합니다. Faster R-CNN + FPN 조합이 표준이며, torchvision의 fasterrcnn_resnet50_fpn이 이 구조입니다.

참고 논문

논문학회/연도링크
Faster R-CNNNeurIPS 2015arXiv:1506.01497
Feature Pyramid Networks (FPN)CVPR 2017arXiv:1612.03144