🤖 AI/ML

Segment Anything

SAM (Segment Anything Model)

Meta AI에서 개발한 범용 이미지 분할 Foundation Model입니다. 점, 박스, 텍스트 등 다양한 프롬프트로 어떤 객체든 분할할 수 있으며, SAM 2는 비디오 분할까지 지원합니다.

📖 상세 설명

Segment Anything Model(SAM)은 2023년 Meta AI에서 발표한 범용 이미지 분할(Segmentation) Foundation Model입니다. 기존 세그멘테이션 모델들이 특정 도메인(의료, 자율주행 등)에 특화되어 학습되었던 것과 달리, SAM은 11억 개 이상의 마스크(SA-1B 데이터셋)로 학습되어 어떤 종류의 이미지에서도 객체를 분할할 수 있는 "제로샷(Zero-shot)" 능력을 갖추고 있습니다.

SAM의 핵심 아키텍처는 세 가지 컴포넌트로 구성됩니다. Image Encoder는 ViT(Vision Transformer) 기반으로 이미지를 고차원 임베딩으로 변환합니다. Prompt Encoder는 점(point), 박스(box), 마스크, 텍스트 등 다양한 형태의 프롬프트를 처리합니다. Mask Decoder는 이미지 임베딩과 프롬프트 임베딩을 결합하여 최종 세그멘테이션 마스크를 생성합니다. 이 구조 덕분에 한 번 이미지를 인코딩하면 다양한 프롬프트로 빠르게 여러 객체를 분할할 수 있습니다.

2024년 7월 발표된 SAM 2는 이미지뿐만 아니라 비디오 분할까지 지원하는 확장 버전입니다. Streaming Memory Architecture를 도입하여 비디오 프레임 간 시간적 연속성을 유지하면서 객체를 추적합니다. SAM 2는 기존 SAM 대비 이미지 분할에서 6배 더 높은 정확도를 달성했으며, 실시간으로 약 44 FPS의 추론 속도를 보여줍니다. 또한 2024년 9월에는 SAM 2.1이 출시되어 시각적으로 유사한 객체와 가려짐(occlusion) 상황에서의 성능이 더욱 개선되었습니다.

SAM의 활용 분야는 매우 다양합니다. 의료 영상에서 종양이나 장기를 분할하거나, 자율주행에서 도로와 차량을 인식하고, 전자상거래에서 제품을 배경에서 분리하는 등 다양한 산업에서 사용됩니다. 특히 라벨링 도구와 결합하면 데이터 어노테이션 시간을 8.4배 단축할 수 있어 ML 파이프라인의 생산성을 크게 향상시킵니다. Apache 2.0 라이선스로 오픈소스 공개되어 상업적 사용도 가능합니다.

💻 코드 예제

SAM을 사용하여 이미지에서 객체를 분할하는 예제입니다. 점 프롬프트를 사용하여 특정 위치의 객체를 분할합니다.

# pip install segment-anything opencv-python matplotlib torch torchvision
import numpy as np
import matplotlib.pyplot as plt
from segment_anything import sam_model_registry, SamPredictor
import cv2

# 모델 로드 (vit_h, vit_l, vit_b 중 선택)
sam_checkpoint = "sam_vit_h_4b8939.pth"  # 다운로드 필요
model_type = "vit_h"

device = "cuda"  # GPU 사용, CPU는 "cpu"
sam = sam_model_registry[model_type](checkpoint=sam_checkpoint)
sam.to(device=device)

predictor = SamPredictor(sam)

# 이미지 로드
image = cv2.imread("your_image.jpg")
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 이미지 임베딩 생성 (한 번만 실행)
predictor.set_image(image)

# 점 프롬프트로 세그멘테이션
# (x, y) 좌표, label 1=전경, 0=배경
input_point = np.array([[500, 375]])
input_label = np.array([1])

masks, scores, logits = predictor.predict(
    point_coords=input_point,
    point_labels=input_label,
    multimask_output=True,  # 여러 마스크 후보 반환
)

# 가장 높은 점수의 마스크 선택
best_mask_idx = np.argmax(scores)
best_mask = masks[best_mask_idx]

# 결과 시각화
def show_mask(mask, ax, color=(30/255, 144/255, 255/255, 0.6)):
    h, w = mask.shape[-2:]
    mask_image = mask.reshape(h, w, 1) * np.array([*color[:3], color[3]])
    ax.imshow(mask_image)

fig, ax = plt.subplots(1, 1, figsize=(10, 10))
ax.imshow(image)
show_mask(best_mask, ax)
ax.scatter(input_point[:, 0], input_point[:, 1], c='red', s=200, marker='*')
ax.set_title(f"Score: {scores[best_mask_idx]:.3f}")
ax.axis('off')
plt.savefig("segmentation_result.png", bbox_inches='tight')
plt.show()

