지난 글에서는 RTX 5070 Ti 환경에서 Conda와 PyTorch를 설치하고, Python으로 여행 사진을 전처리하는 과정을 진행했습니다.
이번에는 본격적으로 AI 모델을 이용해 사진 속 특정 객체를 추출하는 작업을 진행했습니다.
사용한 모델은 Meta에서 공개한 SAM 2.1(Segment Anything Model 2) 입니다.
최종 목표는 여행 사진에서 장소의 특징을 추출하고, 이를 추상화된 일러스트로 변환해 하나의 여행 포스터를 만드는 것입니다.
이번 실습에서는 여행 중 촬영한 전통 정자 사진을 이용해 건축물의 영역을 추출하고, 배경이 투명한 PNG 이미지로 저장하는 것까지 진행했습니다.
설치 과정에서 예상하지 못했던 문제와 Python 코드 오류도 발생했는데, 해결 과정을 함께 정리해 보겠습니다.
1. SAM 2란 무엇일까?
SAM 2는 Meta에서 공개한 이미지 및 동영상 분할(Segmentation) 모델입니다.
이미지 분할은 사진에서 특정 객체가 차지하는 영역을 픽셀 단위로 구분하는 기술입니다.
예를 들어 정자가 있는 사진에서 정자를 선택하면, AI 모델이 정자에 해당하는 영역을 추출합니다.
일반적인 객체 탐지(Object Detection)가 객체의 위치를 사각형으로 표시한다면, 이미지 분할은 객체의 실제 형태에 가까운 마스크를 생성한다는 차이가 있습니다.
이번에는 SAM 2.1 Large 모델을 사용했습니다.
| 항목 | 개발환경 |
| 운영체제 | Ubuntu |
| GPU | NVIDIA RTX 5070 Ti 16GB |
| Python | 3.11 |
| AI 프레임워크 | PyTorch |
| 모델 | SAM 2.1 Large |
| 이미지 처리 | OpenCV, Pillow, NumPy |
SAM 2.1 Large는 약 2억 2,440만 개의 파라미터를 가진 모델입니다.
모바일에서 직접 실행하기에는 부담이 있을 수 있지만, 현재는 이미지 품질이 우선이므로 데스크탑에서 Large 모델부터 실험하기로 했습니다.
2. SAM 2.1 설치하기
GitHub 저장소 다운로드
먼저 기존 Conda 가상환경을 활성화합니다.
프로젝트 폴더로 이동해 SAM 2 공식 저장소를 다운로드합니다.
cd ~/project/travel-illustration-ai
mkdir -p external
cd external
git clone https://github.com/facebookresearch/sam2.git
다운로드한 소스는 external/sam2 디렉터리에서 관리합니다.
SAM 2 설치
SAM 2 디렉터리로 이동합니다.
cd sam2
다음 명령어로 설치를 진행했습니다.
SAM2_BUILD_CUDA=0 python -m pip install -e .
SAM2_BUILD_CUDA=0 옵션은 SAM 2의 선택적인 CUDA 확장 기능을 컴파일하지 않도록 지정하는 설정입니다.
GPU 추론 자체를 비활성화하는 것은 아닙니다. 다만 CUDA 확장에서 제공하는 일부 마스크 후처리 기능은 사용할 수 없게 됩니다.
이번 실습에서는 복잡한 CUDA 빌드 환경을 구성하지 않고 먼저 모델 추론에 성공하는 것을 목표로 했습니다.
설치 중 아무런 반응이 없었던 문제
설치 명령어를 실행했는데 한동안 콘솔에 새로운 메시지가 출력되지 않았습니다.
처음에는 설치가 멈춘 것으로 생각했습니다.
프로세스 상태를 확인하기 위해 다른 터미널에서 다음 명령어를 실행했습니다.
ps aux | grep -E 'pip|python|gcc|ninja' | grep -v grep
실행 중인 프로세스에서 다음과 같은 명령을 확인할 수 있었습니다.
python -m pip install -e .
pip install --prefix /tmp/pip-build-env-...
setuptools>=61.0 torch>=2.5.1
pip이 격리된 빌드 환경을 생성하고 의존성 패키지를 설치하는 과정이었습니다.
CPU 상태도 확인했습니다.
top
CPU 사용률은 거의 0%였지만, 이것만으로 설치가 중단되었다고 판단할 수는 없었습니다.
실제로 설치 명령어를 종료하지 않고 확인해 보니 정상적으로 설치가 완료되었습니다.
이번에 알게 된 점은 pip 설치 과정에서 콘솔 출력이 없거나 CPU 사용량이 낮다고 해서 반드시 프로그램이 멈춘 것은 아니라는 사실입니다.
비슷한 상황이 발생한다면 무조건 설치를 중단하기보다 현재 실행 중인 프로세스와 네트워크 상태를 먼저 확인하는 것이 좋겠습니다.
참고로 빌드 격리 때문에 문제가 발생하는 환경에서는 다음 옵션을 검토할 수 있습니다.
SAM2_BUILD_CUDA=0 python -m pip install \
--no-build-isolation \
-v \
-e .
--no-build-isolation은 기존 Python 환경을 사용해 빌드하도록 하고, -v는 상세한 설치 로그를 출력합니다.
단, 이번에는 해당 명령어로 재설치하지 않고 기존 설치가 정상적으로 완료되었습니다.
설치 결과 확인
다음 명령어로 SAM 2가 정상적으로 설치되었는지 확인했습니다.
python -c "from sam2.sam2_image_predictor import SAM2ImagePredictor; print('SAM2 설치 성공')"
실행 결과:
SAM2 설치 성공
이것으로 모델을 실행하기 위한 첫 번째 준비가 끝났습니다.
3. SAM 2.1 Large 모델 다운로드
SAM 2를 설치했다고 해서 학습된 모델 가중치까지 모두 준비되는 것은 아닙니다.
모델을 실행하려면 사전 학습된 가중치 파일이 필요합니다.
SAM 2.1 Large 모델의 가중치를 다운로드했습니다.
cd ~/project/travel-illustration-ai/external/sam2
wget -c \
https://dl.fbaipublicfiles.com/segment_anything_2/092824/sam2.1_hiera_large.pt \
-O checkpoints/sam2.1_hiera_large.pt
다운로드한 모델은 다음 경로에 저장됩니다.
external/sam2/checkpoints/sam2.1_hiera_large.pt
모델 설정 파일은 다음 경로를 사용합니다.
configs/sam2.1/sam2.1_hiera_l.yaml
모델 설정 파일은 신경망 구조를 정의하고, .pt 파일은 학습된 파라미터를 저장합니다.
두 파일이 서로 대응하는 모델이어야 정상적으로 가중치를 불러올 수 있습니다.
4. Python으로 이미지 객체 추출하기
이제 실제 여행 사진에서 정자 영역을 추출해 보겠습니다.
입력 이미지는 이전 글에서 전처리한 파일을 사용합니다.
datasets/processed/DSC05133.png

