--- license: agpl-3.0 base_model: ultralytics/yolov8n tags: - yolov8 - object-detection - onnx - onnxruntime - raspberry-pi5 - edge-ai - fire-detection pipeline_tag: object-detection --- # Edge Fire Detection AI (화재 감시 온점 시스템) 라즈베리파이 5(Raspberry Pi 5) 임베디드 엣지 디바이스 환경에서 실시간으로 불꽃(Flame)과 연기(Smoke)를 감지하고 바운딩 박스를 추적하는 경량 객체 탐지(Object Detection) 모델입니다. `YOLOv8n(Nano)` 아키텍처를 기반으로 전이 학습(Transfer Learning)을 진행했으며, 하드웨어 연산 부하를 최소화하기 위해 `ONNX` 포맷 고속 런타임 최적화를 적용했습니다. ## 1. 학습 데이터 (Training Data) * **데이터 출처:** AI Hub 화재 감지 영상 데이터셋 및 자체 수집 화재 이미지 셋 * **클래스 정의:** 총 2개 클래스 (`flame`: 불꽃 / `smoke`: 연기) * **데이터 정제 및 증강 (Data Augmentation):** * 야간 및 오지 등 저조도 상황에서의 오작동(False Positive)을 차단하기 위해 밝기 변형, 흐림(Blur), 모자이크(Mosaic) 증강 기법을 적용하여 모델의 강건성(Robustness) 확보 * 엣지 디바이스의 I/O 버스 대역폭 부하를 경감하기 위해 입력 해상도를 320x240 및 640x480 투 트랙 규격으로 스케일링 전처리 수행 ## 2. 모델 성능 (Evaluation Metrics) | 평가 지표 | 파이토치 (.pt) 원본 | ONNX 경량 가속 규격 | 비고 (라즈베리파이 5 CPU 기준) | | :--- | :---: | :---: | :--- | | **mAP50 (전체 정확도)** | 84.5% | 83.9% | 포맷 변환에 따른 정확도 손실 0.6% 미만 방어 | | **mAP50-95** | 0.521 | 0.518 | - | | **추론 속도 (Latency)** | 약 350ms | **약 45ms** | ONNX 변환 후 실시간성(20 FPS 이상) 수렴 | ## 3. 모델 학습 과정 (Model Training Process) * **학습 인프라:** 고성능 외장 GPU(RTX 5070 Ti, 32GB RAM) 환경 기반 로컬 가속 빌드 구동 * **기반 아키텍처:** 3.2M 가벼운 파라미터 구조를 가진 `YOLOv8n`을 백본(Backbone)으로 채택하여 임베디드 CPU 가동 대역폭 사전 확보 * **하이퍼파라미터 설정:** | 항목 | 설정값 | 비고 | | :--- | :---: | :--- | | **Epochs** | 50 | - | | **Batch Size** | 32 | 하드웨어 VRAM 최적화 크기 | | **Optimizer** | AdamW | - | | **Learning Rate** | 1e-3 | 초기 학습률 지정 | | **Augmentation** | Mosaic (1.0), Blur (0.2) | 가혹 환경 오작동 차단용 | ## 4. 개발 시행착오 및 트러블슈팅 (Trials & Errors) 임베디드 엣지 AI 시스템 구현 중 발생한 물리/소프트웨어 레이어의 병목 현상과 해결 리포트입니다. ### ① PyTorch 원시 모델(.pt) 구동 시 레이턴시 저하 * **문제 상황:** 학습 완료된 `best.pt` 가중치를 라즈베리파이 5 CPU 단독 환경에서 추론했을 때 프레임 지연이 약 350ms(3 FPS 미만)까지 늘어나 실시간 화재 탐지가 불가능한 병목 직면. * **해결 조치:** 정적 연산 그래프 구조를 가진 `ONNX` 포맷으로 모델을 익스포트(`format=onnx`, `imgsz=320`)하고, 파이썬 백엔드에 `onnxruntime` 가속 플러그인을 결합하여 추론 레이턴시를 45ms(22 FPS 이상) 수준으로 비약적으로 단축함. ### ② Linux V4L2 장치 채널 타임아웃 (`select() timeout`) * **문제 상황:** 최신 라즈베리파이 OS(Bookworm) 커널에서 OpenCV로 웹캠을 호출할 때 미디어 컨트롤러 가속 스택이 `/dev/video0` 자원을 독점 점유(Lock)하여 `select() timeout`과 함께 하드웨어 좀비 락 현상 발생. * **해결 조치:** OpenCV 카메라 개시 코드단에 V4L2 백엔드를 명시적으로 지정(`cv2.VideoCapture(0, cv2.CAP_V4L2)`)하고, 주피터 서버 구동 시 리눅스 에뮬레이션 호환 레이어 환경 변수인 `LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libv4l/v4l1compat.so`를 프리로드 래핑하여 커널 점유 충돌을 우회함. ### ③ USB 버스 대역폭 초과 및 픽셀 오염 (`error dequeuing buf`) * **문제 상황:** 압축 코덱 기능이 없는 일반 웹캠의 원시 데이터(Raw YUYV)를 640x480 해상도로 수신 시, 라즈베리파이 USB 대역폭 한계로 프레임 버퍼가 누수되어 화면이 지질거리거나 검은색(Black Screen)으로 죽는 현상 발생. * **해결 조치:** 웹캠을 전력 및 전송 효율이 높은 **파란색 USB 3.0 포트**로 물리적 이동 정렬을 수행한 후, 코드 레벨에서 입력 해상도를 `320x240`으로 대폭 낮추고 고속 압축 스트리밍 포맷(`MJPG`) 코덱 지정을 강제화하여 데이터 버스 통로를 복구함. ### ④ 주피터 네트워크 웹 소켓 붕괴 크래시 (`ZMQError`) * **문제 상황:** 추론 `while` 루프가 초당 수십 장의 이미지를 지연 없이 주피터 인라인 위젯(`ipywidgets`) 화면으로 밀어 넣으면서 통신 버퍼 오버플로우로 인해 주피터 커널이 정지하고 소켓이 터지는 현상 발생. * **해결 조치:** 이미지 변환 및 전송 루틴 직후 미세 유휴 연산 타임인 `time.sleep(0.04)` 지연 버퍼 로직을 안착시켜 초당 전송률을 20~25프레임 수준으로 안정화함으로써 연속 구동 안전성을 확보함. ## 5. 사용 방법 (Inference Code) ```python import cv2 import numpy as np from ultralytics import YOLO from IPython.display import display import ipywidgets as widgets import time def main(): model_path = "best.onnx" model = YOLO(model_path, task='detect') # V4L2 가속 백엔드 매핑 cap = cv2.VideoCapture(0, cv2.CAP_V4L2) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240) cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) time.sleep(1) # 하드웨어 안정화 대기 if not cap.isOpened(): print("[오류] 카메라 장치를 활성화할 수 없습니다.") return image_widget = widgets.Image(format='jpeg', width=320, height=240) display(image_widget) try: while cap.isOpened(): success, frame = cap.read() if not success or frame is None: continue # ONNX 가속 추론 구동 (imgsz 일치) results = model(frame, imgsz=320, stream=True) for r in results: annotated_frame = r.plot() # JPEG 압축 후 주피터 렌더링 영역 업데이트 ret, jpeg = cv2.imencode('.jpg', annotated_frame) if ret: image_widget.value = jpeg.tobytes() # ZMQ 과부하 방지용 micro-delay time.sleep(0.04) except KeyboardInterrupt: print("\n사용자에 의해 시스템 가동이 중단되었습니다.") finally: cap.release() cv2.destroyAllWindows() print("하드웨어 자원 회수 완료.") if __name__ == '__main__': main() ``` ## 6. 입출력 형식 (Input / Output Format) ``` Plaintext 입력(Input): 실시간 임베디드 카메라 비디오 프레임 (320x240 RGB Image) 출력(Output): - 불꽃 및 연기 영역 바운딩 박스(Bounding Box) 시각화 투사 - 탐지 클래스 레이블 매핑: [flame, smoke] - 객체별 추론 신뢰도 수치 출력 (Confidence Score: 0.0 ~ 1.0) ``` ## 7. 로컬 동기화 가중치 다운로드 CLI ``` Bash huggingface-cli download firedetection/fire_detection_yolov8n --local-dir ./model ```