print(f"분할된 마스크 개수: {len(masks)}")
print(f"각 마스크 점수: {scores}")

SAM 2를 사용한 비디오 세그멘테이션

# pip install sam2
import torch
from sam2.build_sam import build_sam2_video_predictor

# SAM 2 비디오 모델 로드
predictor = build_sam2_video_predictor(
    "sam2_hiera_large.yaml",
    "sam2_hiera_large.pt"
)

# 비디오 초기화
video_path = "your_video.mp4"
inference_state = predictor.init_state(video_path=video_path)

# 첫 프레임에서 객체 선택 (점 프롬프트)
frame_idx = 0
obj_id = 1
points = np.array([[500, 375]], dtype=np.float32)
labels = np.array([1], dtype=np.int32)

# 프롬프트 추가
_, out_obj_ids, out_mask_logits = predictor.add_new_points(
    inference_state=inference_state,
    frame_idx=frame_idx,
    obj_id=obj_id,
    points=points,
    labels=labels,
)

# 전체 비디오 전파
video_segments = {}
for out_frame_idx, out_obj_ids, out_mask_logits in predictor.propagate_in_video(
    inference_state
):
    video_segments[out_frame_idx] = {
        out_obj_id: (out_mask_logits[i] > 0.0).cpu().numpy()
        for i, out_obj_id in enumerate(out_obj_ids)
    }

print(f"총 {len(video_segments)} 프레임 세그멘테이션 완료")

📊 성능 & 비용

SAM과 SAM 2는 오픈소스 무료로 제공됩니다. Apache 2.0 라이선스로 상업적 사용이 가능합니다.

모델 파라미터 이미지 크기 추론 속도 (A100) VRAM
SAM ViT-B 91M 1024x1024 ~50 FPS ~4GB
SAM ViT-L 308M 1024x1024 ~35 FPS ~8GB
SAM ViT-H 636M 1024x1024 ~20 FPS ~16GB
SAM 2 Tiny 38.9M 1024x1024 ~47 FPS ~3GB
SAM 2 Small 46M 1024x1024 ~44 FPS ~4GB
SAM 2 Large 224.4M 1024x1024 ~30 FPS ~8GB

성능 비교 (벤치마크)

지표 SAM (ViT-H) SAM 2 (Large) 비고
이미지 분할 정확도 Baseline 6x 향상 Meta 공식 벤치마크
비디오 분할 J&F 미지원 SOTA SA-V 데이터셋
어노테이션 속도 빠름 8.4x 빠름 수동 대비
실시간 처리 가능 (30+ FPS) 가능 (44 FPS) A100 기준

🗣️ 실무에서 이렇게 말하세요

올바른 표현

"이미지 라벨링 시간을 줄이려면 SAM으로 세미-오토 어노테이션을 도입해보죠. 점 몇 개만 찍으면 마스크가 자동 생성됩니다."

올바른 표현

"비디오에서 객체 추적이 필요하면 SAM 2를 써보세요. 첫 프레임에서 객체 선택하면 나머지 프레임은 자동으로 전파됩니다."

부정확한 표현

"SAM이 알아서 모든 객체를 분류해줍니다." → SAM은 세그멘테이션 모델로, 객체 "분류(Classification)"는 하지 않습니다. 마스크만 생성합니다.

⚠️ 흔한 실수 & 주의사항

  • 프롬프트 위치가 중요: 점 프롬프트는 객체 중심부에 찍어야 정확한 마스크를 얻습니다. 경계 근처는 모호한 결과를 낼 수 있습니다.
  • multimask_output 활용: 모호한 경우 여러 마스크 후보를 반환하므로, scores를 확인하여 최적의 마스크를 선택하세요.
  • 이미지 인코딩 캐싱: set_image()는 한 번만 호출하고, 여러 프롬프트로 predict()를 반복 호출하면 효율적입니다.
  • GPU 메모리: ViT-H 모델은 16GB+ VRAM이 필요합니다. 메모리가 부족하면 ViT-B나 SAM 2 Tiny를 사용하세요.
  • SAM은 분류하지 않음: 마스크만 생성하고 "이것이 무엇인지"는 알려주지 않습니다. 분류가 필요하면 별도 모델과 결합하세요.
  • SAM 2 비디오 긴 시퀀스: 장시간 비디오에서는 메모리 누적과 드리프트가 발생할 수 있습니다. 주기적인 재초기화를 고려하세요.

🔗 관련 용어

📚 더 배우기