이번 실습에 사용한 이미지 크기는 다음과 같습니다.
(1024, 576, 3)
NumPy 이미지 배열은 (높이, 너비, 채널) 순서이므로 가로 576픽셀, 세로 1024픽셀의 RGB 이미지입니다.
SAM 2 모델 불러오기
파일 위치: src/inference/segment_image.py
먼저 필요한 라이브러리를 불러옵니다.
from pathlib import Path
import cv2
import numpy as np
import torch
from PIL import Image
from sam2.build_sam import build_sam2
from sam2.sam2_image_predictor import SAM2ImagePredictor
모델 경로와 설정 파일을 지정합니다.
PROJECT_ROOT = Path(__file__).resolve().parents[2]
MODEL_PATH = (
PROJECT_ROOT
/ "external/sam2/checkpoints/sam2.1_hiera_large.pt"
)
MODEL_CONFIG = "configs/sam2.1/sam2.1_hiera_l.yaml"
모델 로드 함수는 다음과 같이 작성했습니다.
def load_model():
device = "cuda" if torch.cuda.is_available() else "cpu"
print("사용 장치:", device)
if device != "cuda":
raise RuntimeError(
"CUDA GPU를 사용할 수 없습니다."
)
model = build_sam2(
MODEL_CONFIG,
str(MODEL_PATH),
device=device
)
return SAM2ImagePredictor(model)
PyTorch에서 CUDA 사용 가능 여부를 확인하고 SAM 2 모델을 GPU에 로드합니다.
이번에는 RTX 5070 Ti에서 정상적으로 모델이 실행되었습니다.
마우스로 객체 영역 선택
SAM 2는 점이나 박스 등의 정보를 이용해 분할할 객체를 지정할 수 있습니다.
이번에는 OpenCV의 selectROI()를 이용했습니다.
파일 위치: src/inference/segment_image.py
def select_object(image):
image_bgr = cv2.cvtColor(
image,
cv2.COLOR_RGB2BGR
)
x, y, w, h = cv2.selectROI(
"Select Object",
image_bgr,
showCrosshair=True,
fromCenter=False
)
cv2.destroyAllWindows()
if w == 0 or h == 0:
raise ValueError("영역이 선택되지 않았습니다.")
return np.array(
[x, y, x + w, y + h],
dtype=np.float32
)
프로그램을 실행하면 이미지 선택 창이 나타납니다.
마우스로 정자 전체를 감싸는 사각형을 선택하고 Enter를 누르면 선택한 좌표가 반환됩니다.
실제 실행 결과는 다음과 같았습니다.
선택 영역: [111. 357. 570. 650.]
이 좌표는 이미지 안에서 선택한 사각형의 좌측 상단과 우측 하단 위치를 나타냅니다.

