printf("ho_tari\n");
Mini Project1 - No Smoking Area Project (with YOLOv8) 본문
(Telechips) AI 시스템 반도체 SW 개발자 교육/비전과AI머신러닝
Mini Project1 - No Smoking Area Project (with YOLOv8)
호타리 2025. 5. 13. 14:182025.05.13
🚭 금연구역 흡연자 식별 프로젝트 개요
🎯 프로젝트 개요
- 프로젝트명: 금연구역 흡연자 실시간 탐지 및 웹 알림 시스템
- 목표: CCTV 또는 웹캠으로 입력되는 영상에서 흡연 행위 탐지 후 웹 서버를 통해 경고 및 저장하는 시스템 구축
- 기술요소: YOLOv8 + Flask + OpenCV 기반 영상 스트리밍 및 객체 탐지
🖥️ 실행 흐름 요약
[웹캠 영상 수신]
↓
[YOLOv8로 person/cigarette 탐지]
↓
[담배가 사람 박스 내부? → YES]
↓
[30 프레임 이상 유지? → YES]
↓
[1회 카운트 증가 + 이미지 저장 + 빨간 화면 + 경고 문구 출력]
🧠 주요 기능
기능설명
🚶 객체 탐지 | person, cigarette 클래스 YOLOv8 모델로 실시간 탐지 |
📦 포함 판단 | 담배 박스가 사람 박스 안에 포함되면 흡연 행위로 판단 |
🖼️ 프레임 저장 | 탐지된 흡연 이미지 자동 저장 (폴더 및 static 디렉토리) |
🚨 경고 출력 | "Stop Smoking Please." 문구 및 빨간 오버레이 처리 |
🌐 웹 제공 | Flask 서버에서 실시간 스트리밍 + 최근 이미지 확인 UI 제공 |
이미지 저장 조건 | 지속 시간 조건 만족 시 한 번만 저장 |
중복 저장 방지 | ✅ is_counted 플래그로 1회 저장 후 무시 |
프레임 기반 조건 | ✅ SMOKE_DETECT_THRESHOLD (기본 30프레임) 도입 |
탐지 시 오버레이 | 동일하게 붉은 배경 + 텍스트 출력 유지 |
🛠️ 기술 구성
항목사용 기술
웹 서버 | Flask |
영상처리 | OpenCV (cv2.VideoCapture, cv2.rectangle, cv2.imwrite) |
객체탐지 | YOLOv8 (ultralytics 라이브러리) |
실시간 스트리밍 | multipart/x-mixed-replace MIME 타입 사용 |
UI 템플릿 | index.html (최근 감지 이미지와 흡연자 수 표시) |
📄 data.yaml (Roboflow 기반) 분석
🔍 주요 요소 해설
항목설명
train, val, test | 각각의 이미지 경로 지정. 절대경로를 사용하여 Windows PC 환경에서 구성됨 |
nc | 클래스 수: 2개 (cigarette, person) |
names | 클래스 이름 리스트 |
roboflow | Roboflow에서 자동으로 추가된 메타데이터 정보. 데이터셋의 출처, 프로젝트명, 라이선스 등 포함 |
🧠 학습 과정 개요
✅ 데이터셋 구성
항목내용
클래스 | person, cigarette |
총 인스턴스 수 | person: 약 6,800개 / cigarette: 약 6,400개 |
이미지 내 객체 위치 | 대부분 중앙 중심에 분포 (center bias 존재) |
바운딩 박스 크기 | cigarette는 작고 compact, person은 상대적으로 큼 |
데이터 불균형 여부 | 심각한 imbalance는 아님 (비슷한 수준) |
🔍 바운딩 박스 통계 시각화
- cigarette: 소형 객체, 중앙 밀집
- person: 다양한 크기와 위치
- 너비-높이 분포에서 cigarette는 작은 범위에 집중
📊 학습 결과 분석
🎯 성능 지표
- F1 최적 confidence: 0.308 (F1 score = 0.77)
- Precision 최적 confidence: 0.874 (Precision = 1.00)
- Recall 최고점: 0.90 (at confidence = 0.0)
📈 학습 곡선 분석 (results.png)
항목경향
train/box_loss, cls_loss, dfl_loss | 안정적 감소 |
val/cls_loss, val/dfl_loss | 일부 노이즈 존재, 전체적 감소 추세 |
precision, recall | 점진적 상승 (최종 Precision ~0.78, Recall ~0.75) |
mAP@0.5 | 약 0.775 도달 |
mAP@0.5:0.95 | 약 0.32 도달 |
🔎 문제점 및 개선점
- cigarette 클래스에서 Precision/Recall 낮음 → 작은 객체 탐지 강화 필요
- 중앙 밀집 데이터 특성으로 인해 실제 응용시 오탐 가능성 존재 → 배경 다양화 필요
🧪 모델 응용: 실시간 경고 시스템
🛠 동작 방식
- 실시간 웹캠 또는 영상 스트림 처리
- 객체 탐지 수행 후, 담배 bounding box가 사람 bounding box에 완전히 포함되면:
- "금연구역입니다. 나가주세요" 문구 화면 출력
- (선택) TTS로 음성 경고 가능
💻 사용 코드
- YOLO('best.pt') 로 커스텀 모델 불러오기
- OpenCV VideoCapture로 프레임 추출
- box.xyxy, box.cls, results.names를 활용한 후처리
- 포함 조건: person_box가 cigarette_box를 완전히 포함할 경우
- cv2.putText()로 경고 문구 표시
📌 향후 개선 방향
- 🔁 데이터 증강: Mosaic, CutMix, Copy-Paste
- 🧠 소형 객체 특화 백본 적용 (YOLO-NAS, EfficientDet 등)
- 📹 CCTV 연동 및 경고 시스템 자동화
- 🗣 TTS 및 알람 시스템 연동 (ESP32, Raspberry Pi로 IoT 연동도 가능)
🔍 1. F1-Confidence Curve 분석 (F1_curve.png)
- 전체 최고 F1 score = 0.77 @ confidence = 0.308
- 클래스별 F1 성능:
- person: 전체적으로 높은 F1-score 유지 (최고 약 0.9)
- cigarette: F1-score가 낮고 변동폭이 큼 (최고 약 0.65)
- 해석:
- 모델은 사람(person)을 잘 탐지하지만 담배(cigarette) 탐지는 상대적으로 어려움
- 가장 이상적인 confidence threshold는 약 0.308
🎯 2. Precision-Confidence Curve 분석 (P_curve.png)
- 전체 precision = 1.0 @ confidence = 0.874
- 클래스별 precision:
- person: 높은 precision 유지 (0.9 이상)
- cigarette: 낮은 confidence에선 precision 저조, 0.8 부근에서 최댓값 근접
- 해석:
- 높은 confidence일수록 precision 향상됨
- cigarette 클래스는 오탐지 비율이 높음 (false positive 많음)
📈 3. Recall-Confidence Curve 분석 (R_curve.png)
- 전체 recall = 0.90 @ confidence = 0.000
- confidence가 증가할수록 recall 감소
- person: 높은 recall 유지 (0.85 이상)
- cigarette: confidence 0.3 이상에서 recall 급감
- 해석:
- 낮은 confidence에서도 많은 객체 탐지됨 (recall ↑) → false positive 증가 가능성 있음
- cigarette은 recall과 precision을 균형 있게 잡기 어려움
🔄 4. 학습 곡선 (results.png)
- Training 손실 감소:
- box_loss, cls_loss, dfl_loss 모두 꾸준히 감소 → 학습은 잘 진행됨
- Validation 손실:
- val_cls_loss: 안정적으로 감소
- val_box_loss, val_dfl_loss: 비교적 노이즈 많고 다소 불안정
- 성능 지표:
- Precision(B): 점진적으로 상승 (약 0.78)
- Recall(B): 0.60 → 0.75까지 향상
- mAP50(B): 약 0.775 도달
- mAP50-95(B): 약 0.32 도달
- 해석:
- 전반적으로 precision, recall, mAP 모두 향상 중
- validation loss에서 약간의 노이즈는 있지만 추세는 안정적임
- 모델 성능은 양호하지만 cigarette 클래스 개선 필요
✅ 종합 평가
항목평가

