Object Detection(객체 탐지)은 이미지나 영상에서 특정 객체의 존재 여부를 확인하고, 해당 객체의 위치를 바운딩 박스(bounding box)로 표시하는 기술입니다. 이는 컴퓨터 비전에서 중요한 분야로, 이미지 내에서 여러 개의 객체를 동시에 탐지하고 분류할 수 있습니다. Object Detection은 주로 딥러닝 기반의 CNN(합성곱 신경망) 모델을 활용하며, 대표적인 알고리즘으로는 R-CNN 계열(Faster R-CNN, Mask R-CNN), YOLO(You Only Look Once), SSD(Single Shot MultiBox Detector) 등이 있습니다. 이러한 기술은 자율 주행, 보안 감시, 의료 영상 분석, 증강 현실 등 다양한 분야에서 활용됩니다.

객체 탐지(Object Detection)에서 전통적인 기법이란 딥러닝이 등장하기 이전에 사용되던 방식으로, 핸드크래프트된 특징 추출과 기계학습 분류기를 결합한 방법을 말합니다. 대표적으로 HOG(Histogram of Oriented Gradients), SIFT(Scale-Invariant Feature Transform) 같은 특징 추출기를 통해 이미지에서 경계·패턴을 뽑아내고, 이를 SVM(Support Vector Machine)이나 Adaboost 같은 분류기에 입력하여 객체 여부를 판별했습니다. 또한, 탐지 과정에서는 윈도우 슬라이딩 기법이나 선택적 탐색(Selective Search) 같은 방법을 이용해 후보 영역을 만들어냈습니다. 이 방식은 당시 좋은 성과를 냈지만, 특징을 직접 설계해야 하고 복잡한 배경이나 다양한 스케일 변화에 약하다는 한계가 있어 이후 딥러닝 기반 객체 탐지로 빠르게 대체되었습니다.
👉 이 과정을 통해 “이 이미지는 경계선이 많네, 둥근 패턴이 있네” 같은 수치화된 특징 벡터를 얻습니다.

객체 탐지의 딥러닝 기반 기법은 크게 1단계 탐지(One-Stage)와 2단계 탐지(Two-Stage)로 나눌 수 있습니다. 1단계 탐지는 입력 이미지를 한 번에 처리해 위치와 클래스를 동시에 예측하는 방식으로, YOLO·SSD·RetinaNet 등이 대표적이며 속도가 매우 빨라 실시간 응용에 적합하지만 작은 객체나 복잡한 배경에서 정확도가 다소 떨어질 수 있습니다. 반면 2단계 탐지는 먼저 후보 영역(Region Proposal)을 제안한 뒤, 그 영역을 다시 정밀하게 분류하고 박스를 보정하는 방식으로, R-CNN 계열(Faster R-CNN, Mask R-CNN 등)이 대표적입니다. 이 방식은 정확도가 높고 작은 객체에도 강하지만 속도가 느려 실시간 적용에는 불리합니다.
1단계 탐지 기법은 객체 위치 추정과 클래스 분류를 한 번에 동시에 수행하는 방식입니다. 즉, 입력 이미지를 바로 격자(grid)나 앵커 박스(anchor box) 단위로 나누고, 각 영역에서 객체의 존재 여부와 클래스, 위치 좌표를 곧바로 예측합니다. 대표적인 알고리즘으로는 YOLO(You Only Look Once), SSD(Single Shot MultiBox Detector), RetinaNet 등이 있으며, 속도가 빠르고 실시간 처리에 유리하지만, 작은 객체나 복잡한 배경에 대해서는 상대적으로 정확도가 떨어질 수 있습니다.
2단계 탐지 기법은 먼저 객체가 있을 법한 후보 영역(region proposal)을 찾고, 그 영역을 다시 분류·정교화하는 방식입니다. 즉, 1단계에서 "여기 객체가 있을 수 있다"라는 후보 박스를 만들고, 2단계에서 그 후보를 세밀하게 분석해 최종 클래스와 위치를 결정합니다. 대표적인 알고리즘은 R-CNN 계열(R-CNN, Fast R-CNN, Faster R-CNN, Mask R-CNN)이며, 정확도가 높고 작은 객체 탐지에도 강하지만, 속도가 느려 실시간 처리에는 덜 적합합니다.


