1. 컴퓨터 비전 개요
컴퓨터 비전은 이미지나 영상에서 객체 검출, 이미지 분류, 얼굴 인식, 장면 이해 등의 작업을 수행한다. 인간의 시각 인식을 모방하는 것이 목표이며, 현재는 합성곱 신경망(CNN)이 핵심 구조로 자리 잡았다.
주요 응용 도메인
- 자율주행: 차선, 보행자, 신호등 인식
- 의료 영상 분석: CT/MRI 기반 질병 진단
- 보안 감시: 실시간 객체 및 이상 행동 감지
- 산업 검사: 불량품 탐지
주요 프레임워크
| 프레임워크 | 특징 |
|---|---|
| OpenCV | 이미지 전처리 및 전통적 비전 처리에 특화된 C++/Python 라이브러리 |
| TensorFlow | Google 개발, 대규모 배포 및 모바일 최적화에 강점 |
| PyTorch | 직관적 API, 동적 그래프, 연구 및 실험에 적합 |
| Ultralytics | YOLO 계열 모델에 특화된 고수준 학습/추론 API 제공 |
2. 컴퓨터 비전 데이터셋
딥러닝 모델의 성능은 데이터의 양과 질에 직접적으로 좌우된다. 모델이 학습하는 패턴의 다양성은 데이터셋이 결정하며, 편향되거나 불균형한 데이터는 과적합이나 특정 클래스에 대한 낮은 재현율로 이어진다.
대표 공개 데이터셋
COCO (Common Objects in Context)
Microsoft가 공개한 대규모 멀티태스크 데이터셋이다. 약 33만 장의 이미지와 150만 개 이상의 객체 주석을 포함하며, 80개 클래스를 지원한다. 바운딩 박스, 폴리곤 세그멘테이션, 키포인트, 캡션을 동시에 제공하는 것이 특징이다. 매년 COCO Challenge를 통해 최신 모델들이 벤치마킹된다.
Open Images Dataset (Google)
900만 장 이상의 이미지와 6억 개 이상의 바운딩 박스 주석을 포함하며 약 600개 클래스를 제공한다. 실제 웹에서 수집된 이미지이기 때문에 배경 다양성이 매우 높다. 객체 관계 주석(Visual Relationship), 행동 태그, 랜드마크 정보도 포함된다.
KITTI
독일 카를스루에 공과대학과 Toyota 기술연구소가 제공한 자율주행 특화 데이터셋이다. LiDAR 포인트 클라우드, 스테레오 영상, GPS/IMU 데이터를 결합하여 깊이 추정, 3D 객체 탐지, SLAM 연구에 사용된다.
AI Hub
한국지능정보사회진흥원(NIA)이 운영하는 국내 AI 데이터 플랫폼이다. 한국어 기반 데이터셋과 자율주행, 의료, 농업 등 도메인 특화 데이터를 제공하며, 국내 환경에 맞는 AI 모델 개발에 유용하다.
PascalVOC 2007
객체 탐지 벤치마크 데이터셋으로, 총 20개 클래스(사람, 자동차, 개, 고양이 등)를 포함한다. train/val/test로 분할 제공되며, 각 이미지에 바운딩 박스와 클래스 레이블이 포함되어 있다. 성능 평가 기준으로 mAP를 사용한다.
3. 어노테이션 유형
어노테이션은 지도학습에서 이미지에 정답 레이블을 부여하는 과정이다. 컴퓨터 비전에서는 작업 유형에 따라 어노테이션 방식이 다르며, 어노테이션의 정밀도가 모델 성능에 직접적인 영향을 미친다.
주요 어노테이션 방식
바운딩 박스 (Bounding Box)
객체를 감싸는 직사각형으로 표현하는 가장 기본적인 방식이다. 객체 탐지(Object Detection) 태스크에서 가장 널리 사용된다. 좌표 표현 방식은 두 가지가 있다.
- Pascal VOC 포맷:
[x_min, y_min, x_max, y_max]— 픽셀 절댓값 - YOLO 포맷:
[x_center, y_center, width, height]— 이미지 크기 대비 정규화값 (0~1)
폴리곤 (Polygon) 어노테이션
불규칙한 형태의 객체를 정밀하게 표현하기 위해 꼭짓점 좌표를 순서대로 연결한 다각형으로 라벨링한다. 도로 표지판, 건물 외벽 등 직사각형으로 표현하기 어려운 대상에 사용된다.
세그멘테이션 (Segmentation)
픽셀 단위로 객체를 분리한다. 두 종류로 나뉜다.
- Semantic Segmentation: 같은 클래스의 객체는 동일한 레이블로 처리
- Instance Segmentation: 같은 클래스라도 개별 객체를 다른 레이블로 구분
키포인트 (Keypoint) 어노테이션
눈, 코, 손목, 팔꿈치 등 특정 신체 부위나 특징점에 좌표를 부여한다. 얼굴 인식, 포즈 추정 등에 사용되며 COCO Keypoints가 대표적이다.
스켈레톤 (Skeleton) 어노테이션
여러 키포인트를 선으로 연결하여 인체 구조 또는 포즈를 표현한다. 행동 인식, 스포츠 분석 등에 활용된다.
라인 / 폴리라인 (Line / Polyline) 어노테이션
도로 차선이나 경계선을 선 형태로 라벨링한다. 자율주행에서 차선 감지에 주로 사용된다.
3D 바운딩 박스
객체의 길이, 너비, 높이를 포함한 3차원 공간 내 라벨링 방식이다. LiDAR 포인트 클라우드 데이터에서 자율주행 차량 탐지에 사용된다.
4. 컴퓨터 비전 주요 태스크
컴퓨터 비전 태스크는 목적에 따라 크게 네 가지로 분류된다.
| 태스크 | 설명 |
|---|---|
| Image Classification | 이미지 전체를 하나의 클래스로 분류 |
| Object Detection | 이미지 내 여러 객체의 위치(바운딩 박스)와 클래스를 동시에 예측 |
| Semantic Segmentation | 각 픽셀에 클래스 레이블 부여 |
| Instance Segmentation | 픽셀 단위로 각 객체 인스턴스를 개별 구분 |
5. 객체 탐지 알고리즘: 전통 기법
딥러닝 이전의 객체 탐지는 사람이 직접 설계한 특징(Hand-crafted Feature)과 머신러닝 분류기를 조합하는 방식으로 동작했다.
처리 흐름
후보 영역 탐색 → 특징 추출 → 분류기 판별
후보 영역 탐색 (Region Proposal)
- 슬라이딩 윈도우 (Sliding Window): 고정 크기의 창을 이미지 전체에 걸쳐 일정 간격으로 이동시키며 각 위치에서 분류기를 실행한다. 모든 위치를 탐색하기 때문에 계산 비용이 크다.
- 선택적 탐색 (Selective Search): 색상, 질감, 경계선 정보를 이용해 객체가 있을 법한 후보 영역만 추려낸다. 슬라이딩 윈도우 대비 계산 효율이 높다.
특징 추출 (Feature Extraction)
- HOG (Histogram of Oriented Gradients): 이미지의 밝기 변화 방향(기울기 방향)을 히스토그램으로 표현한다. 보행자 검출에 많이 쓰였다.
- SIFT (Scale-Invariant Feature Transform): 크기·회전 변화에도 동일하게 검출되는 특징점을 추출한다.
분류기 학습 (Classifier Training)
추출된 특징 벡터를 SVM, Adaboost, 랜덤 포레스트 등의 분류기에 입력하여 객체 여부를 이진 또는 다중 분류한다.
한계: 특징을 사람이 직접 설계해야 하고, 복잡한 배경·다양한 스케일 변화에 취약하다. 이후 CNN 기반 딥러닝으로 빠르게 대체되었다.
6. 객체 탐지 알고리즘: 딥러닝 기반
딥러닝 기반 객체 탐지는 아키텍처에 따라 크게 두 갈래로 나뉜다.
Two-Stage Detection
후보 영역(Region Proposal)을 먼저 생성한 뒤, 그 영역을 다시 분류·좌표 보정하는 방식이다.
처리 흐름
입력 이미지
↓
RPN (Region Proposal Network) → 후보 박스 생성
↓
RoI Pooling → 후보 영역을 고정 크기로 변환
↓
분류 Head + 박스 회귀 Head → 최종 클래스·좌표 출력
- R-CNN: CNN으로 각 후보 영역을 개별 처리 → 속도 느림
- Fast R-CNN: 전체 이미지를 한 번만 CNN에 통과시켜 Feature Map 공유
- Faster R-CNN: RPN을 도입하여 후보 영역 생성까지 네트워크 내부에서 처리
- Mask R-CNN: Faster R-CNN에 픽셀 단위 마스크 예측 Branch 추가
장점: 정확도 높음, 작은 객체에 강함
단점: 속도 느림, 실시간 처리에 불리
One-Stage Detection
후보 영역 탐색 없이 입력 이미지에서 위치와 클래스를 한 번에 예측하는 방식이다.
처리 흐름
입력 이미지
↓
Backbone CNN → Feature Map 추출
↓
격자(Grid) 또는 앵커 기반 분할
↓
각 셀/앵커마다 바운딩 박스 좌표 + 클래스 확률 동시 예측
- YOLO (You Only Look Once): 이미지를 격자로 나누어 각 격자에서 직접 예측
- SSD (Single Shot MultiBox Detector): 다양한 해상도의 Feature Map에서 멀티스케일 앵커로 예측
- RetinaNet: Focal Loss를 도입해 클래스 불균형 문제를 해결
장점: 속도 빠름, 실시간 처리 가능
단점: 작은 객체나 복잡한 배경에서 정확도가 다소 낮을 수 있음
7. YOLO
YOLO(You Only Look Once)는 이미지를 $S \times S$ 격자로 나누고, 각 격자 셀에서 여러 개의 바운딩 박스와 클래스 확률을 동시에 예측하는 One-Stage 객체 탐지 모델이다.
YOLO 핵심 동작 원리
이미지를 단일 CNN에 통과시켜 Feature Map을 생성하고, 해당 Feature Map의 각 위치에서 앵커 박스를 기준으로 다음 세 가지를 예측한다.
- 바운딩 박스 좌표 $(x, y, w, h)$: 격자 셀 기준 중심 좌표와 너비·높이
- Objectness Score: 해당 박스에 객체가 존재할 확률
- 클래스 확률: 각 클래스에 속할 조건부 확률
최종 예측 신뢰도는 다음과 같이 계산된다.
[
\text{Confidence} = P(\text{Object}) \times \text{IoU}_{\text{pred}}^{\text{truth}}
]
YOLO 버전 계보
| 버전 | 개발 주체 | 주요 변경 |
|---|---|---|
| YOLOv1 ~ v3 | Joseph Redmon | 기본 구조 정립, 앵커 박스, 멀티스케일 예측 도입 |
| YOLOv4 | Alexey Bochkovskiy | CSPNet, PANet, CIoU Loss 적용 |
| YOLOv5 | Ultralytics | PyTorch 기반, 경량화·배포 편의성 강화 |
| YOLOv8 | Ultralytics | Anchor-free 구조, 다양한 태스크 통합 지원 |
| YOLOv11 | Ultralytics | 최신 아키텍처, 향상된 정확도·속도 균형 |
모델 크기별 분류
YOLOv8은 동일한 아키텍처를 유지하면서 채널 수와 레이어 깊이를 조정해 5가지 크기를 제공한다.
| 코드 | 이름 | 특징 |
|---|---|---|
| n | nano | 초경량, 모바일·임베디드 환경 |
| s | small | 속도·정확도 균형, 실시간 추론 |
| m | medium | 균형 잡힌 성능 |
| l | large | 높은 정확도 요구 시 |
| x | extra-large | 최고 정확도, 느린 속도 |
태스크별 모델 유형
| 모델 | 설명 |
|---|---|
| YOLO Detect | 바운딩 박스 기반 객체 탐지 |
| YOLO Segment | 객체 탐지 + 픽셀 단위 분할 |
| YOLO Pose | 인체 관절 키포인트 예측 |
| YOLO Cls | 이미지 분류 |
| YOLO OBB | 회전 바운딩 박스 탐지 |
8. PascalVOC 2007 데이터셋 전처리 파이프라인
PascalVOC 2007은 XML 형식의 어노테이션을 사용한다. YOLO는 정규화된 텍스트 포맷의 어노테이션을 요구하기 때문에, 학습 전에 포맷 변환과 디렉터리 구조 정리가 필요하다.
디렉터리 구조 생성
from pathlib import Path
root = Path('./pascal_datasets')
Path('./pascal_datasets/trainval').mkdir(parents=True, exist_ok=True)
Path('./pascal_datasets/test').mkdir(parents=True, exist_ok=True)
Path.mkdir(parents=True, exist_ok=True)는 중간 디렉터리가 없어도 재귀적으로 생성하며, 이미 존재하는 경우 오류를 발생시키지 않는다.
for path1 in ('images', 'labels'):
for path2 in ('train2007', 'val2007', 'test2007'):
new_path = root / 'VOC' / path1 / path2
new_path.mkdir(parents=True, exist_ok=True)
YOLO 학습에 맞는 디렉터리 구조를 생성한다. images와 labels 폴더를 동일한 계층 구조로 만들어, 이미지 경로에서 labels 경로로의 자동 매핑이 가능하도록 설계한다.
최종 구조:
pascal_datasets/
└── VOC/
├── images/
│ ├── train2007/
│ ├── val2007/
│ └── test2007/
└── labels/
├── train2007/
├── val2007/
└── test2007/
VOC XML → YOLO 포맷 변환
VOC 어노테이션은 XML 형식으로 픽셀 절댓값 좌표를 사용한다. YOLO는 이미지 크기로 정규화된 중심 좌표 포맷을 요구한다.
# convert2Yolo 라이브러리를 활용한 변환
# --datasets: 입력 데이터 포맷 지정 (VOC)
# --img_path: JPEGImages 디렉터리 경로
# --label: Annotations 디렉터리 경로 (XML 파일 위치)
# --convert_output_path: 변환된 YOLO .txt 파일 저장 경로
# --img_type: 이미지 확장자
# --manifest_path: 변환 메타 정보 저장 경로
# --cls_list_file: 클래스 목록 파일 (.names)
!python example.py \
--datasets VOC \
--img_path /content/pascal_datasets/trainval/VOCdevkit/VOC2007/JPEGImages \
--label /content/pascal_datasets/trainval/VOCdevkit/VOC2007/Annotations \
--convert_output_path /content/pascal_datasets/VOC/labels/train2007 \
--img_type '.jpg' \
--manifest_path /content/pascal_datasets \
--cls_list_file ./voc.names
변환 결과로 생성되는 YOLO 어노테이션 포맷:
# <class_id> <x_center> <y_center> <width> <height>
# 예) 8 0.587 0.733 0.122 0.341
# class_id : 객체 클래스 인덱스 (voc.names 기준)
# x_center : 바운딩 박스 중심 x 좌표 / 이미지 너비 → 0~1 정규화
# y_center : 바운딩 박스 중심 y 좌표 / 이미지 높이 → 0~1 정규화
# width : 바운딩 박스 너비 / 이미지 너비 → 0~1 정규화
# height : 바운딩 박스 높이 / 이미지 높이 → 0~1 정규화
정규화 이유: 이미지 해상도가 달라도 같은 모델로 처리할 수 있고, 손실 함수 계산 시 스케일 불균형 문제가 줄어든다.
Validation 분할 이동
VOC의 ImageSets/Main/val.txt 파일에는 validation으로 사용할 이미지 ID 목록이 있다. 이 목록을 읽어 train2007에서 val2007로 해당 라벨 파일을 이동한다.
import shutil
path = '/content/pascal_datasets/trainval/VOCdevkit/VOC2007/ImageSets/Main/val.txt'
with open(path) as f:
image_ids = f.read().strip().split()
# strip(): 앞뒤 공백·개행 제거
# split(): 공백 기준 분할 → 이미지 ID 리스트 생성
# 예) ['000001', '000002', '000003', ...]
for id in image_ids:
ori_path = '/content/pascal_datasets/VOC/labels/train2007'
mv_path = '/content/pascal_datasets/VOC/labels/val2007'
shutil.move(f'{ori_path}/{id}.txt', f'{mv_path}/{id}.txt')
# shutil.move(src, dst): src 파일을 dst로 이동 (rename이 아닌 실제 이동)
이미지 파일 분배
라벨 파일이 이동된 기준으로, 대응하는 이미지 파일도 각 subset 디렉터리로 이동한다.
import os
import shutil
path = '/content/pascal_datasets'
for folder, subset in ('trainval', 'train2007'), ('trainval', 'val2007'), ('test', 'test2007'):
ex_imgs_path = f'{path}/{folder}/VOCdevkit/VOC2007/JPEGImages'
label_path = f'{path}/VOC/labels/{subset}'
img_path = f'{path}/VOC/images/{subset}'
print(subset, ": ", len(os.listdir(label_path)))
# os.listdir(label_path): 해당 경로의 파일 목록 반환
# len(): 파일 수 확인 (train/val/test 분할 결과 검증용)
for lbs_list in os.listdir(label_path):
shutil.move(
os.path.join(ex_imgs_path, lbs_list.split('.')[0] + '.jpg'),
os.path.join(img_path, lbs_list.split('.')[0] + '.jpg')
)
# lbs_list.split('.')[0]: '000001.txt' → '000001' (확장자 제거)
# os.path.join(): 경로 결합 (OS에 따른 구분자 자동 처리)
# shutil.move(): 이미지 파일을 labels와 대응하는 images 폴더로 이동
핵심 설계 의도: 이미지 파일과 라벨 파일의 이름을 동일하게 유지하고 동일한 계층 구조에 배치함으로써, YOLO 학습 시 images/ 경로를 지정하면 자동으로 labels/ 경로를 찾는 Ultralytics의 파일 매핑 규칙을 따른다.
AI가 추천하는 심화예제
파일 이동 과정에서 이미지가 없는 라벨 파일이 존재하거나 반대 경우가 발생할 수 있다. 전처리 전에 유효성 검사를 추가하는 것이 좋다.
label_ids = set(f.split('.')[0] for f in os.listdir(label_path))
img_ids = set(f.split('.')[0] for f in os.listdir(ex_imgs_path))
missing_imgs = label_ids - img_ids # 라벨은 있지만 이미지가 없는 경우
orphan_imgs = img_ids - label_ids # 이미지는 있지만 라벨이 없는 경우
# → missing_imgs, orphan_imgs가 빈 set이어야 정상
9. YAML 설정 파일
YAML 파일은 YOLO 학습 전반에 걸쳐 데이터 경로, 클래스 정보, 모델 구조, 하이퍼파라미터를 정의하는 설정 파일이다.
data.yaml 구조
# custom_voc.yaml
path: /content/pascal_datasets/VOC # 데이터셋 루트 경로
train: images/train2007 # 학습 이미지 경로 (path 기준 상대경로)
val: images/val2007 # 검증 이미지 경로
test: images/test2007 # 테스트 이미지 경로
nc: 20 # 클래스 수 (PascalVOC 20개)
names: # 클래스 이름 목록 (인덱스 순서)
- aeroplane
- bicycle
- bird
- boat
- bottle
- bus
- car
- cat
- chair
- cow
- diningtable
- dog
- horse
- motorbike
- person
- pottedplant
- sheep
- sofa
- train
- tvmonitor
설계 이유: 데이터 경로와 클래스 정의를 코드에서 분리하여, 데이터셋이 바뀌어도 YAML 파일만 교체하면 학습 코드를 수정하지 않아도 된다. 재현성과 실험 관리 측면에서 중요하다.
10. YOLOv8 학습 파이프라인
YOLO 객체 초기화
from ultralytics import YOLO
model = YOLO('yolov8s.pt')
# 'yolov8s.pt': Ultralytics가 제공하는 COCO pretrained weights
# 파일이 없으면 자동으로 다운로드됨
# s = small 버전 (속도·정확도 균형)
YOLO 클래스는 모델 로드, 학습, 검증, 추론을 모두 통합하는 고수준 API다. 내부적으로 PyTorch 기반의 신경망 구조를 로드하며, .pt 파일은 모델 가중치와 함께 아키텍처 설정도 포함한다.
model.train() — 학습 실행
results = model.train(
data='/content/pascal_datasets/custom_voc.yaml', # 데이터셋 설정 파일 경로
epochs=10, # 전체 학습 반복 횟수
batch=32, # 1회 gradient 업데이트에 사용할 이미지 수
imgsz=640, # 입력 이미지 크기 (640×640으로 리사이즈)
device=0, # GPU 인덱스 (0 = 첫 번째 GPU, "cpu" = CPU)
workers=2, # DataLoader 병렬 처리 스레드 수
name='custom_s' # 학습 결과 저장 폴더명 (runs/detect/custom_s/)
)
입력 → 출력 흐름
이미지 파일 (다양한 크기)
↓ 리사이즈 + 정규화 (imgsz=640, pixel/255.0)
Tensor [batch, 3, 640, 640] # B x C x H x W
↓ Backbone (CSPDarknet)
Feature Maps (다중 해상도)
↓ Neck (PANet / FPN)
통합된 Feature Map
↓ Detection Head
예측값: [batch, num_anchors, 4 + 1 + nc]
# 4: 바운딩 박스 좌표 (x, y, w, h)
# 1: Objectness Score
# nc: 클래스 수 (PascalVOC = 20)
↓ 손실 함수 계산
box_loss + cls_loss + dfl_loss
↓ 역전파 (backpropagation)
↓ Optimizer 파라미터 업데이트 (SGD 또는 AdamW)
주요 파라미터 설계 의도
batch=32: 배치 크기가 클수록 GPU 메모리를 더 쓰지만, gradient 추정이 안정적이어서 수렴 속도가 빠르다.imgsz=640: YOLO 기본 입력 크기로, 너무 작으면 작은 객체 탐지 성능이 떨어지고 너무 크면 메모리·속도 문제가 생긴다.workers=2: DataLoader의 멀티프로세싱 스레드 수. GPU가 데이터를 기다리는 idle time을 줄이기 위해 설정하며, Colab 환경에서는 2~4 정도가 적합하다.pretrained weights: COCO에서 학습된 가중치를 초기값으로 사용하는 Transfer Learning 방식이다. 처음부터 학습하는 것보다 수렴이 빠르고 적은 데이터에서도 좋은 성능을 낸다.
AI가 추천하는 심화예제
학습 시 데이터 증강(augmentation)이 자동으로 적용된다. 특정 증강만 비활성화하거나 강도를 조정하려면 다음과 같이 파라미터를 추가한다.
results = model.train(
data='custom_voc.yaml',
epochs=50,
batch=16,
imgsz=640,
device=0,
augment=True, # 기본값 True, 데이터 증강 전체 활성화
hsv_h=0.015, # Hue 변화 강도
hsv_s=0.7, # Saturation 변화 강도
flipud=0.0, # 상하 반전 비율 (0.0 = 비활성화)
mosaic=1.0, # Mosaic 증강 비율
mixup=0.1 # MixUp 증강 비율
)
11. YOLOv8 검증 및 추론
model.val() — 검증 실행
학습이 완료된 가중치를 로드하여 테스트 데이터셋에 대한 성능 지표를 계산한다.
model = YOLO("/content/runs/detect/custom_s2/weights/best.pt")
# best.pt: 학습 중 val mAP가 가장 높았던 시점의 가중치
results = model.val(
data="/content/pascal_datasets/custom_voc.yaml",
imgsz=640, # 학습 시와 동일한 입력 크기 사용 권장
iou=0.5, # NMS에 적용할 IoU 임계값 (겹치는 박스 제거 기준)
batch=32,
device=0,
workers=2,
half=True, # FP16 (16-bit float) 추론 → 속도 향상, 정확도 미세 손실
split="test" # 사용할 데이터 분할 (train/val/test 중 선택)
)
print(results)
# 출력: mAP@50, mAP@50-95, Precision, Recall 등
half=True (FP16)의 의미: 기본적으로 모델은 FP32(32-bit float)로 동작하지만, FP16으로 전환하면 메모리 사용량이 절반으로 줄고 GPU 연산 속도가 향상된다. 단, 수치 정밀도가 소폭 낮아질 수 있다.
iou 파라미터의 역할: NMS(Non-Maximum Suppression)에서 두 박스의 IoU가 이 값 이상이면 신뢰도가 낮은 박스를 제거한다. 값이 낮을수록 중복 박스를 더 적극적으로 제거하고, 높을수록 겹치는 박스를 더 많이 허용한다.
model.predict() — 추론 실행
model = YOLO("/content/runs/detect/custom_s2/weights/best.pt")
results = model.predict(
source="/content/pascal_datasets/VOC/images/custom2007", # 추론할 이미지 경로 또는 폴더
imgsz=640,
conf=0.25, # Confidence 임계값: 이 값 미만의 예측 박스는 출력에서 제외
device=0,
save=True, # 바운딩 박스가 그려진 결과 이미지 저장
save_txt=True, # 탐지 결과를 YOLO 형식 .txt로 저장
save_conf=True # .txt에 신뢰도 점수도 함께 저장
)
print(results)
추론 흐름
이미지 파일 (디스크)
↓ 로드 + 리사이즈 (imgsz=640)
Tensor [1, 3, 640, 640] # 단일 이미지 배치
↓ Backbone → Neck → Head
Raw 예측값 [1, num_preds, 4+nc]
↓ conf 임계값 필터링 (conf=0.25)
↓ NMS (중복 박스 제거)
최종 탐지 결과: [(class_id, conf, x1, y1, x2, y2), ...]
↓ save_txt=True → .txt 파일 저장 (YOLO 포맷)
↓ save=True → 박스가 그려진 이미지 저장
conf 파라미터 설계 의도: 낮은 값(0.1)으로 설정하면 탐지 수가 늘지만 오탐이 많아지고, 높은 값(0.7)으로 설정하면 확실한 것만 출력하지만 놓치는 객체가 생긴다. 0.25는 Ultralytics 기본값으로, 일반적인 탐지 시나리오에서 균형을 맞춘 값이다.
AI가 추천하는 심화예제
추론 결과 객체를 후처리하여 클래스별로 필터링하거나 좌표를 직접 활용하려면 results 객체를 파싱한다.
for result in results:
boxes = result.boxes # Boxes 객체
xyxy = boxes.xyxy # Tensor [N, 4] — 절댓값 좌표 (x1, y1, x2, y2)
conf = boxes.conf # Tensor [N] — 신뢰도 점수
cls = boxes.cls # Tensor [N] — 클래스 인덱스
# 예) cls=14 → 'person' (PascalVOC 기준)
for i in range(len(cls)):
print(f"Class: {int(cls[i])}, Conf: {conf[i]:.2f}, Box: {xyxy[i].tolist()}")
12. 성능 평가 지표
IoU (Intersection over Union)
예측 바운딩 박스와 정답 바운딩 박스가 얼마나 겹치는지를 나타낸다.
[
\text{IoU} = \frac{\text{예측 박스} \cap \text{정답 박스}}{\text{예측 박스} \cup \text{정답 박스}}
]
- IoU = 1: 완전 일치
- IoU = 0: 전혀 겹치지 않음
- 일반적으로 IoU ≥ 0.5이면 정답(True Positive)으로 간주
Precision (정밀도)
모델이 객체라고 예측한 것들 중 실제로 맞은 비율이다.
[
\text{Precision} = \frac{TP}{TP + FP}
]
- TP (True Positive): 맞게 탐지한 객체 수
- FP (False Positive): 잘못 탐지한 객체 수 (없는 객체를 있다고 예측)
정밀도가 높다는 것은 오탐이 적다는 의미다.
Recall (재현율)
실제로 존재하는 객체들 중 모델이 탐지한 비율이다.
[
\text{Recall} = \frac{TP}{TP + FN}
]
- FN (False Negative): 놓친 실제 객체 수
재현율이 높다는 것은 실제 객체를 빠짐없이 잡아낸다는 의미다. Precision과 Recall은 트레이드오프 관계에 있으며, conf 임계값으로 조절된다.
AP (Average Precision)
Precision-Recall 곡선 아래 면적으로, 특정 클래스에 대한 탐지 성능을 단일 수치로 요약한다. Recall을 0에서 1까지 변화시키며 각 지점의 Precision을 계산한 뒤 평균을 낸다.
[
\text{AP} = \int_{0}^{1} P(R) , dR
]
특정 IoU 임계값에서 계산하며, AP@50은 IoU ≥ 0.5일 때 정답으로 인정한 기준으로 계산된 AP다.
mAP (mean Average Precision)
모든 클래스의 AP를 평균한 값이다. 전체 모델의 탐지 성능을 대표하는 지표로, 클래스 수가 많을수록 개별 클래스 성능 편차를 평균으로 흡수한다.
[
\text{mAP} = \frac{1}{N} \sum_{i=1}^{N} \text{AP}_i
]
mAP@50 vs mAP@50-95
| 지표 | 기준 | 특징 |
|---|---|---|
| mAP@50 | IoU ≥ 0.5 | 대략적 위치만 맞아도 정답 인정, 관대한 기준 |
| mAP@50-95 | IoU 0.5~0.95 (0.05 간격 평균) | 정밀한 위치 예측이 필요, 엄격한 기준 |
mAP@50-95는 COCO 챌린지의 기본 평가 지표로, 모델이 박스를 정밀하게 맞출수록 높은 점수를 받는다.
FPS 및 Latency
| 지표 | 설명 |
|---|---|
| FPS (Frames Per Second) | 초당 처리 가능한 이미지 수. 높을수록 빠른 모델 |
| Latency | 이미지 1장 처리에 걸리는 시간 (ms). FPS의 역수 관계 |
30 FPS = Latency 약 33ms. 실시간 비디오 처리는 일반적으로 30 FPS 이상을 요구한다.
13. 확장 및 수정 포인트
이 파이프라인을 커스텀 데이터셋에 적용하거나 성능을 개선하려면 다음 지점을 이해해야 한다.
| 목적 | 수정 위치 |
|---|---|
| 다른 데이터셋 사용 | custom_voc.yaml의 path, train/val/test, nc, names |
| 모델 크기 변경 | YOLO('yolov8n.pt') ~ YOLO('yolov8x.pt') |
| 학습률·에포크 조정 | model.train()의 epochs, lr0, lrf 파라미터 |
| 입력 해상도 변경 | model.train/val/predict의 imgsz 파라미터 |
| 데이터 증강 조정 | model.train()의 hsv_h, mosaic, flipud 등 파라미터 |
| 추론 임계값 조정 | model.predict()의 conf, iou 파라미터 |
| 새로운 태스크 (Segment/Pose) | YOLO('yolov8s-seg.pt') 등 태스크별 모델 로드 |