SAM 2 이미지 분할 실행
선택한 영역을 모델에 전달해 실제 이미지 분할을 실행합니다.
파일 위치: src/inference/segment_image.py
with torch.inference_mode():
with torch.autocast(
device_type="cuda",
dtype=torch.bfloat16
):
predictor.set_image(image)
masks, scores, logits = predictor.predict(
box=box,
multimask_output=True
)
best_index = np.argmax(scores)
best_mask = masks[best_index]
torch.inference_mode()는 추론 과정에서 불필요한 그래디언트 계산을 비활성화합니다.
torch.autocast()는 GPU에서 일부 연산에 BF16을 활용하도록 설정합니다.
multimask_output=True는 여러 후보 마스크를 생성하도록 하는 옵션입니다.
각 마스크에는 모델이 추정한 품질 점수가 함께 반환됩니다.
이번에 출력된 점수는 다음과 같았습니다.
사용 장치: cuda
마스크 점수: 0.82421875
이 점수가 실제 객체 추출 정확도 82.4%를 의미하는 것은 아닙니다.
SAM 2가 예측한 마스크 품질에 대한 추정 점수이므로 실제 결과물과 비교하는 과정이 필요합니다.
5. 이미지 저장 과정에서 발생한 IndexError
모델 추론은 정상적으로 완료되었지만, 결과 이미지를 저장하는 과정에서 오류가 발생했습니다.
오류 메시지는 다음과 같았습니다.
IndexError: arrays used as indices must be
of integer (or boolean) type
문제가 발생한 코드는 다음 부분이었습니다.
파일 위치: src/inference/segment_image.py
overlay[mask] = (
0.6 * image[mask]
+ 0.4 * np.array([255, 0, 0])
).astype(np.uint8)
여기서 문제는 image[mask]입니다.
NumPy 배열에서 마스크를 이용해 특정 픽셀을 선택할 때는 불리언 배열이나 정수 인덱스를 사용해야 합니다.
그런데 전달된 마스크가 해당 인덱싱에 적합한 자료형이 아니어서 오류가 발생한 것입니다.
해결 방법
마스크를 명시적으로 Boolean 자료형으로 변환했습니다.
mask = np.asarray(mask) > 0
수정 후에는 해당 부분이 정상적으로 실행되었습니다.
다만 이 코드는 0과 1로 표현된 이진 마스크를 전제로 합니다. 마스크가 연속적인 확률값이나 로짓이라면 적절한 임계값을 별도로 지정해야 합니다.
수정한 결과 저장 코드
파일 위치: src/inference/segment_image.py
def save_results(image, mask):
OUTPUT_DIR.mkdir(
parents=True,
exist_ok=True
)
# Boolean 마스크로 변환
mask = np.asarray(mask) > 0
# 마스크를 이미지 저장용 값으로 변환
mask_uint8 = mask.astype(np.uint8) * 255
# 1. 마스크 이미지 저장
Image.fromarray(mask_uint8).save(
OUTPUT_DIR / "mask.png"
)
# 2. 원본 이미지에 마스크 표시
overlay = image.copy()
overlay[mask] = (
0.6 * image[mask]
+ 0.4 * np.array([255, 0, 0])
).astype(np.uint8)
Image.fromarray(overlay).save(
OUTPUT_DIR / "overlay.png"
)
# 3. 투명 배경 이미지 생성
rgba = np.dstack(
[image, mask_uint8]
)
Image.fromarray(rgba).save(
OUTPUT_DIR / "subject.png"
)
처음에는 모델 추론에 문제가 있는 것으로 생각할 수 있지만, 실제로는 AI 모델의 문제가 아니라 NumPy 배열의 자료형 문제였습니다.
모델 개발에서는 추론 과정과 결과 후처리 과정을 구분해서 확인해야 한다는 점을 알 수 있었습니다.
6. OpenCV에서 발생한 Qt 폰트 경고
이미지 선택 창을 실행할 때 다음 메시지도 반복해서 출력되었습니다.
QFontDatabase: Cannot find font directory
...
Note that Qt no longer ships fonts.
OpenCV의 GUI에서 사용하는 Qt 라이브러리가 폰트 디렉터리를 찾지 못해 발생하는 경고입니다.
이번 환경에서는 이미지 선택 창이 정상적으로 표시되었고 마우스 입력도 가능했습니다.
따라서 SAM 2의 이미지 분할 기능에는 직접적인 영향을 주지 않았습니다.
경고 메시지가 나타난다고 해서 반드시 프로그램 실행이 실패한 것은 아닙니다.
문제가 발생한 기능과 경고 메시지의 관련성을 먼저 확인하는 것이 중요하겠습니다.
7. SAM 2 이미지 분할 실행 결과
오류를 수정한 후 프로그램을 다시 실행했습니다.
cd ~/project/travel-illustration-ai
conda activate travel-ai
python src/inference/segment_image.py
정상적으로 실행되었고, 다음 세 가지 결과 파일이 생성되었습니다.
outputs/
└── segmentation/
├── mask.png
├── overlay.png
└── subject.png
① mask.png — 객체 영역 마스크
마스크 이미지는 AI가 추출한 객체의 영역을 흑백으로 나타냅니다.
- 흰색: 추출한 정자 영역
- 검은색: 배경 영역

