| --- |
| 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 |
| ``` |