YOLO(You Only Look Once)는 이미지를 격자 단위로 나누어 각 격자에서 객체의 위치(바운딩 박스 좌표)와 클래스를 동시에 예측하는 1단계 객체 탐지(One-Stage Detection) 알고리즘입니다. 한 번의 신경망 추론으로 전체 이미지의 탐지를 수행하기 때문에 매우 빠르고, 실시간 객체 탐지에 적합하다는 장점이 있습니다. YOLO 계열은 v1에서 시작해 v3까지는 Joseph Redmon이 개발했으며, 이후 v4·v7은 커뮤니티 연구자들, v5·v8·v11은 Ultralytics가 주도적으로 발전시켜 현재까지 이어지고 있습니다. 이러한 발전 과정을 거치면서 YOLO는 속도와 정확도의 균형을 잡은 대표적인 객체 탐지 모델로 자리 잡아 다양한 산업 현장에서 활용되고 있습니다.
PascalVOC 2007은 객체 탐지(Object Detection), 분할(Segmentation), 동작 인식(Action Recognition) 등의 다양한 컴퓨터 비전 과제를 위한 벤치마크 데이터셋입니다. 총 20개의 객체 클래스(예: 사람, 자동차, 개, 고양이 등)를 포함하며, 훈련(train), 검증(val), 테스트(test) 세트로 구성되어 있습니다. 각 이미지에는 객체의 경계 상자(Bounding Box) 및 해당 클래스 레이블이 주어지며, Mean Average Precision(mAP) 평가 기준을 적용하여 성능을 측정합니다.
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)
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)
# PascalVOC 2007 Train/Val
# train: 2501장, val: 2510장
%cd /content/pascal_datasets/trainval
!unzip -q VOCtrainval_06-Nov-2007.zip
# test: 4952장
%cd /content/pascal_datasets/test
!unzip -q VOCtest_06-Nov-2007.zip
# 어노테이션을 YOLO 형식으로 변환
!git clone https://github.com/ssaru/convert2Yolo.git
%cd convert2Yolo/
%pip install -qr requirements.txt
# datasets: 데이터셋이 VOC 형식임을 지정
# img_path: 이미지 파일 경로
# label: 어노테이션(xml) 경로
# convert_output_path: YOLO 형식으로 변환된 라벨 저장 경로
# img_type: 사용할 이미지 파일 확장자
# manifest_path: 변환 과정에서 사용할 추가적인 정보 파일 저장 경로
# cls_list_file: VOC에서 사용할 클래스 목록이 정의된 파일
!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
!python example.py \
--datasets VOC \
--img_path /content/pascal_datasets/test/VOCdevkit/VOC2007/JPEGImages \
--label /content/pascal_datasets/test/VOCdevkit/VOC2007/Annotations \
--convert_output_path /content/pascal_datasets/VOC/labels/test2007 \
--img_type '.jpg' \
--manifest_path /content/pascal_datasets \
--cls_list_file ./voc.names
# /content/pascal_datasets/trainval/VOCdevkit/VOC2007/ImageSets/Main/val.txt 파일을 읽어서
# /content/pascal_datasets/VOC/labels/train2007 파일 중 txt 문서에 있는 파일을
# /content/pascal_datasets/VOC/labels/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()
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')
# /content/pascal_datasets/trainval/VOCdevkit/VOC2007/JPEGImages 와
# /content/pascal_datasets/test/VOCdevkit/VOC2007/JPEGImages 에서
# 이미지를 가져와 디렉토리에 맞게 저장
import os
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)))
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'))
%cd /content/
YAML 파일은 모델 구성, 데이터 경로, 하이퍼파라미터 등을 정의하는 설정 파일로, 모델 학습과 추론을 자동화하는 데 중요한 역할을 합니다. 주로 data.yaml과 model.yaml 같은 파일이 있으며, data.yaml은 학습 및 검증 데이터셋의 경로, 클래스 개수, 클래스 이름 등을 정의하고, model.yaml은 네트워크 구조(레이어, 채널 수, 활성화 함수 등)를 설정합니다. YAML 형식은 가독성이 뛰어나고 계층적 구조를 쉽게 표현할 수 있어 YOLO의 설정을 직관적으로 관리할 수 있으며, 이를 통해 사용자 맞춤형 모델을 효율적으로 구축할 수 있습니다.
아래 내용을 custom_voc.yaml로 저장합니다.
path: /content/pascal_datasets/VOC
train:
- images/train2007
val:
- images/val2007
test:
- images/test2007
nc: 20
names: ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 'dog',
'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor']
!pip install ultralytics
from ultralytics import YOLO
# data: 데이터셋 설정 파일
# epochs: 학습 에포크 수
# batch: 배치 크기
# imgsz: 입력 이미지 크기
# device: GPU(0), CPU(-1)
# workers: 데이터 로딩에 사용할 CPU 스레드 수
# name: 학습 결과 저장 폴더명
model = YOLO('yolov8s.pt')
results = model.train(
data='custom_voc.yaml',
epochs=10,
batch=32,
imgsz=640,
device=0,
workers=2,
name='custom_s'
)
객체 탐지 모델이 예측한 객체 중 실제로 정답인 객체의 비율을 의미합니다. 즉, 모델이 "이것이 객체다"라고 판단한 것들 중에서 실제로 맞는 것이 얼마나 많은지를 측정합니다. 수식으로 표현하면 Precision = (TP) / (TP + FP)이며, 여기서 TP(True Positive)는 모델이 올바르게 탐지한 객체 수, FP(False Positive)는 잘못 탐지한 객체 수를 뜻합니다. 정밀도가 높을수록 모델이 잘못된 탐지를 덜 한다는 의미입니다.
실제 존재하는 객체 중에서 모델이 올바르게 탐지한 객체의 비율을 의미합니다. 즉, 놓치지 않고 얼마나 많은 객체를 찾았는지를 평가합니다. 수식으로 표현하면 Recall = (TP) / (TP + FN)이며, 여기서 FN(False Negative)은 모델이 놓친 실제 객체 수를 의미합니다. 재현율이 높을수록 모델이 더 많은 객체를 탐지하지만, 때때로 잘못된 탐지(FP)도 많아질 수 있습니다.

