본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 9. · 11 Views
YOLO 객체 탐지 완벽 가이드
실시간 객체 탐지의 혁명 YOLO를 처음부터 실무까지 완벽 정복. YOLOv1부터 최신 YOLOv8까지의 발전 과정과 커스텀 데이터셋 학습, 실시간 탐지 구현까지 이북처럼 술술 읽히는 입문서입니다.
목차
1. YOLO의 핵심 아이디어
어느 날 김개발 씨가 회사에서 CCTV 영상 분석 프로젝트를 맡게 되었습니다. "실시간으로 사람과 차량을 구분해서 탐지해야 한다고요?" 선배 박시니어 씨가 웃으며 말합니다.
"YOLO를 쓰면 되죠. You Only Look Once, 한 번만 보면 됩니다."
YOLO(You Only Look Once)는 이미지를 단 한 번만 보고 모든 객체를 동시에 탐지하는 혁신적인 방법입니다. 마치 사진 한 장을 보고 순식간에 "여기 사람, 저기 차, 그쪽에 강아지"라고 외치는 것과 같습니다.
기존 방식이 이미지를 여러 번 스캔하며 느리게 동작했다면, YOLO는 실시간 처리가 가능할 만큼 빠릅니다.
다음 코드를 살펴봅시다.
from ultralytics import YOLO
import cv2
# YOLOv8 모델 로드
model = YOLO('yolov8n.pt') # n은 nano 모델 (가장 가벼움)
# 이미지에서 객체 탐지
results = model('street.jpg')
# 탐지된 객체 정보 출력
for result in results:
boxes = result.boxes # 바운딩 박스 정보
for box in boxes:
# 클래스명과 신뢰도 출력
print(f"탐지: {model.names[int(box.cls)]} (신뢰도: {box.conf:.2f})")
김개발 씨는 컴퓨터 비전 프로젝트를 처음 맡은 신입 개발자입니다. 회의실에서 팀장님이 말씀하십니다.
"이번 프로젝트는 실시간 영상에서 사람과 차량을 구분해야 합니다. 초당 30프레임은 처리해야 해요." 김개발 씨는 막막했습니다.
대학교 때 배운 이미지 처리 기법으로는 한 장 처리하는 데도 몇 초씩 걸렸는데, 초당 30장이라니요? 박시니어 씨가 옆에서 모니터를 가리킵니다.
"여기 보세요. YOLO라는 게 있어요.
You Only Look Once, 한 번만 본다는 뜻이죠." 그렇다면 YOLO의 핵심 아이디어는 무엇일까요? 쉽게 비유하자면, YOLO는 마치 베테랑 경비원이 CCTV 화면을 한 눈에 훑어보는 것과 같습니다.
초보 경비원은 화면의 왼쪽부터 오른쪽까지, 위에서 아래로 차근차근 살펴봐야 하지만, 베테랑은 화면을 딱 한 번 보는 순간 "3시 방향에 의심 인물, 9시 방향에 차량 진입"이라고 즉시 파악합니다. YOLO도 이처럼 이미지 전체를 한 번에 분석하여 모든 객체를 동시에 찾아냅니다.
YOLO가 등장하기 전에는 어땠을까요? 전통적인 객체 탐지 방법은 슬라이딩 윈도우 방식이었습니다.
이미지의 왼쪽 위부터 작은 창문을 하나씩 옮겨가며 "여기 사람 있나? 없네.
여기는? 없네..."를 반복했습니다.
하나의 이미지에서 수천 번의 검사를 해야 했고, 당연히 느렸습니다. 더 발전된 R-CNN 같은 방법도 있었지만, 이것 역시 2단계 과정이었습니다.
먼저 "객체가 있을 것 같은 영역"을 찾고, 그 다음 각 영역마다 "이게 뭔지" 분류했습니다. 정확도는 높았지만, 실시간 처리는 불가능했습니다.
바로 이런 문제를 해결하기 위해 2015년 YOLO가 등장했습니다. YOLO의 혁신적인 아이디어는 객체 탐지를 회귀 문제로 재정의한 것입니다.
"객체가 어디 있나?"와 "그게 뭔가?"를 동시에 하나의 신경망에서 처리합니다. 이미지를 입력하면, 단 한 번의 forward pass로 모든 바운딩 박스의 위치와 클래스를 예측합니다.
구체적으로 어떻게 동작할까요? YOLO는 입력 이미지를 그리드로 나눕니다.
예를 들어 7x7 그리드라면, 이미지를 49개의 작은 칸으로 쪼개는 것입니다. 각 그리드 셀은 담당 영역에 객체가 있는지 판단하고, 있다면 바운딩 박스의 위치와 크기, 그리고 객체의 클래스를 예측합니다.
위의 코드를 살펴보겠습니다. 첫 번째 줄에서 ultralytics 라이브러리로부터 YOLO 클래스를 가져옵니다.
Ultralytics는 YOLO를 가장 쉽게 사용할 수 있게 만든 공식 라이브러리입니다. 다음으로 사전 학습된 yolov8n.pt 모델을 로드합니다.
'n'은 nano의 약자로, 가장 가벼운 모델입니다. 그리고 단 한 줄로 객체 탐지를 수행합니다.
model('street.jpg')만 호출하면, 모델은 이미지를 분석하여 탐지 결과를 반환합니다. 마지막으로 결과를 순회하며 탐지된 객체의 클래스명과 신뢰도를 출력합니다.
실제 현업에서는 어떻게 활용할까요? 자율주행 자동차를 개발한다고 가정해봅시다.
차량의 카메라는 초당 30프레임의 영상을 촬영합니다. YOLO는 각 프레임마다 도로 위의 차량, 보행자, 신호등, 표지판을 실시간으로 탐지합니다.
테슬라, 우버 등 많은 자율주행 기업에서 YOLO 계열 모델을 실제로 활용하고 있습니다. 공장 자동화에서도 마찬가지입니다.
컨베이어 벨트 위의 불량품을 실시간으로 찾아내거나, 로봇 팔이 물건을 집기 위해 위치를 파악할 때 YOLO가 사용됩니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수는 모든 상황에 가장 무거운 모델을 사용하는 것입니다. YOLOv8에는 n(nano), s(small), m(medium), l(large), x(extra large) 다섯 가지 크기가 있습니다.
임베디드 기기나 모바일에서는 nano나 small을 사용해야 하고, 고성능 서버에서만 large나 extra large를 사용해야 합니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
박시니어 씨의 설명을 들은 김개발 씨는 눈이 반짝였습니다. "와, 정말 간단하네요!" YOLO의 핵심은 속도와 정확도의 균형입니다.
완벽한 정확도는 아니지만, 실시간 처리가 가능할 만큼 빠르면서도 실용적인 수준의 정확도를 제공합니다. 여러분도 이제 YOLO로 실시간 객체 탐지 프로젝트를 시작할 수 있습니다.
실전 팁
💡 - YOLOv8n(nano)은 모바일/임베디드용, YOLOv8x(extra large)는 서버용으로 선택하세요
- 실시간 처리가 필요하면 FPS(초당 프레임)를 먼저 측정하고 모델 크기를 조정하세요
- 사전 학습된 모델은 COCO 데이터셋(80개 클래스)으로 학습되어 있으니, 일반적인 객체는 바로 탐지 가능합니다
2. Grid Cell과 Bounding Box
김개발 씨가 YOLO 코드를 실행하니 신기하게도 이미지 위에 네모 박스들이 그려졌습니다. "이 박스는 어떻게 그려지는 거죠?" 박시니어 씨가 종이에 격자를 그리며 설명하기 시작합니다.
"이미지를 바둑판처럼 나눈다고 생각해보세요."
그리드 셀은 이미지를 바둑판처럼 나눈 각각의 칸이며, 바운딩 박스는 객체를 둘러싸는 사각형 영역입니다. 각 그리드 셀은 자기 영역의 중심에 객체가 있으면 그 객체를 책임지고 탐지합니다.
마치 아파트 경비원들이 각자 담당 구역을 맡듯이, 각 셀이 담당 영역의 객체를 찾아냅니다.
다음 코드를 살펴봅시다.
import cv2
from ultralytics import YOLO
model = YOLO('yolov8n.pt')
img = cv2.imread('people.jpg')
# 객체 탐지 수행
results = model(img)
# 각 탐지 결과의 바운딩 박스 정보
for result in results:
boxes = result.boxes.xyxy.cpu().numpy() # [x1, y1, x2, y2] 형식
for box in boxes:
x1, y1, x2, y2 = map(int, box)
# 바운딩 박스 그리기
cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.imwrite('result.jpg', img)
김개발 씨는 YOLO가 객체를 찾는다는 건 알겠는데, 정확히 어떻게 찾는지 궁금했습니다. 모니터에는 사람 주위에 초록색 네모 박스가 그려져 있었습니다.
박시니어 씨가 A4 용지를 꺼내 격자를 그립니다. "자, 이 종이가 우리 이미지라고 생각해봅시다.
YOLO는 이걸 이렇게 격자로 나눠요." 그렇다면 그리드 셀은 정확히 무엇일까요? 쉽게 비유하자면, 그리드 셀은 마치 아파트 단지를 동과 호수로 나누는 것과 같습니다.
101동, 102동, 103동... 각 동마다 담당 경비원이 있듯이, 이미지의 각 격자 칸마다 담당 역할이 있습니다.
YOLO는 보통 이미지를 13x13, 19x19, 또는 더 세밀한 격자로 나눕니다. 각 그리드 셀은 어떤 일을 할까요?
각 셀은 세 가지 질문에 답합니다. 첫째, "내 영역 중심에 객체가 있나요?" 둘째, "있다면 그 객체를 감싸는 박스는 어디인가요?" 셋째, "그 객체는 무엇인가요?" 예를 들어 사람이 사진 한가운데 서 있다면, 한가운데 그리드 셀이 "여기 사람 있습니다!"라고 신호를 보냅니다.
그리고 그 사람을 딱 맞게 감싸는 바운딩 박스의 위치와 크기를 예측합니다. 바운딩 박스는 어떻게 표현될까요?
바운딩 박스는 네 개의 숫자로 표현됩니다. 가장 일반적인 방식은 (x1, y1, x2, y2) 형식입니다.
x1, y1은 박스의 왼쪽 위 모서리 좌표이고, x2, y2는 오른쪽 아래 모서리 좌표입니다. 마치 직사각형을 그릴 때 시작점과 끝점을 찍는 것과 같습니다.
또 다른 표현 방식도 있습니다. (center_x, center_y, width, height) 형식은 박스의 중심점 좌표와 너비, 높이를 나타냅니다.
YOLO는 내부적으로 이 방식을 사용하지만, 우리가 결과를 받을 때는 보통 (x1, y1, x2, y2)로 변환되어 나옵니다. 위의 코드를 단계별로 살펴보겠습니다.
먼저 이미지를 읽어오고 YOLO 모델로 객체 탐지를 수행합니다. result.boxes.xyxy는 탐지된 모든 바운딩 박스를 (x1, y1, x2, y2) 형식으로 반환합니다.
.cpu().numpy()는 GPU 텐서를 CPU의 넘파이 배열로 변환하는 과정입니다. 각 박스를 순회하며 좌표를 정수로 변환합니다.
픽셀 좌표는 정수여야 하기 때문입니다. 그리고 OpenCV의 rectangle 함수로 이미지에 직접 박스를 그립니다.
초록색(0, 255, 0)으로 두께 2픽셀의 선을 그리는 것입니다. 실제 현업에서는 어떻게 활용할까요?
소매점 매장의 무인 계산대를 개발한다고 가정해봅시다. 고객이 상품을 올려놓으면, 카메라가 촬영하고 YOLO가 각 상품의 바운딩 박스를 찾습니다.
사과 한 개는 작은 박스, 수박 한 통은 큰 박스로 탐지됩니다. 시스템은 바운딩 박스의 크기와 위치를 기반으로 "사과 2개, 수박 1개"라고 정확히 계산합니다.
교통 관제 시스템도 마찬가지입니다. 각 차량의 바운딩 박스를 추적하여, 어느 차선에 몇 대의 차가 있는지, 각 차량의 이동 방향은 어디인지 파악합니다.
하지만 주의할 점도 있습니다. 초보 개발자들이 흔히 착각하는 것이 있습니다.
바운딩 박스가 완벽하게 정확하다고 생각하는 것입니다. 실제로는 약간의 오차가 항상 있습니다.
사람 머리 끝이 살짝 잘릴 수도 있고, 발끝이 박스 밖으로 나갈 수도 있습니다. 이는 정상입니다.
또 다른 실수는 좌표계를 헷갈리는 것입니다. 이미지에서 (0, 0)은 왼쪽 위 모서리입니다.
x는 오른쪽으로 갈수록 증가하고, y는 아래로 갈수록 증가합니다. 수학 좌표계와 반대라는 점을 기억하세요.
다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨는 격자 종이에 사람 모양을 그리고 박스를 그렸습니다.
"이렇게 각 셀이 담당 영역의 객체를 찾는 거예요." 김개발 씨는 이제 이해가 됐습니다. 이미지를 격자로 나누고, 각 셀이 병렬로 동시에 일하기 때문에 빠른 것이었습니다.
여러분도 이제 YOLO의 그리드 기반 탐지 원리를 이해하셨을 것입니다.
실전 팁
💡 - 바운딩 박스 좌표는 항상 이미지 범위를 벗어나지 않는지 검증하세요 (0 <= x, y <= 이미지 크기)
- 여러 객체가 겹칠 때는 NMS(Non-Maximum Suppression)로 중복 박스를 제거합니다 (YOLO가 자동으로 처리)
- 바운딩 박스의 면적(width * height)으로 객체의 상대적 크기를 파악할 수 있습니다
3. YOLOv1부터 v8까지 발전
김개발 씨가 검색을 하다가 YOLOv1, YOLOv3, YOLOv5, YOLOv8 등 여러 버전을 발견했습니다. "왜 이렇게 버전이 많죠?" 박시니어 씨가 웃으며 답합니다.
"YOLO는 2015년부터 계속 진화해왔어요. 마치 스마트폰 버전업처럼요."
YOLO는 2015년 YOLOv1 논문 발표 이후 지속적으로 발전해왔습니다. YOLOv2에서 배치 정규화를 도입하고, YOLOv3에서 다중 스케일 탐지를 추가했으며, YOLOv5부터는 PyTorch 기반으로 재작성되어 사용성이 크게 개선되었습니다.
최신 YOLOv8은 정확도와 속도 모두에서 최고 수준을 보여줍니다.
다음 코드를 살펴봅시다.
from ultralytics import YOLO
# 다양한 YOLOv8 모델 크기
models = {
'nano': 'yolov8n.pt', # 가장 빠름, 정확도 낮음
'small': 'yolov8s.pt', # 균형잡힌 선택
'medium': 'yolov8m.pt', # 중간 성능
'large': 'yolov8l.pt', # 높은 정확도
'xlarge': 'yolov8x.pt' # 최고 정확도, 느림
}
# 용도에 맞는 모델 선택
model = YOLO('yolov8n.pt') # 실시간 애플리케이션
# model = YOLO('yolov8x.pt') # 정확도가 중요한 경우
results = model('test.jpg', conf=0.5) # 신뢰도 50% 이상만
김개발 씨는 YOLO 튜토리얼을 찾아보다가 혼란스러워졌습니다. 어떤 글은 YOLOv3을 설명하고, 어떤 글은 YOLOv5를 추천하고, 또 어떤 글은 YOLOv8이 최신이라고 합니다.
박시니어 씨가 타임라인을 그리며 설명합니다. "YOLO는 긴 여정을 거쳐왔어요.
각 버전마다 의미 있는 개선이 있었죠." YOLO의 역사는 어떻게 시작되었을까요? 쉽게 비유하자면, YOLO의 발전은 마치 자동차의 진화와 같습니다.
최초의 자동차는 느리고 불편했지만 혁신적이었습니다. 점점 엔진이 개선되고, 안전장치가 추가되고, 연비가 좋아지면서 오늘날의 완성도 높은 자동차가 되었습니다.
YOLO도 이와 똑같은 과정을 거쳤습니다. 2015년, YOLOv1의 등장은 충격이었습니다.
Joseph Redmon과 그의 팀이 발표한 YOLOv1 논문은 객체 탐지 분야에 혁명을 일으켰습니다. "You Only Look Once"라는 제목처럼, 이미지를 단 한 번만 보고 객체를 탐지한다는 아이디어는 당시로서는 매우 참신했습니다.
하지만 작은 객체 탐지가 약하고, 정확도가 다른 방법보다 낮다는 문제가 있었습니다. **2016년, YOLOv2(YOLO9000)**가 나왔습니다.
YOLOv2는 여러 개선사항을 담았습니다. 배치 정규화를 추가해 학습 안정성을 높였고, 앵커 박스 개념을 도입해 다양한 크기의 객체를 더 잘 탐지하게 되었습니다.
또한 9000개 클래스를 탐지할 수 있어 YOLO9000이라는 별명도 얻었습니다. 2018년, YOLOv3는 더 큰 도약이었습니다.
YOLOv3는 다중 스케일 예측을 도입했습니다. 세 가지 다른 크기의 그리드를 사용해, 큰 객체부터 작은 객체까지 모두 잘 탐지하게 되었습니다.
큰 그리드는 큰 객체를, 작은 그리드는 작은 객체를 담당하는 방식입니다. 또한 Darknet-53이라는 더 깊은 백본 네트워크를 사용해 정확도가 크게 향상되었습니다.
2020년, YOLOv4가 등장했지만 논란이 있었습니다. 원래 YOLO 창시자 Joseph Redmon이 연구를 중단하면서, 다른 연구자들이 YOLOv4를 발표했습니다.
많은 최신 기법들을 집대성했지만, 여전히 Darknet 프레임워크를 사용해 접근성이 떨어졌습니다. 2020년, YOLOv5는 게임 체인저였습니다.
Ultralytics라는 회사가 PyTorch로 완전히 재작성한 YOLOv5를 공개했습니다. 정식 논문 없이 GitHub에 바로 공개되어 논란이 있었지만, 사용성이 워낙 뛰어나 폭발적으로 인기를 얻었습니다.
pip install 한 줄로 설치되고, 파이썬 코드 몇 줄로 바로 사용할 수 있었습니다. 2023년, YOLOv8이 현재 최신 버전입니다.
같은 Ultralytics 팀이 만든 YOLOv8은 아키텍처를 대폭 개선했습니다. 앵커 프리(anchor-free) 방식으로 전환해 더 단순하면서도 정확해졌습니다.
또한 객체 탐지뿐 아니라 세그멘테이션(픽셀 단위 분할), 포즈 추정(관절 위치 탐지), 분류 등 다양한 작업을 지원합니다. 위의 코드를 살펴보겠습니다.
YOLOv8은 다섯 가지 크기로 제공됩니다. n(nano)은 약 3MB로 매우 가볍지만 정확도가 낮습니다.
모바일이나 임베디드 기기에 적합합니다. s(small)와 m(medium)은 일반적인 애플리케이션에 적합한 균형잡힌 선택입니다.
l(large)과 x(extra large)는 정확도가 중요하고 속도는 덜 중요한 경우에 사용합니다. conf=0.5 매개변수는 신뢰도 임계값입니다.
모델이 50% 이상 확신하는 탐지 결과만 반환하라는 의미입니다. 이 값을 높이면 정밀도가 올라가지만 재현율이 낮아집니다.
실제 현업에서는 어떻게 선택할까요? 스마트폰 앱을 개발한다면 YOLOv8n을 선택해야 합니다.
배터리와 메모리가 제한적이기 때문입니다. 반면 클라우드 서버에서 의료 영상을 분석한다면 YOLOv8x를 사용해야 합니다.
환자의 생명이 걸린 문제이므로 정확도가 최우선이기 때문입니다. 자율주행 자동차는 중간 지점인 YOLOv8m이나 YOLOv8l을 선택합니다.
실시간 처리가 필요하지만, 동시에 사람의 생명이 걸려 있어 정확도도 중요하기 때문입니다. 주의할 점이 있습니다.
초보 개발자들은 무조건 최신 버전이 좋다고 생각합니다. 하지만 YOLOv5도 여전히 매우 훌륭하고, 많은 프로덕션 시스템에서 사용 중입니다.
레거시 코드와의 호환성이나 안정성이 중요하다면 검증된 YOLOv5를 선택하는 것이 현명할 수 있습니다. 또한 버전 번호의 혼란이 있습니다.
YOLOv6, YOLOv7도 존재하지만, 다른 연구 팀이 만든 것이어서 Ultralytics의 YOLOv5-v8 계열과는 다릅니다. 실무에서는 Ultralytics의 공식 구현을 사용하는 것이 권장됩니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨가 정리해줍니다.
"YOLOv8이 최신이고 가장 좋지만, 프로젝트 상황에 맞춰 선택하면 돼요." YOLO의 발전 과정을 이해하면, 왜 이렇게 설계되었는지, 어떤 문제를 해결하려고 했는지 알 수 있습니다. 여러분의 프로젝트에 가장 적합한 버전을 선택하세요.
실전 팁
💡 - 대부분의 경우 YOLOv8이 최선의 선택이지만, 레거시 프로젝트는 YOLOv5도 충분합니다
- 모델 크기는 nano → small → medium → large → xlarge 순으로 정확도는 올라가지만 속도는 느려집니다
- 실시간 처리가 필요하면 nano나 small, 정확도가 중요하면 large나 xlarge를 선택하세요
4. YOLOv8 실습 환경 구축
김개발 씨가 "이제 직접 해볼 시간이네요!"라며 노트북을 켰습니다. 하지만 어디서부터 시작해야 할지 막막했습니다.
박시니어 씨가 터미널을 열며 말합니다. "설치는 생각보다 간단해요.
파이썬만 있으면 됩니다."
YOLOv8 환경 구축은 매우 간단합니다. Python 3.8 이상과 pip만 있으면, ultralytics 패키지 하나로 모든 것이 해결됩니다.
GPU를 사용하려면 PyTorch와 CUDA를 먼저 설치해야 하지만, CPU만으로도 테스트는 충분히 가능합니다. 마치 레고 블록처럼 필요한 조각들을 하나씩 끼워 맞추면 됩니다.
다음 코드를 살펴봅시다.
# 1. Ultralytics 설치 (터미널에서 실행)
# pip install ultralytics
# 2. 설치 확인 및 기본 테스트
from ultralytics import YOLO
import torch
# CUDA(GPU) 사용 가능 여부 확인
print(f"CUDA available: {torch.cuda.is_available()}")
print(f"PyTorch version: {torch.__version__}")
# YOLOv8 모델 다운로드 및 로드
model = YOLO('yolov8n.pt') # 처음 실행시 자동 다운로드됨
# 샘플 이미지로 테스트
results = model('https://ultralytics.com/images/bus.jpg')
results[0].show() # 결과 시각화
김개발 씨는 딥러닝 환경 구축이 복잡하다는 이야기를 많이 들었습니다. TensorFlow, Keras, CUDA, cuDNN...
설치만 하루 종일 걸린다는 선배들의 하소연도 들었습니다. 박시니어 씨가 안심시킵니다.
"YOLOv8은 달라요. Ultralytics 팀이 정말 잘 만들어놨어요." 환경 구축은 왜 중요할까요?
쉽게 비유하자면, 환경 구축은 마치 요리를 시작하기 전 주방을 정리하는 것과 같습니다. 칼, 도마, 냄비가 제자리에 있고, 재료가 준비되어 있어야 요리를 시작할 수 있습니다.
프로그래밍도 마찬가지입니다. 필요한 라이브러리가 올바르게 설치되어 있어야 코드를 실행할 수 있습니다.
첫 번째 단계는 Python 설치입니다. Python 3.8 이상이 필요합니다.
터미널에서 python --version을 입력해 버전을 확인하세요. 만약 3.7 이하라면 Python 공식 웹사이트에서 최신 버전을 다운로드하세요.
대부분의 경우 Python을 설치하면 pip도 함께 설치됩니다. 두 번째 단계는 가상환경 생성입니다 (선택사항이지만 강력 권장).
가상환경은 프로젝트마다 독립적인 Python 환경을 만들어줍니다. 마치 각 프로젝트마다 별도의 작업실을 갖는 것과 같습니다.
터미널에서 다음을 실행하세요: python -m venv yolo_env source yolo_env/bin/activate # Windows는 yolo_env\Scripts\activate 세 번째 단계는 PyTorch 설치입니다. Ultralytics는 PyTorch 위에서 동작합니다.
PyTorch 공식 웹사이트(pytorch.org)에 가면 여러분의 시스템에 맞는 설치 명령을 생성해줍니다. GPU가 있다면 CUDA 버전을 선택하세요.
없다면 CPU 버전으로 충분합니다. 예를 들어 GPU(CUDA 11.8)가 있는 경우: pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 CPU만 있는 경우: pip install torch torchvision 네 번째 단계는 Ultralytics 설치입니다.
이제 핵심 패키지를 설치합니다. 단 한 줄이면 됩니다: pip install ultralytics 이 명령은 YOLOv8뿐 아니라 필요한 모든 의존성 패키지를 자동으로 설치합니다.
OpenCV, NumPy, Pillow 등이 모두 포함됩니다. 위의 코드를 살펴보겠습니다.
먼저 CUDA 사용 가능 여부를 확인합니다. torch.cuda.is_available()이 True를 반환하면 GPU를 사용할 수 있습니다.
False라면 CPU로 동작하는데, 속도는 느리지만 학습이나 간단한 테스트는 가능합니다. 다음으로 YOLO 모델을 로드합니다.
YOLO('yolov8n.pt')를 처음 실행하면, 모델 파일이 자동으로 다운로드됩니다. 약 6MB 정도의 파일이며, 한 번만 다운로드되면 다음부터는 로컬에 저장된 파일을 사용합니다.
마지막으로 온라인 샘플 이미지로 테스트합니다. Ultralytics는 URL을 직접 입력할 수 있어 편리합니다.
show() 메서드는 탐지 결과를 시각화한 이미지를 화면에 표시합니다. 실제 현업에서는 어떻게 환경을 관리할까요?
대부분의 회사는 Docker 컨테이너를 사용합니다. Dockerfile에 모든 설치 과정을 정의해두면, 누가 어디서 실행하든 동일한 환경이 보장됩니다.
Ultralytics는 공식 Docker 이미지도 제공합니다: docker pull ultralytics/ultralytics docker run -it ultralytics/ultralytics 클라우드 환경에서는 Google Colab이나 AWS SageMaker, Azure ML 등을 사용합니다. 이들 플랫폼은 GPU를 쉽게 사용할 수 있게 해줍니다.
주의할 점이 있습니다. 초보 개발자들이 흔히 하는 실수는 여러 버전의 PyTorch를 섞어 쓰는 것입니다.
CPU 버전과 GPU 버전을 동시에 설치하면 충돌이 발생합니다. 반드시 하나만 설치하세요.
또 다른 실수는 CUDA 버전 불일치입니다. GPU 드라이버의 CUDA 버전과 PyTorch의 CUDA 버전이 맞아야 합니다.
nvidia-smi 명령으로 시스템의 CUDA 버전을 먼저 확인하세요. Windows 사용자는 긴 경로 문제를 겪을 수 있습니다.
Windows는 기본적으로 260자 이상의 경로를 지원하지 않습니다. 레지스트리를 수정하거나, 짧은 경로에 프로젝트를 생성하세요.
다시 김개발 씨의 이야기로 돌아가 봅시다. 터미널에서 pip install ultralytics를 입력하고, 설치가 완료되자 김개발 씨는 환호했습니다.
"생각보다 쉽네요!" 박시니어 씨가 미소를 짓습니다. "맞아요.
예전에는 정말 복잡했는데, 지금은 많이 간단해졌어요." 환경 구축이 끝났으니, 이제 본격적으로 YOLO를 사용할 준비가 되었습니다. 여러분도 위의 단계를 따라하면 10분 안에 환경을 구축할 수 있습니다.
실전 팁
💡 - 가상환경을 만들어 프로젝트마다 독립적인 환경을 유지하세요 (venv 또는 conda 사용)
- GPU가 없어도 학습과 테스트는 가능하지만, 실전 프로젝트는 GPU 사용을 강력 권장합니다
- Google Colab은 무료 GPU를 제공하니 연습용으로 활용하세요
5. 커스텀 데이터셋 학습
김개발 씨가 사전 학습된 모델로 테스트를 해보니, 일반적인 객체는 잘 탐지되었습니다. 하지만 회사 프로젝트는 특수한 부품을 탐지해야 했습니다.
"이건 어떻게 하죠?" 박시니어 씨가 답합니다. "직접 학습시켜야죠.
데이터만 있으면 간단해요."
커스텀 데이터셋은 여러분의 특정 문제를 위해 직접 만든 학습 데이터입니다. 이미지와 각 이미지의 객체 위치를 표시한 어노테이션(annotation) 파일로 구성됩니다.
YOLO는 YAML 설정 파일로 데이터셋을 정의하고, 단 몇 줄의 코드로 학습을 시작할 수 있습니다. 마치 선생님이 학생에게 새로운 과목을 가르치듯이, 모델에게 새로운 객체를 가르치는 것입니다.
다음 코드를 살펴봅시다.
from ultralytics import YOLO
# 1. 사전 학습된 모델을 베이스로 로드
model = YOLO('yolov8n.pt')
# 2. 커스텀 데이터셋으로 학습 (전이 학습)
results = model.train(
data='custom_dataset.yaml', # 데이터셋 설정 파일
epochs=100, # 학습 반복 횟수
imgsz=640, # 입력 이미지 크기
batch=16, # 배치 크기
name='custom_model' # 저장될 모델 이름
)
# 3. 학습된 모델로 예측
model = YOLO('runs/detect/custom_model/weights/best.pt')
results = model('test_image.jpg')
김개발 씨는 공장 자동화 프로젝트를 맡았습니다. 컨베이어 벨트 위의 불량 부품을 탐지해야 하는데, 사전 학습된 YOLO 모델은 "사람", "자동차", "고양이" 같은 일반 객체만 알고 있습니다.
박시니어 씨가 설명합니다. "YOLO에게 여러분의 부품을 가르쳐야 해요.
이걸 커스텀 학습이라고 합니다." 커스텀 학습은 왜 필요할까요? 쉽게 비유하자면, 사전 학습된 모델은 마치 일반 상식을 가진 사람과 같습니다.
사과, 바나나, 자동차는 알지만, 여러분 회사만의 특수 부품은 본 적이 없습니다. 그래서 새로운 지식을 가르쳐야 합니다.
다행히 이미 일반 상식(물체의 형태, 색상, 질감 인식)은 알고 있으니, 새로운 것을 빠르게 배울 수 있습니다. 이를 전이 학습(Transfer Learning)이라고 합니다.
첫 번째 단계는 데이터 수집입니다. 최소 100장, 이상적으로는 500-1000장의 이미지가 필요합니다.
다양한 각도, 조명, 배경에서 촬영한 이미지일수록 좋습니다. 공장 부품이라면 정상 부품과 불량 부품을 모두 촬영하세요.
스마트폰 카메라로 찍어도 충분합니다. 두 번째 단계는 어노테이션(라벨링)입니다.
각 이미지에서 객체의 위치를 표시해야 합니다. LabelImg, CVAT, Roboflow 같은 도구를 사용하면 마우스로 박스를 그려서 라벨을 지정할 수 있습니다.
예를 들어 "불량_나사"라는 클래스를 만들고, 이미지에서 불량 나사가 있는 곳에 박스를 그립니다. 어노테이션 결과는 YOLO 형식의 텍스트 파일로 저장됩니다: 0 0.5 0.5 0.3 0.2 첫 번째 숫자는 클래스 ID(0번 클래스), 나머지는 바운딩 박스의 중심 좌표와 너비, 높이입니다 (0-1 사이로 정규화됨).
세 번째 단계는 데이터셋 구조 만들기입니다. YOLO는 특정 폴더 구조를 기대합니다: dataset/ ├── images/ │ ├── train/ # 학습용 이미지 │ └── val/ # 검증용 이미지 └── labels/ ├── train/ # 학습용 라벨 └── val/ # 검증용 라벨 전체 데이터의 80%는 train 폴더에, 20%는 val 폴더에 넣습니다.
검증 데이터는 학습 중 모델의 성능을 평가하는 데 사용됩니다. 네 번째 단계는 YAML 설정 파일 작성입니다.
custom_dataset.yaml 파일을 만들어 데이터셋을 정의합니다: yaml path: /path/to/dataset train: images/train val: images/val nc: 2 # 클래스 개수 names: ['정상_부품', '불량_부품'] # 클래스 이름 다섯 번째 단계는 학습 실행입니다. 위의 코드를 보면, model.train()을 호출하는 것만으로 학습이 시작됩니다.
epochs=100은 전체 데이터를 100번 반복 학습한다는 의미입니다. batch=16은 한 번에 16장의 이미지를 처리합니다.
GPU 메모리가 부족하면 이 값을 줄이세요. 학습 중에는 자동으로 진행 상황이 출력됩니다.
Loss(손실) 값이 점점 줄어드는 것을 볼 수 있습니다. 학습이 완료되면 runs/detect/custom_model/ 폴더에 결과가 저장됩니다.
best.pt는 검증 데이터에서 가장 좋은 성능을 보인 모델입니다. last.pt는 마지막 에포크의 모델입니다.
보통 best.pt를 사용합니다. 실제 현업에서는 어떻게 진행될까요?
의료 영상 분석 스타트업을 예로 들어봅시다. X-ray 이미지에서 골절을 탐지하는 시스템을 개발한다면, 수천 장의 X-ray 이미지를 수집하고 의사들이 골절 부위를 라벨링합니다.
YOLO를 이 데이터로 학습시키면, 새로운 X-ray 이미지에서 골절을 자동으로 탐지할 수 있습니다. 농업 분야에서는 드론으로 촬영한 농작물 이미지에서 병충해를 탐지합니다.
건강한 잎과 병든 잎을 라벨링하고 학습시키면, 자동으로 피해 구역을 파악할 수 있습니다. 주의할 점이 있습니다.
초보 개발자들이 흔히 하는 실수는 데이터가 너무 적다는 것입니다. 클래스당 최소 100장은 있어야 합니다.
50장으로는 제대로 학습되지 않습니다. 데이터가 부족하면 데이터 증강(augmentation)을 사용하세요.
YOLO는 자동으로 이미지를 회전, 확대, 밝기 조정 등을 하며 학습합니다. 또 다른 실수는 불균형한 데이터셋입니다.
"정상" 이미지가 1000장인데 "불량"이 10장뿐이라면, 모델은 모든 것을 정상으로 판단하려고 합니다. 각 클래스의 개수를 비슷하게 맞추세요.
과적합(overfitting)도 조심해야 합니다. 학습 데이터에서는 100% 정확한데 실제 데이터에서는 형편없다면, 과적합된 것입니다.
검증 데이터의 loss가 올라가기 시작하면 학습을 멈추는 조기 종료(early stopping)를 사용하세요. YOLO는 이를 자동으로 처리합니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. 500장의 부품 이미지를 라벨링하고 학습을 돌린 김개발 씨는 긴장하며 결과를 기다렸습니다.
2시간 후, 학습이 완료되고 테스트해보니 불량 부품을 정확히 탐지했습니다! 박시니어 씨가 축하합니다.
"잘했어요. 이제 여러분만의 YOLO 모델을 가진 거예요." 커스텀 데이터셋 학습은 처음에는 복잡해 보이지만, 한 번 해보면 생각보다 간단합니다.
여러분의 문제에 맞는 데이터를 준비하고, YOLO에게 가르치세요.
실전 팁
💡 - 클래스당 최소 100장, 이상적으로는 500-1000장의 이미지를 준비하세요
- 데이터 라벨링은 Roboflow, CVAT, LabelImg 같은 무료 도구를 활용하세요
- 학습 중 검증 loss를 모니터링하여 과적합을 방지하세요
6. 실시간 객체 탐지 구현
김개발 씨가 학습된 모델로 이미지는 잘 탐지했지만, 실시간 영상에서도 동작해야 했습니다. "웹캠이나 CCTV 영상도 처리할 수 있나요?" 박시니어 씨가 노트북의 웹캠을 가리킵니다.
"당연하죠. OpenCV와 결합하면 쉬워요."
실시간 객체 탐지는 비디오 스트림의 각 프레임을 연속적으로 처리하는 것입니다. OpenCV로 웹캠이나 비디오 파일에서 프레임을 읽어오고, YOLO로 객체를 탐지한 뒤, 다시 화면에 표시하는 루프를 만듭니다.
마치 영화를 재생하면서 각 장면마다 자막을 붙이는 것과 같습니다.
다음 코드를 살펴봅시다.
import cv2
from ultralytics import YOLO
# 학습된 모델 로드
model = YOLO('runs/detect/custom_model/weights/best.pt')
# 웹캠 열기 (0은 기본 웹캠)
cap = cv2.VideoCapture(0)
# 비디오 파일 사용: cap = cv2.VideoCapture('video.mp4')
while cap.isOpened():
success, frame = cap.read()
if not success:
break
# 프레임에서 객체 탐지
results = model(frame, conf=0.5)
# 결과를 프레임에 그리기
annotated_frame = results[0].plot()
# FPS 계산 및 표시
cv2.imshow('YOLO Detection', annotated_frame)
# 'q' 키를 누르면 종료
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
김개발 씨는 이제 정적인 이미지가 아닌, 움직이는 영상에서 실시간으로 객체를 탐지해야 했습니다. 회의에서 팀장님이 말씀하셨습니다.
"CCTV 영상을 실시간으로 분석해서, 위험 상황이 감지되면 알람을 보내야 해요." 박시니어 씨가 옆에서 조언합니다. "OpenCV를 알고 있나요?
비디오 처리의 표준 라이브러리예요." 실시간 처리는 어떻게 동작할까요? 쉽게 비유하자면, 실시간 객체 탐지는 마치 영화 검열관이 필름을 한 장면씩 넘겨보는 것과 같습니다.
영화는 초당 24프레임의 정지 이미지로 구성되어 있습니다. 각 프레임을 빠르게 확인하고, 문제가 있으면 표시를 하고, 다음 프레임으로 넘어갑니다.
이 과정이 빠르게 반복되면 실시간처럼 보입니다. 비디오 처리의 기본 구조를 이해해봅시다.
모든 비디오 처리는 세 단계로 구성됩니다. 첫째, 입력 소스 열기입니다.
웹캠, 비디오 파일, IP 카메라, RTSP 스트림 등이 될 수 있습니다. 둘째, 프레임별 처리 루프입니다.
무한 반복문 안에서 한 프레임씩 읽어서 처리합니다. 셋째, 결과 출력 및 종료입니다.
처리된 프레임을 화면에 표시하거나 파일로 저장하고, 종료 조건이 되면 리소스를 정리합니다. 위의 코드를 단계별로 살펴보겠습니다.
먼저 학습된 YOLO 모델을 로드합니다. 실시간 처리에서는 모델 로딩을 루프 밖에서 한 번만 해야 합니다.
루프 안에서 매번 로드하면 엄청나게 느려집니다. cv2.VideoCapture(0)은 컴퓨터의 기본 웹캠을 엽니다.
숫자를 바꾸면 다른 카메라를 선택할 수 있습니다 (1, 2, ...). 비디오 파일을 처리하려면 파일 경로를 넣으면 됩니다: cv2.VideoCapture('traffic.mp4').
while cap.isOpened() 루프는 카메라가 열려 있는 동안 계속 실행됩니다. cap.read()는 한 프레임을 읽어옵니다.
success는 성공 여부, frame은 실제 이미지 데이터입니다. model(frame, conf=0.5)는 해당 프레임에서 객체를 탐지합니다.
conf=0.5는 신뢰도 50% 이상의 탐지만 반환합니다. 이 값을 낮추면 더 많은 객체를 탐지하지만 오탐도 늘어납니다.
results[0].plot()은 탐지된 객체를 프레임에 그려서 반환합니다. 바운딩 박스, 클래스 이름, 신뢰도가 모두 표시됩니다.
cv2.imshow()는 프레임을 윈도우에 표시합니다. cv2.waitKey(1)은 1밀리초 동안 키 입력을 기다립니다.
'q' 키가 눌리면 루프를 종료합니다. 마지막으로 cap.release()와 cv2.destroyAllWindows()로 리소스를 정리합니다.
이걸 빼먹으면 카메라가 계속 점유된 상태로 남아 문제가 생길 수 있습니다. 성능 최적화는 어떻게 할까요?
실시간 처리의 핵심은 FPS(초당 프레임 수)입니다. 최소 15-20 FPS는 되어야 부드럽게 보입니다.
30 FPS면 완벽합니다. 속도가 느리다면 여러 방법이 있습니다.
첫째, 더 작은 모델을 사용하세요. YOLOv8x 대신 YOLOv8n을 사용하면 속도가 크게 향상됩니다.
둘째, 입력 이미지 크기를 줄이세요. model(frame, imgsz=320)처럼 작은 크기로 처리하면 빨라집니다.
기본값은 640입니다. 셋째, GPU를 사용하세요.
CUDA가 설치되어 있으면 자동으로 GPU를 사용하지만, 명시적으로 model.to('cuda')를 호출할 수도 있습니다. 넷째, 프레임 스킵을 사용하세요.
모든 프레임이 아닌 2프레임마다 한 번씩만 탐지하면 속도가 2배 빨라집니다. 실제 현업에서는 어떻게 구현될까요?
공항 보안 시스템을 예로 들어봅시다. 수십 대의 CCTV 카메라가 실시간 영상을 보냅니다.
각 카메라 스트림마다 별도의 YOLO 프로세스가 돌아가며 "방치된 가방", "수상한 행동" 등을 탐지합니다. 위험이 감지되면 즉시 보안 요원에게 알림이 갑니다.
스마트 공장에서는 조립 라인을 촬영하는 카메라가 각 작업 단계를 모니터링합니다. 부품이 제대로 조립되지 않았거나, 불량품이 발견되면 즉시 라인을 멈춥니다.
주의할 점이 있습니다. 초보 개발자들이 흔히 하는 실수는 블로킹 연산을 루프 안에 넣는 것입니다.
예를 들어 탐지 결과를 데이터베이스에 저장하거나 API를 호출하는 작업이 루프 안에 있으면, 그 작업이 끝날 때까지 다음 프레임을 처리하지 못합니다. 이런 작업은 별도의 스레드나 큐로 비동기 처리해야 합니다.
또 다른 실수는 메모리 누수입니다. 탐지 결과를 계속 메모리에 쌓아두면 곧 메모리가 부족해집니다.
필요한 정보만 저장하고 나머지는 버리세요. 프레임 드롭도 고려해야 합니다.
처리 속도가 카메라 프레임 속도보다 느리면, 프레임이 쌓입니다. OpenCV의 버퍼를 조정하거나(cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)), 프레임을 건너뛰는 로직을 추가하세요.
다시 김개발 씨의 이야기로 돌아가 봅시다. 웹캠을 켜고 코드를 실행하자, 화면에 실시간으로 바운딩 박스가 그려졌습니다.
김개발 씨가 손을 흔들자 "hand" 라벨이 따라다녔습니다. 박시니어 씨가 칭찬합니다.
"완벽해요! 이제 CCTV 스트림에 연결하면 실제 시스템이 되는 거예요." 실시간 객체 탐지는 YOLO의 진정한 강점입니다.
정적인 이미지 분석을 넘어서, 움직이는 세상을 이해하는 AI 시스템을 만들 수 있습니다. 여러분도 이제 실시간 비전 시스템을 구축할 준비가 되었습니다.
실전 팁
💡 - 실시간 처리에는 YOLOv8n 또는 YOLOv8s를 추천합니다 (속도 우선)
- FPS를 측정하려면
time.time()으로 프레임 간 시간을 재세요 - 멀티 카메라 처리는 각 카메라마다 별도 스레드나 프로세스를 사용하세요
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.
보안 아키텍처 구성 완벽 가이드
프로젝트의 보안을 처음부터 설계하는 방법을 배웁니다. AWS 환경에서 VPC부터 WAF, 암호화, 접근 제어까지 실무에서 바로 적용할 수 있는 보안 아키텍처를 단계별로 구성해봅니다.
AWS Organizations 완벽 가이드
여러 AWS 계정을 체계적으로 관리하고 통합 결제와 보안 정책을 적용하는 방법을 실무 스토리로 쉽게 배워봅니다. 초보 개발자도 바로 이해할 수 있는 친절한 설명과 실전 예제를 제공합니다.
AWS KMS 암호화 완벽 가이드
AWS KMS(Key Management Service)를 활용한 클라우드 데이터 암호화 방법을 초급 개발자를 위해 쉽게 설명합니다. CMK 생성부터 S3, EBS 암호화, 봉투 암호화까지 실무에 필요한 모든 내용을 담았습니다.
AWS Secrets Manager 완벽 가이드
AWS에서 데이터베이스 비밀번호, API 키 등 민감한 정보를 안전하게 관리하는 Secrets Manager의 핵심 개념과 실무 활용법을 배워봅니다. 초급 개발자도 쉽게 따라할 수 있도록 실전 예제와 함께 설명합니다.