2026. 7. 20. 16:40ㆍAI 기반 프론트엔드 웹개발자 양성과정

[Data, YOLO] 로컬 데이터 수집·증강
YOLO 객체 탐지 기초 + 추적
2026.07.20 · 학습 범위: 데이터(수집·증강·라벨링), YOLO 기초·심화(추적), Teachable Machine, COCO 80클래스, SAM2
📋 오늘 다룬 것들
드디어 AI 객체 탐지에 들어갔다. 먼저 카메라로 직접 데이터를 찍고(로컬 수집), 사진 한 장을 여러 장으로 부풀리는 데이터 증강을 해봤다. 그다음 YOLO로 분류·탐지·자세·분할 4가지 작업을 돌리고, 모델 학습과 과적합 개념, 추론 파라미터 튜닝, 실시간 CCTV 스트림 처리, 마지막으로 심화의 객체 추적(Tracking)까지 훑었다. 코드 한 줄로 물체를 찾아내는 게 신기했다.
📊 데이터 준비
로컬 데이터 수집 (카메라 촬영)
공개 데이터 말고, 컴퓨터에 연결된 웹캠으로 직접 찍어 나만의 데이터셋을 만드는 방법. OpenCV(cv2)로 카메라를 켜고 한 장 찍어 저장한다.
import cv2, os from datetime import datetime save_dir = "./captured_images" os.makedirs(save_dir, exist_ok=True) # 폴더 없으면 자동 생성 cap = cv2.VideoCapture(0) # 0 = 첫 번째 카메라 success, frame = cap.read() # 사진 한 장 읽기 if success: ts = datetime.now().strftime('%Y%m%d_%H%M%S') # 파일명 겹침 방지 cv2.imwrite(f"{save_dir}/result_{ts}.jpg", frame) cap.release() # 카메라 반드시 해제
VideoCapture(0) 카메라 켜기 → cap.read() 한 장 가져오기 → cv2.imwrite() 파일 저장 → cap.release()로 반드시 끄기(안 끄면 다른 프로그램이 카메라를 못 씀). 파일명에 촬영 시각을 넣으면 여러 장 찍어도 이름이 안 겹친다.데이터 증강 (이미지 변환)
학습 이미지가 적으면 AI가 특정 각도·밝기에만 익숙해져 틀리기 쉽다. 사진 1장을 회전·밝기·반전으로 변형해 데이터를 늘리는 게 증강이다. PIL로 처리했다.
from PIL import Image, ImageEnhance, ImageOps img = Image.open("result.jpg") img_rotated = img.rotate(90) # 90도 회전 img_bright = ImageEnhance.Brightness(img).enhance(0.5) # 밝기 50% img_flip = ImageOps.mirror(img) # 좌우 반전(거울) img_rotated.save("./img_rotate.jpg") # 변환본 저장
ImageFilter.BLUR(흐리게), ImageOps.grayscale(흑백), ImageEnhance.Contrast(대비) 등 PIL만으로 10가지 이상 변형이 가능하다. YOLO 학습 땐 증강 이미지를 images/train에, 같은 이름의 라벨(.txt)을 labels/train에 함께 둔다.데이터 라벨링 (labelImg)
AI 학습용 이미지에 객체 위치를 박스로 표시하고 좌표를 기록하는 작업이 라벨링이다. labelImg는 PC에 설치해 쓰는 무료 오픈소스 도구(웹 기반으로는 Roboflow). 박스를 그리면 YOLO 형식의 .txt 좌표가 저장된다.
# 설치 pip install labelImg # YOLO 좌표 형식 (.txt) — 한 줄 = 객체 하나, 값은 모두 0~1 정규화 # class x_center y_center width height 0 0.525 0.376 0.284 0.418 # 클래스번호 x y w h # classes.txt — 줄 번호 = 클래스 번호 person # 0번 cat # 1번 dog # 2번
x_center = 중심 x ÷ 이미지 너비 식. 그래서 이미지 크기가 달라져도 같은 라벨을 재사용할 수 있다. 클래스 번호는 항상 0부터 시작하고, classes.txt의 줄 순서가 곧 번호다.Pillow(PIL): 이미지 열기·회전·밝기·반전 등 처리(증강에 사용, pip install pillow). schedule: 파이썬 작업을 일정 간격으로 자동 실행(pip install schedule) — 예: schedule.every(10).minutes.do(job)로 10분마다 사진을 자동 촬영해 데이터를 모으는 식으로 활용할 수 있다.🎯 YOLO 기초
01 — YOLO란?
YOLO(You Only Look Once) = "한 번만 본다". 조셉 레드먼이 만든 오픈소스 객체 탐지 AI로, 이미지·영상 속 사물을 번개처럼 빠르게 찾는다. 자율주행(차·사람·신호 인식), 로봇(물건 집기), 의료(진단 보조) 등에 쓰인다.
02~05 — 네 가지 작업 (분류 · 탐지 · 자세 · 분할)
YOLO는 모델 파일만 바꾸면 같은 4단계 코드로 서로 다른 작업을 한다. 모델 로드 → 추론 → results[0].plot()로 결과 그리기 → cv2.imwrite()로 저장.
from ultralytics import YOLO import cv2 model = YOLO("yolo11n.pt") # ① 모델 로드 results = model("input.jpg") # ② 추론 result_image = results[0].plot() # ③ 결과 시각화 cv2.imwrite("result.jpg", result_image) # ④ 저장
| 작업 | 모델 파일 | 무엇을 하나 |
|---|---|---|
| 분류 Classification | yolo11n-cls.pt | "이 사진은 강아지" — 사진 1장에 정답 하나 |
| 탐지 Detection | yolo11n.pt | 여러 물체 위치를 네모 박스로 표시 |
| 자세 Pose | yolo11n-pose.pt | 사람 관절 17개를 점·선으로 표시 |
| 분할 Segmentation | yolo11n-seg.pt | 물체 외곽선을 픽셀 단위로 색칠 |
n → s → m → l → x 순 — 작을수록 빠르고, 클수록 정확하다(속도 ↔ 정확도 트레이드오프). 분류는 "전체 사진 하나의 답", 탐지는 "위치까지 박스", 분할은 "박스가 아니라 모양 그대로"가 핵심 차이.06 — 모델 학습 · 과적합 · 트레이드오프
미리 학습된 yolo11n-cls.pt에 새 클래스를 추가 학습(Fine-tuning)한다. 데이터셋은 train(학습)·val(검증)·test(최종) 3단으로 나눈다.
model = YOLO("yolo11n-cls.pt") model.train( data="dataset", # train/val 자동 인식 epochs=2, # 전체 데이터 반복 횟수 batch=1, # 한 번에 처리할 이미지 수 imgsz=256, # 입력 이미지 크기 )
best.pt로 저장한다. train과 val에 같은 이미지가 섞이면 "시험 문제 유출"이라 점수가 부풀려진다.
train accuracy ↑인데 val accuracy ↓로 둘의 격차가 벌어지는 것. val loss가 최저점을 찍고 다시 오르기 시작하는 지점이 과적합 시작 신호 → 그 직전의 best.pt를 쓰는 게 정답. 대응책은 epochs 줄이기(EarlyStopping patience), 데이터 증강, 데이터 양 늘리기.
imgsz↑↔학습시간↑, batch↑↔메모리↑, epochs↑↔과적합 위험↑. "가장 좋은 설정"은 없고, 하드웨어·시간·목표에 맞춰 균형점을 실험으로 찾는 게 학습의 본질이다.
07~09 — 추론 파라미터 튜닝
model()에 파라미터를 넣어 결과를 세밀하게 제어한다. model.names로 클래스 목록(ID↔이름)을 먼저 확인하고 원하는 것만 탐지할 수 있다.
model(
"input.jpg",
save=True, # 결과 자동 저장
conf=0.5, # 신뢰도 50% 이상만 (기본 0.25)
max_det=3, # 최대 탐지 개수
save_crop=True, # 탐지 영역만 잘라 저장
save_txt=True, # 좌표를 txt로 저장
save_conf=True, # txt에 신뢰도 점수까지 저장
classes=[0, 2], # 0=person, 2=car 만 탐지
)
save_conf — 좌표 텍스트를 저장할 때 각 줄 끝에 신뢰도 값을 하나 더 붙이는 옵션이다. 그래서 save_txt=True와 짝으로 켜야 의미가 있다(저장되는 txt가 없으면 효과도 없음). classes=[60, 75]처럼 번호만 주면 dining table·vase만 골라 탐지된다.10 — HTTP 실시간 CCTV 스트림 (m3u8)
웹캠 번호 대신 m3u8 주소를 VideoCapture에 넣으면 인터넷 CCTV를 실시간으로 받는다. m3u8은 영상을 수 초 단위 조각으로 쪼개 순서대로 받는 HLS(HTTP Live Streaming) 재생목록으로, 유튜브 라이브·OTT와 같은 방식이다.
stream_url = "http://210.99.70.120:1935/live/cctv009.stream/playlist.m3u8" cap = cv2.VideoCapture(stream_url) while cap.isOpened(): success, frame = cap.read() if not success: break results = model(frame) cv2.imshow("CCTV", results[0].plot()) if cv2.waitKey(1) & 0xFF == ord('q'): # q 누르면 종료 break cap.release(); cv2.destroyAllWindows()
cv2.waitKey(1) & 0xFF == ord('q') 풀이 — "1ms 동안 키 눌렸나? 'q'면 종료". waitKey(1)은 1ms 키 입력 대기(없으면 영상이 안 보임), ord('q')는 'q'의 번호(113). & 0xFF는 일부 환경에서 키 번호 앞에 붙는 쓸데없는 비트를 잘라 하위 8비트(0~255)만 남기는 안전장치 — 그래야 어떤 컴퓨터에서든 113 == 113 비교가 성립한다.
11 — 영상에 글자 표시 (putText)
탐지 결과(객체 수·상태)를 프레임 위에 그려 CCTV 알람 UI처럼 만든다. cv2.putText는 매개변수 순서가 고정이다.
count = len(results[0].boxes) # 탐지 객체 수 status, color = ("Warning", (0,0,255)) if count >= 5 else ("Safe", (255,0,0)) cv2.putText( frame, # ① 그릴 영상 f"Detected: {count}, {status}", # ② 문자열 (10, 30), # ③ 좌표 (x, y) cv2.FONT_HERSHEY_SIMPLEX, # ④ 폰트 1, color, 2, # ⑤크기 ⑥색 ⑦두께 cv2.LINE_AA # 안티앨리어싱(글자 매끈) )
B(파랑)→G(초록)→R(빨강) 순으로 색을 쓴다. 그래서 (255,0,0)은 빨강이 아니라 파랑, (0,0,255)가 빨강이다. 일반 RGB와 순서가 반대라 계속 헷갈렸다.COCO 80 클래스 (coco.yaml)
YOLO 사전학습(pretrained) 모델은 COCO 데이터셋의 80개 클래스로 학습돼 있다. classes=[0, 2]처럼 걸러낼 때 쓰는 번호가 바로 이 목록이고, 전체는 coco.yaml 또는 model.names로 확인한다.
| 번호 | 이름 | 번호 | 이름 |
|---|---|---|---|
| 0 | person (사람) | 15 | cat (고양이) |
| 1 | bicycle (자전거) | 16 | dog (강아지) |
| 2 | car (자동차) | 60 | dining table (식탁) |
| 3 | motorcycle (오토바이) | 75 | vase (꽃병) |
| ... | ... | 79 | toothbrush (칫솔) |
classes=[0]이면 "사람만"이라는 뜻으로 통한다. 내가 만든 커스텀 모델은 이 목록이 아니라 학습 때 지정한 classes.txt 순서를 따른다.🧪 직접 학습시키기 — Teachable Machine
코드 없이 브라우저에서 바로 모델을 학습시켜 보는 Google Teachable Machine도 써봤다. 이미지·소리·자세 모델을 웹에서 만들 수 있는데, 오늘은 이미지 분류를 해봤다.
model.train()이 코드로 하는 학습이라면, Teachable Machine은 같은 원리(예시 → 학습 → 예측)를 클릭만으로 체험하는 도구다. 데이터가 많고 클래스가 균형 잡힐수록 잘 맞힌다는 점, 과적합·일반화 개념이 그대로 적용된다는 점은 동일하다. "학습이 뭔지" 감을 잡기에 좋았다.🚀 YOLO 심화
01 — 객체 추적 (Tracking)
탐지는 매 프레임 물체를 새로 찾지만, 추적은 물체마다 고유 번호(ID)를 붙여 계속 따라간다. 사람 1번이 화면 밖으로 나갔다 다시 들어와도 같은 1번으로 인식한다. model() 대신 model.track()을 쓰는 게 핵심.
results = model.track(frame, persist=True, conf=0.6) # persist=True → 이전 프레임 정보 유지(같은 ID로 추적) # conf=0.6 → 60% 이상 확신할 때만 탐지 annotated_frame = results[0].plot() cv2.namedWindow("YOLO_TRACKING", cv2.WINDOW_NORMAL) # 창 크기 조절 가능 cv2.imshow("YOLO_TRACKING", annotated_frame)
detect)는 매 프레임 독립적이라 ID가 없고, 추적(track)은 프레임을 이어 붙여 같은 물체에 같은 ID를 유지한다. persist=True가 "이전 프레임을 기억해라"는 스위치다.🔗 수업에서 소개된 참고 링크
오늘 강사님이 참고하라고 알려준 사이트·문서들을 모아뒀다. 실습에 직접 쓴 것도, 앞으로 볼 자료도 함께 정리한다.
| 자료 | 용도 | 링크 |
|---|---|---|
| Teachable Machine | 노코드로 직접 모델 학습(이미지·소리·자세) | teachablemachine.withgoogle.com |
| labelImg | 데이터 라벨링 도구 (pip install labelImg) | github.com/HumanSignal/labelImg |
| COCO 80 클래스 | YOLO 사전학습 모델의 클래스 번호↔이름 목록 | ultralytics · coco.yaml |
| schedule | 파이썬 작업 주기 실행 (pip install schedule) | pypi.org/project/schedule |
| Pillow (PIL) | 이미지 처리·증강 (pip install pillow) | pypi.org/project/pillow |
| SAM 2 | Meta의 영상 세그멘테이션 모델 | docs.ultralytics · SAM 2 · 데모 |
✍️ 마치며
파이썬 문법을 배운 지 얼마 안 됐는데, 오늘은 그 문법으로 진짜 AI를 돌려봤다는 게 가장 크게 남았다. YOLO("yolo11n.pt") 한 줄에 이미지 경로만 넣으면 물체를 찾아 박스를 그려주는 게 신기하면서도, 뒤에 있는 train/val·과적합·트레이드오프 같은 개념을 알아야 "왜 이 모델을 이렇게 쓰는지" 이해된다는 걸 느꼈다. BGR 색 순서나 & 0xFF처럼 사소하지만 안 알면 계속 틀리는 것들도 오늘 확실히 짚었다. 다음엔 직접 모은 데이터로 나만의 분류 모델을 학습시켜 볼 예정이다.
🏷️ YOLO | OpenCV | 객체탐지 | 데이터 | AI | 학습일지
'AI 기반 프론트엔드 웹개발자 양성과정' 카테고리의 다른 글
| [260722 17일차] OpenAPI · HuggingFace · Transformers · OCR (1) | 2026.07.22 |
|---|---|
| [260721 16일차] YOLO 심화 (0) | 2026.07.22 |
| [260716 14일차] Anaconda, Python (0) | 2026.07.16 |
| [260715 13일차] Vercel, Claude Web (0) | 2026.07.15 |
| [260714 12일차] Node·Express, Groq API (0) | 2026.07.14 |