사람(person) 탐지 성능 | 매우 우수 (Precision/Recall/F1 모두 높음) |
담배(cigarette) 탐지 성능 | 낮음 (precision, recall, F1 모두 낮고 민감) |
F1 최적 threshold | 0.308 (전체 F1 score 최대화 지점) |
최종 Precision | 1.00 (confidence 0.874에서) |
모델 개선 포인트 | 담배 객체 탐지 데이터 추가 학습 / class imbalance 해결 / hard negative mining 적용 권장 |

📊 1. 클래스별 인스턴스 수 분포 (좌측 상단 바 그래프)
- 클래스:
- cigarette: 약 6,400개
- person: 약 6,800개
- 해석:
- 두 클래스 간 데이터 수는 비교적 균형적이나, 약간의 불균형은 존재함 (person이 조금 더 많음)
- class imbalance 문제가 심각하진 않음 → 모델 학습에 큰 영향을 주진 않지만 정밀한 탐지를 위해 담배 클래스 추가 확보 고려 가능
🟥 2. 바운딩 박스 시각화 (우측 상단)
- 이미지 전체에서 각 클래스의 바운딩 박스 위치를 선으로 표시한 것
- cigarette: 진한 파란색 / person: 밝은 하늘색
- 해석:
- 대부분의 객체는 이미지 중앙에 위치
- cigarette 클래스는 크기가 작고 상대적으로 중앙에 몰림
- person 클래스는 크고 화면 전체에 고르게 분포됨
- 이 차이 때문에 모델이 cigarette을 잘 탐지하지 못할 수 있음 (작은 객체 탐지 어려움)
📌 3. 중심 좌표 분포 (좌측 하단, x-y 분포 히트맵)
- 바운딩 박스 중심의 (x, y) 좌표 히트맵
- 중심은 대체로 이미지 중앙 근처 (0.5, 0.5)에 밀집됨
- 해석:
- 데이터셋이 중앙에 객체가 위치한 경우가 많음 → 중심성 편향(Center Bias) 존재
- 이는 모델의 일반화 성능에 영향을 줄 수 있음 (모델이 중심에만 집중하게 됨)
📐 4. 크기 분포 (우측 하단, width-height 히트맵)
- 바운딩 박스의 너비와 높이 분포
- 대부분의 객체는 (width, height) ≈ (0.1
0.3, 0.10.3) 영역에 분포 - cigarette 클래스는 더 작은 영역에 몰릴 가능성이 큼
- 해석:
- 작은 객체 비율이 높고, 비율이 다양한 객체 존재
- 이는 소형 객체 검출에 어려움을 줄 수 있음
- anchor 설정 / augmentation 전략에서 이 특성을 고려할 필요 있음
✅ 종합 분석
항목평가 및 제안
클래스 수 분포 | 비교적 균형적이나, cigarette 클래스는 소형 객체로 탐지 성능 낮음 |
위치 분포 | 중심에 객체 몰림 → 중심성 편향 가능성 있음 |
크기 분포 | 많은 객체가 작고 좁은 영역에 분포 → 작은 객체 탐지 강화 필요 |
바운딩 박스 분포 | cigarette는 크기 작고 central density 높음 |
https://github.com/taehuenkang/No_Smoking_Area_Project