Create README.md
Browse files
README.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: agpl-3.0
|
| 3 |
+
base_model: ultralytics/yolov8n
|
| 4 |
+
tags:
|
| 5 |
+
- yolov8
|
| 6 |
+
- object-detection
|
| 7 |
+
- onnx
|
| 8 |
+
- onnxruntime
|
| 9 |
+
- raspberry-pi5
|
| 10 |
+
- edge-ai
|
| 11 |
+
- fire-detection
|
| 12 |
+
pipeline_tag: object-detection
|
| 13 |
+
---
|
| 14 |
+
|
| 15 |
+
# Edge Fire Detection AI (ํ์ฌ ๊ฐ์ ์จ์ ์์คํ
)
|
| 16 |
+
|
| 17 |
+
๋ผ์ฆ๋ฒ ๋ฆฌํ์ด 5 ๋ฑ ์๋ฒ ๋๋ ์ฃ์ง ๋๋ฐ์ด์ค ํ๊ฒฝ์์ ์ค์๊ฐ์ผ๋ก ๋ถ๊ฝ(Flame)๊ณผ ์ฐ๊ธฐ(Smoke)๋ฅผ ๊ฐ์งํ๊ณ ๋ฐ์ด๋ฉ ๋ฐ์ค๋ฅผ ์ถ์ ํ๋ ๊ฒฝ๋ ๊ฐ์ฒด ํ์ง(Object Detection) ๋ชจ๋ธ์
๋๋ค. `YOLOv8n(Nano)` ์ํคํ
์ฒ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ์ธํ๋๋์์ผ๋ฉฐ, ์ฃ์ง ํ๊ฒฝ์์์ ์ค์๊ฐ์ฑ ํ๋ณด๋ฅผ ์ํด `ONNX` ํฌ๋งท ๊ณ ์ ์ต์ ํ ๋ฐํ์์ ์ง์ํฉ๋๋ค.
|
| 18 |
+
|
| 19 |
+
## 1. ํ์ต ๋ฐ์ดํฐ (Training Data)
|
| 20 |
+
* **๋ฐ์ดํฐ ์ถ์ฒ:** AI Hub ํ์ฌ ๊ฐ์ง ์์ ๋ฐ์ดํฐ์
๋ฐ ์์ฒด ์์ง ํ์ฌ ์ ์ฒ๋ฆฌ ์ด๋ฏธ์ง
|
| 21 |
+
* **ํด๋์ค ๊ตฌ์ฑ:** ์ด 2๊ฐ ํด๋์ค ์ ๋ ฌ (`flame`: ๋ถ๊ฝ / `smoke`: ์ฐ๊ธฐ)
|
| 22 |
+
* **๋ฐ์ดํฐ ์ ์ ๋ฐ ์ฆ๊ฐ (Data Augmentation):** * ์ ์กฐ๋ ๊ฐํน ํ๊ฒฝ ๋ฐ ์นด๋ฉ๋ผ ๋
ธ์ด์ฆ ํ๊ฒฝ์์์ ์ค์๋(False Positive)์ ๋ฐฉ์งํ๊ธฐ ์ํด ๋ฐ๊ธฐ ๋ณํ, ํ๋ฆผ(Blur), ๋ชจ์์ดํฌ ์ฆ๊ฐ ๊ธฐ๋ฒ ์ ์ฉ
|
| 23 |
+
* ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด 5 I/O ๋ฒ์ค ์ ์ก๋ ๊ณผ๋ถํ ๋ฐฉ์ง๋ฅผ ์ํด ์
๋ ฅ ํด์๋๋ฅผ 320x240 ๋ฐ 640x480 ์ค์ผ์ผ๋ฌ๋ก ๊ฐ๊ณต ์ ๋ ฌ (v2)
|
| 24 |
+
|
| 25 |
+
## 2. ๋ชจ๋ธ ์ฑ๋ฅ (Evaluation)
|
| 26 |
+
|
| 27 |
+
| ํ๊ฐ ์งํ | ํ์ดํ ์น (.pt) ๊ท๊ฒฉ | ONNX ๊ฒฝ๋ ๊ฐ์ ๊ท๊ฒฉ | ๋น๊ณ (๋ผ์ฆ๋ฒ ๋ฆฌํ์ด 5 CPU ๊ธฐ์ค) |
|
| 28 |
+
| :--- | :---: | :---: | :--- |
|
| 29 |
+
| **mAP50 (์ ์ฒด ์ ํ๋)** | 84.5% | 83.9% | ํฌ๋งท ๋ณํ์ ๋ฐ๋ฅธ ์ ํ๋ ์์ค ์ต์ํ |
|
| 30 |
+
| **mAP50-95** | 0.521 | 0.518 | - |
|
| 31 |
+
| **์ถ๋ก ์๋ (Latency)** | ์ฝ 350ms | **์ฝ 45ms** | ONNX ๊ฐ์ ์ ์ค์๊ฐ์ฑ(20 FPS ์ด์) ๋ฌ์ฑ |
|
| 32 |
+
|
| 33 |
+
## 3. ํ์ต ์ค์ (Hyperparameters)
|
| 34 |
+
|
| 35 |
+
| ํญ๋ชฉ | ์ค์ ๊ฐ | ๋น๊ณ |
|
| 36 |
+
| :--- | :---: | :--- |
|
| 37 |
+
| **๊ธฐ๋ฐ ์ํคํ
์ฒ (Model)** | YOLOv8n | 3.2M ๊ฒฝ๋ ํ๋ผ๋ฏธํฐ ๊ตฌ์กฐ |
|
| 38 |
+
| **์
๋ ฅ ํด์๋ (imgsz)** | 320 / 640 | ๊ฐ๋ณ ํํฅ ๋ ์ด์ด ๋งคํ |
|
| 39 |
+
| **Epochs** | 50 | - |
|
| 40 |
+
| **Batch Size** | 32 | - |
|
| 41 |
+
| **Optimizer** | AdamW | - |
|
| 42 |
+
| **Augmentation** | Mosaic (1.0), Blur (0.2) | ์๋ฒ ๋๋ ํ๊ฒฝ ์ค์๋ ์ฐจ๋จ์ฉ |
|
| 43 |
+
|
| 44 |
+
## 4. ์ฌ์ฉ ๋ฐฉ๋ฒ (Inference Code)
|
| 45 |
+
|
| 46 |
+
๋ผ์ฆ๋ฒ ๋ฆฌํ์ด 5 ํ๊ฒฝ์์ `onnxruntime` ๋ฐฑ์๋๋ฅผ ํ์ฉํ์ฌ ํ๋์จ์ด ๋ณ๋ชฉ ์์ด ๊ณ ์ ์ถ๋ก ์ ์ํํ๋ ์ฃผํผํฐ ๋
ธํธ๋ถ ์ต์ ํ ๋ง์คํฐ ์คํฌ๋ฆฝํธ์
๋๋ค.
|
| 47 |
+
|
| 48 |
+
```python
|
| 49 |
+
import cv2
|
| 50 |
+
import numpy as np
|
| 51 |
+
from ultralytics import YOLO
|
| 52 |
+
from IPython.display import display
|
| 53 |
+
import ipywidgets as widgets
|
| 54 |
+
import time
|
| 55 |
+
|
| 56 |
+
def main():
|
| 57 |
+
# 1. ๊ณ ์ ๊ฐ์ ONNX ๋ชจ๋ธ ๋ก๋ (task='detect' ๋ช
์ ํ์)
|
| 58 |
+
model_path = "best.onnx"
|
| 59 |
+
model = YOLO(model_path, task='detect')
|
| 60 |
+
|
| 61 |
+
# 2. V4L2 ๋ฆฌ๋
์ค ํ์ค ๋น๋์ค ์
๋ ฅ ์์ผ ์ฐ๊ฒฐ (๋ฌผ๋ฆฌ 0๋ฒ ์ฑ๋)
|
| 62 |
+
cap = cv2.VideoCapture(0, cv2.CAP_V4L2)
|
| 63 |
+
|
| 64 |
+
# 3. ํ๋์จ์ด ๋์ญํญ ๊ณผ๋ถํ ๋ฐฉ์ง๋ฅผ ์ํ ํด์๋ ๋ฐ ๋ฒํผ ์ ์ด
|
| 65 |
+
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
|
| 66 |
+
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
|
| 67 |
+
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
|
| 68 |
+
|
| 69 |
+
time.sleep(1) # ํ๋ก ๋๊ธฐํ ์์ ํ ์ง์ฐ
|
| 70 |
+
if not cap.isOpened():
|
| 71 |
+
print("[์ค๋ฅ] ์นด๋ฉ๋ผ ์ฅ์น๋ฅผ ํ์ฑํํ ์ ์์ต๋๋ค.")
|
| 72 |
+
return
|
| 73 |
+
|
| 74 |
+
# ์ฃผํผํฐ ๋
ธํธ๋ถ ์ธ๋ผ์ธ ์ถ๋ ฅ์ ์ํ ์ด๋ฏธ์ง ์์ ฏ ์ ์ธ
|
| 75 |
+
image_widget = widgets.Image(format='jpeg', width=320, height=240)
|
| 76 |
+
display(image_widget)
|
| 77 |
+
|
| 78 |
+
try:
|
| 79 |
+
while cap.isOpened():
|
| 80 |
+
success, frame = cap.read()
|
| 81 |
+
if not success or frame is None:
|
| 82 |
+
continue
|
| 83 |
+
|
| 84 |
+
# 4. YOLOv8 ONNX ๊ฐ์ ์ถ๋ก ๊ตฌ๋
|
| 85 |
+
results = model(frame, imgsz=320, stream=True)
|
| 86 |
+
for r in results:
|
| 87 |
+
annotated_frame = r.plot()
|
| 88 |
+
|
| 89 |
+
# 5. JPEG ์์ถ ์ธ์ฝ๋ฉ ํ ์ฃผํผํฐ ๋ ๋๋ง ํ์ดํ๋ผ์ธ ์ ์ก
|
| 90 |
+
ret, jpeg = cv2.imencode('.jpg', annotated_frame)
|
| 91 |
+
if ret:
|
| 92 |
+
image_widget.value = jpeg.tobytes()
|
| 93 |
+
|
| 94 |
+
# ์ฃผํผํฐ ์น ์์ผ ๊ณผ๋ถํ(ZMQ ์๋ฌ) ์ฐจ๋จ์ฉ ๋ฏธ์ธ ์ง์ฐ
|
| 95 |
+
time.sleep(0.04)
|
| 96 |
+
|
| 97 |
+
except KeyboardInterrupt:
|
| 98 |
+
print("\n์ฌ์ฉ์์ ์ํด ์์คํ
๊ฐ๋์ด ์ค๋จ๋์์ต๋๋ค.")
|
| 99 |
+
finally:
|
| 100 |
+
cap.release()
|
| 101 |
+
cv2.destroyAllWindows()
|
| 102 |
+
print("ํ๋์จ์ด ์์ ํ์ ์๋ฃ.")
|
| 103 |
+
|
| 104 |
+
if __name__ == '__main__':
|
| 105 |
+
main()
|
| 106 |
+
```
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
## 5. ์
์ถ๋ ฅ ํ์ (Input / Output Format)
|
| 110 |
+
Plaintext
|
| 111 |
+
|
| 112 |
+
์
๋ ฅ(Input): ์ค์๊ฐ ์นด๋ฉ๋ผ ๋น๋์ค ํ๋ ์ (320x240 ๋๋ 640x480 RGB ์ด๋ฏธ์ง)
|
| 113 |
+
์ถ๋ ฅ(Output):
|
| 114 |
+
- ์์ธก ๊ฐ์ฒด ๋ฐ์ด๋ฉ ๋ฐ์ค ํฌ์ฌ (Bounding Box ์ขํ ์ ๋ณด)
|
| 115 |
+
- ํด๋์ค ๋ ์ด๋ธ ๋งคํ: [flame, smoke]
|
| 116 |
+
- ์ ๋ขฐ๋ ์์น ์ถ๋ ฅ (Confidence Score: 0.0 ~ 1.0)
|
| 117 |
+
|
| 118 |
+
## 6. ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด ์๋ฒ ๋๋ ๋ฐฐํฌ ๊ฐ์ด๋
|
| 119 |
+
ํ๊ฒฝ ๊ตฌ์ถ ๋ฐ ์๋ฒ ๊ฐ๋
|
| 120 |
+
Bash
|
| 121 |
+
|
| 122 |
+
# ๊ฐ์ํ๊ฒฝ ์ง์
์ํ ํ์ธ ํ ํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ์ฌ
|
| 123 |
+
conda activate myenv
|
| 124 |
+
pip install notebook ultralytics ipywidgets opencv-python onnxruntime
|
| 125 |
+
|
| 126 |
+
# ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด 5 ์ต์ OS์ ๋ฏธ๏ฟฝ๏ฟฝ์ด ์์ ๋
์ ์ ๊ธ(Lock) ์ฐํ ์ต์
์ ํ์ฌํ์ฌ ์ฃผํผํฐ ์คํ
|
| 127 |
+
LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libv4l/v4l1compat.so jupyter notebook --ip=0.0.0.0 --no-browser --port=8888
|
| 128 |
+
|
| 129 |
+
์น์บ ํ๋์จ์ด ์ค์๊ฐ ํธ๋ฌ๋ธ์ํ
์ธ์
|
| 130 |
+
|
| 131 |
+
select() timeout ๊ฒฝ๊ณ ๋ฐ์ ์: ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด 5์ ์ ๋ ฅ ๊ณต๊ธ ๋ฌธ์ ์ด๊ฑฐ๋ ์ปค๋ ๋ฝ ์ํ์
๋๋ค. ํฐ๋ฏธ๋์์ sudo reboot๋ฅผ ์ํํ์ฌ ์ฅ์น ๋ฝ์ ๊ฐ์ ์ด๊ธฐํํ ๋ค ์ฌ๊ฐ๋ํ์ญ์์ค.
|
| 132 |
+
|
| 133 |
+
ํ๋ฉด ๊นจ์ง ๋ฐ error dequeuing buf ๋ฐ์ ์: USB ๋ฒ์ค ์ ์ก ๋์ญํญ ํ๊ณ์น ์ด๊ณผ ํ์์
๋๋ค. ์นด๋ฉ๋ผ ์ฐ๊ฒฐ ์ ์ ๊ฒ์์ ํฌํธ์์ ์ ์ก ์ ๋ ฅ์ด ๋์ ํ๋์ USB 3.0 ํฌํธ๋ก ๋ฌผ๋ฆฌ์ ์ผ๋ก ์ด๋ ์ ๋ ฌํ๊ณ ์ฝ๋ ๋ด ํด์๋๋ฅผ 320x240์ผ๋ก ์ ์งํ์ญ์์ค.
|
| 134 |
+
|
| 135 |
+
## 7. ๋ก์ปฌ ๋๊ธฐํ ๊ฐ์ค์น ๋ค์ด๋ก๋ CLI
|
| 136 |
+
Bash
|
| 137 |
+
|
| 138 |
+
huggingface-cli download Onjeom/fire_detection_yolov8n --local-dir ./model
|