특정 클래스에 대해 Precision-Recall 곡선을 기반으로 평균 정밀도를 계산한 값입니다. AP는 Recall을 0에서 1까지 변화시키면서 Precision을 계산한 후 평균을 내는 방식으로 구합니다. 객체 탐지 모델의 성능을 측정하는 대표적인 방법이며, 보통 특정 IoU 기준에서 계산됩니다(예: AP@IoU=0.5는 IoU가 0.5 이상인 경우에 대해 AP를 구함)

예측된 바운딩 박스와 실제 객체의 바운딩 박스가 얼마나 겹치는지를 나타내는 값입니다. IoU는 두 박스가 겹치는 영역의 면적을 두 박스의 총 합집합 면적으로 나누어 계산합니다. 값이 1에 가까울수록 예측 박스와 실제 박스가 거의 일치한다는 뜻이며, 보통 객체 탐지 성능 평가에서 특정 임계값(예: IoU ≥ 0.5)을 기준으로 모델의 정확도를 평가합니다.

여러 클래스에 대한 AP 값을 평균 낸 값으로, 전체 모델의 객체 탐지 성능을 평가하는 종합적인 지표입니다. 단일 클래스가 아닌 전체 데이터셋에 포함된 모든 클래스의 성능을 반영하며, 다양한 IoU 임곗값(예: 0.5~0.95)에 대해 평균을 내기도 합니다. 높은 mAP 값은 모델이 다양한 클래스의 객체를 정확하게 탐지한다는 것을 의미합니다.
IoU(Intersection over Union)가 0.5(50%) 이상이면 정답으로 인정하고 계산한 평균 정밀도입니다. 즉, 모델이 대략적인 위치라도 맞추면 성능이 좋게 나옵니다.
IoU를 0.5부터 0.95까지 0.05 간격으로 변화시키면서 성능을 평가한 평균 정밀도입니다. 즉, 객체의 위치를 더욱 정확하게 맞춰야 높은 점수를 받기 때문에 더 엄격한 기준입니다.
초당 몇 개의 이미지를 처리할 수 있는지를 의미하며, 값이 높을수록 모델이 빠르게 동작한다는 뜻입니다. 예를 들어 30 FPS라면 1초에 30장의 이미지를 처리할 수 있다는 의미입니다.
한 장의 이미지를 입력했을 때 결과가 나오기까지 걸리는 시간으로, 보통 밀리초(ms) 단위로 측정합니다. 예를 들어 Latency가 50ms라면, 한 장의 이미지를 탐지하는 데 0.05초가 걸린다는 뜻입니다.
# 학습된 모델 로드
model = YOLO("runs/detect/custom_s/weights/best.pt")
# 검증 수행
results = model.val(
data="custom_voc.yaml", # 데이터셋 설정
imgsz=640, # 이미지 크기
iou=0.5, # IoU 임계값
batch=32, # 배치 크기
device=0, # GPU 사용
workers=2, # 데이터 로드 시 병렬 처리할 워커 수
half=True, # FP16 연산 활성화 (속도 향상)
split="test" # 테스트 데이터셋을 사용
)
print(results)
model = YOLO("runs/detect/custom_s/weights/best.pt")
# 객체 탐지 수행
results = model.predict(
source="/content/pascal_datasets/VOC/images/custom2007", # 테스트 이미지 폴더
imgsz=640, # 입력 이미지 크기
conf=0.25, # 신뢰도(Confidence) 임계값
device=0, # GPU 사용 (CPU 사용 시 "cpu")
save=True, # 탐지 결과 저장
save_txt=True, # 탐지 결과를 txt 형식으로 저장 (YOLO 포맷)
save_conf=True # 탐지된 객체의 신뢰도 점수도 저장
)
print(results)
| Segmentation (0) | 2025.03.10 |
|---|---|
| 이안류 CCTV 데이터셋 (0) | 2025.03.06 |
| OCR (0) | 2025.02.20 |
| OpenCV (0) | 2025.02.18 |
| 포켓몬 분류 데이터셋 (0) | 2025.02.17 |