② overlay.png — 분할 영역 확인
원본 이미지 위에 추출한 영역을 붉은색으로 표시합니다.
마스크가 실제 정자의 지붕과 기둥, 난간을 얼마나 잘 포함하는지 확인할 수 있습니다.

③ subject.png — 배경이 투명한 이미지
마스크를 Alpha 채널로 사용해 객체를 제외한 영역을 투명하게 처리했습니다.

이 이미지는 이후 여행 포스터에 들어갈 독립적인 그래픽 요소로 활용할 수 있습니다.
실제로 세 파일 모두 정상적으로 생성되었고, 결과물을 확인했을 때 이번 실습의 목적에 맞는 이미지가 만들어졌습니다.
아직 최종 목표인 추상화 일러스트는 아니지만, 사진 속 주요 피사체를 AI로 분리하는 첫 번째 과정에 성공한 것입니다.
8. 이번 실습을 마치며
이번에는 공개 AI 모델인 SAM 2.1을 직접 설치하고, GPU를 이용해 여행 사진에서 정자 영역을 추출했습니다.
진행하면서 두 가지 문제를 경험했습니다.
첫 번째는 설치 과정에서 콘솔 출력이 멈춘 것처럼 보였던 현상입니다.
실제로는 pip이 의존성 패키지를 설치하고 있었으며, 결과적으로 설치가 정상 완료되었습니다.
두 번째는 이미지 저장 과정에서 발생한 NumPy IndexError입니다.
마스크를 Boolean 자료형으로 변환해 해결할 수 있었습니다.
처음 사용하는 AI 모델이다 보니 설치부터 실행까지 모든 과정이 익숙하지는 않았지만, 실제 코드를 실행하고 오류를 해결하면서 모델의 동작 방식을 조금씩 이해할 수 있었습니다.
특히 이번 실습을 통해 다음과 같은 처리 구조를 확인했습니다.
여행 사진
↓
객체 영역 선택
↓
SAM 2 이미지 분할
↓
객체 마스크 생성
↓
배경 분리
↓
투명 PNG 이미지 저장
다음 단계에서는 추출한 객체를 바탕으로 색상과 형태를 단순화하는 이미지 추상화(Image Abstraction) 작업을 진행할 예정입니다.
최종 목표는 단순한 배경 제거가 아니라 사진의 특징을 유지하면서도 간결하고 통일감 있는 일러스트를 만드는 것입니다.
앞으로 공개 이미지 생성 모델도 비교해 보면서 여행 사진에 적합한 추상화 모델을 직접 만들어 보고자 합니다.
참고 자료
RTX 5070 Ti로 시작하는 AI 이미지 모델 개발 - Conda·PyTorch 환경 구축과 이미지 전처리
AI를 활용한 서비스를 개발하다 보면 공개된 모델이나 외부 API를 사용하는 경우가 많습니다. 하지만 이번에는 직접 모델을 학습하고 모바일 기기에 탑재하는 프로젝트를 진행해 보려고 합니다.
incurio.tistory.com
'개발 & IT > 머신러닝 & 딥러닝' 카테고리의 다른 글
| RTX 5070 Ti로 시작하는 AI 이미지 모델 개발 - Conda·PyTorch 환경 구축과 이미지 전처리 (0) | 2026.10.28 |
|---|---|
| AI 코딩 에이전트가 CUDA를 10시간 만에 대체했다? 실제 성과와 과장된 해석 (0) | 2026.08.06 |
| Kimi K3 내 컴퓨터에서 돌릴 수 있을까? 현실적인 사용 방법 (0) | 2026.07.29 |
| Jetson Orin Nano 가장 쉽게 시작하는 법: 점퍼·USB 없이 SD카드 하나로 끝내는 설치법 (0) | 2026.01.16 |
| “AI 모델을 만든다”는 말, 도대체 무슨 뜻일까? (1) | 2025.12.31 |






















































