“์ปจํ
์ด๋์ ์นด๋ฉ๋ผ ๋ง์ดํธํ๊ณ YOLOv8 ๋๋ฆฌ๋ฉด ๋๊ฒ ์ง” ๋ผ๊ณ ์๊ฐํ์ต๋๋ค. v1์ ์ฌ๋ฆฌ๊ณ ๋ก๊ทธ๋ฅผ ๋ดค๋๋ exec format error. v2 ์ฌ๋ฆฌ๋ Failed to read frame from camera. v3, v4, v5, v6 ๋น๋ ์คํจ… ๊ฒฐ๊ตญ v7์์์ผ ํ์ฌ ๊ฐ์ง๊ฐ ์ ์ ๋์ํ์ต๋๋ค. ์ด ํฌ์คํ
์ ๊ทธ 7๋ฒ์ ์๋ ๋ค์ ๋ฐ๊ฒฌํ ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด 5์ ์นด๋ฉ๋ผ ์ํคํ
์ฒ์ ๊ดํ ์ด์ผ๊ธฐ์
๋๋ค.
๐ Edge AI ์ํค ์์ธ ๋ฌธ์: GitHub Wiki โ Edge AI | ๋ชจ๋ํฐ๋ง ์ค์ฆ ๐ณ Docker Hub ์ด๋ฏธ์ง: safe-edge-integrated-ai | safe-edge-audio
๐ ์ Edge AI์ธ๊ฐ โ ํด๋ผ์ฐ๋ AI๋ ์ ๋๋ ์ด์
์ค๋งํธ ํฉํ ๋ฆฌ ํ์ฅ์ ์ธํฐ๋ท์ด ๋ถ์์ ํ๊ฑฐ๋ ์์ ์ฐจ๋จ๋ ํ์๋ง ํ๊ฒฝ์ธ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ํด๋ผ์ฐ๋ ์๋ฒ์ ์์์ ๋ณด๋ด์ ์ถ๋ก ํ๋ ๋ฐฉ์์ ์น๋ช ์ ์ธ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
โ ํด๋ผ์ฐ๋ AI ๋ฐฉ์
ํ์ฅ ์นด๋ฉ๋ผ โ ์ธํฐ๋ท โ ํด๋ผ์ฐ๋ ์๋ฒ ์ถ๋ก โ ๊ฒฐ๊ณผ ๋ฐํ
๋ฌธ์ : ๋คํธ์ํฌ ๋จ์ ์ ๊ฐ์ ์์ ๋ถ๊ฐ / ์ง์ฐ ์๊ฐ ์กด์ฌ
โ
Edge AI ๋ฐฉ์ (์ด ํ๋ก์ ํธ)
ํ์ฅ ์นด๋ฉ๋ผ โ ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด ์ง์ ์ถ๋ก โ ์ฆ์ ๊ฒฐ๊ณผ ์ ์ฅ
์ฅ์ : ๋คํธ์ํฌ ๋
๋ฆฝ / ์ค์๊ฐ ์ฒ๋ฆฌ / ํ์๋ง ์์ ๋์
ํ์ฌ๋ ํญ๋ฐ์ด ์ผ์ด๋๋ ๋ฐ๋ก ๊ทธ ์๊ฐ, ๋คํธ์ํฌ๋ ํจ๊ป ๋๊ธธ ์ ์์ต๋๋ค. ๊ทธ ์๊ฐ์ ๊ฐ์ง๊ฐ ์ ๋๋ค๋ ๊ฑด ์์คํ ์ ์กด์ฌ ์ด์ ์์ฒด๋ฅผ ๋ถ์ ํ๋ ๊ฒ์ ๋๋ค. ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด์์ ์ง์ ์ถ๋ก ํ๋ ๊ฒ์ด ์ ์ผํ ๋ต์ด์์ด์.
๐งฉ 4์ข AI ํ๋ ๊ตฌ์ฑ
| ํ๋ | ๊ฐ์ง ๋์ | ๋ชจ๋ธ | ์ ๋ ฅ ์ฅ์น |
|---|---|---|---|
safe-edge-integrated-ai | ๐ฅ ํ์ฌ ๊ฐ์ง | YOLOv8 | CSI ์นด๋ฉ๋ผ |
safe-edge-integrated-ai | ๐ง ์์ธ ์ด์ (์ฐ๋ฌ์งยท๊ตฝํ) | YOLOv8 Pose | ๋์ผ ์นด๋ฉ๋ผ |
safe-edge-audio | ๐ฅ ์ด์ ์์ (ํญ๋ฐยท์ด์ฑ) | YAMNet | USB ๋ง์ดํฌ |
bme280-sensor | ๐ก๏ธ ์จ์ต๋ยท๊ธฐ์ | BME280 ์ง์ ์ฝ๊ธฐ | I2C GPIO |
๋ชจ๋ ํ๋๋ ์ถ๋ก ๊ฒฐ๊ณผ๋ฅผ InfluxDB safe_edge_db์ ๊ธฐ๋กํฉ๋๋ค. ํ์ฌ ๊ฐ์ง ๊ฒฐ๊ณผ๋ 0 ๋๋ 1์ ์ด์ง๊ฐ์ผ๋ก ์ ์ฅ๋ฉ๋๋ค.
๐ฅ Episode 10-1. ARM ์ํคํ ์ฒ โ “exec format error”
์ฒซ ๋ฒ์งธ ๋ฒฝ์ v1์ ์ฌ๋ฆฌ์๋ง์ ๋ฐ๋ก ์์ต๋๋ค.
exec /hello-app: exec format error
PC(x86_64)์์ docker build๋ฅผ ํ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก x86_64 ์ํคํ
์ฒ ์ด๋ฏธ์ง๊ฐ ์์ฑ๋ฉ๋๋ค. ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด๋ ARM64 ์ํคํ
์ฒ์
๋๋ค. ์คํ ์์ฒด๊ฐ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
ํด๊ฒฐ: docker buildx๋ก ARM64 ์ ์ฉ ์ด๋ฏธ์ง๋ฅผ ๋น๋ํฉ๋๋ค.
# --platform ์ต์
์ผ๋ก ์ํคํ
์ฒ ๋ช
์
docker buildx build --platform linux/arm64 \
-t minsoo0919/safe-edge-integrated-ai:v2 \
--push .
๐ก ๊ตํ: ARM ๊ธฐ๋ฐ ๋ ธ๋์ ๋ฐฐํฌํ ๋๋ ์ด๋ฏธ์ง ๋น๋ ๋จ๊ณ๋ถํฐ
--platform linux/arm64๋ฅผ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ๊ณ ์ ํด์ผ ํฉ๋๋ค.
๐ฅ Episode 10-2. Grafana โ InfluxDB ์ฐ๊ฒฐ ์คํจ โ ๋ด๋ถ/์ธ๋ถ DNS ๊ฒฝ๊ณ
ArgoCD๋ฅผ ํตํด InfluxDB๋ฅผ K3s ํด๋ฌ์คํฐ ๋ด๋ถ์ ์ฌ๋ฆฌ๊ณ , Grafana์์ ์ฐ๊ฒฐํ๋ ค ํ์ต๋๋ค. Grafana ๋ฐ์ดํฐ ์์ค ์ค์ ์ K3s ๋ด๋ถ DNS ์ฃผ์๋ฅผ ์
๋ ฅํ๋๋ connection refused.
http://influxdb-svc.monitoring.svc.cluster.local:8086
โ connection refused โ
์์ธ: Grafana๋ K3s ํด๋ฌ์คํฐ ์ธ๋ถ Host PC์ Docker ์ปจํ ์ด๋๋ก ๋ ์์ต๋๋ค. K3s ๋ด๋ถ DNS๋ ํด๋ฌ์คํฐ ๋ด๋ถ ํ๋๋ผ๋ฆฌ๋ง ํต์ ๊ฐ๋ฅํฉ๋๋ค. ํด๋ฌ์คํฐ ๋ฐ์์ ๋ด๋ถ DNS๋ฅผ ์ฌ์ฉํ๋ ๊ฑด ๊ตฌ์กฐ์ ์ผ๋ก ๋ถ๊ฐ๋ฅํฉ๋๋ค.
ํด๊ฒฐ: ๋ง์คํฐ ๋ ธ๋ ๊ณ ์ IP + NodePort ์กฐํฉ์ผ๋ก ๋ณ๊ฒฝํฉ๋๋ค.
# ๋ณ๊ฒฝ ์ (๋ถ๊ฐ)
http://influxdb-svc.monitoring.svc.cluster.local:8086
# ๋ณ๊ฒฝ ํ (์ ์)
http://10.10.10.10:30086
์ถ๊ฐ๋ก DB๋ช
์ ์คํ(sage_edge_db โ safe_edge_db)๋ ์์์ต๋๋ค. ์ด๊ฒ๋ ํจ๊ป ์์ ํ๊ณ Save & Test ์ฑ๊ณต.
๐ก ๊ตํ: ์ํคํ ์ฒ๋ฅผ ์ค๊ณํ ๋๋ถํฐ ํด๋ฌ์คํฐ ๋ด๋ถ/์ธ๋ถ ํต์ ๊ฒฝ๊ณ๋ฅผ ๋ช ํํ ๊ตฌ๋ถํด๋๋ฉด ์ด๋ฐ ํผ๋์ ์๋ฐฉํ ์ ์์ต๋๋ค.
๐ฅ Episode 10-3. ์นด๋ฉ๋ผ ์ธ์ โ v1์์ v7๊น์ง
๊ฐ์ฅ ์ค๋ ๊ฑธ๋ ธ๊ณ , ๊ฐ์ฅ ๋ง์ด ๋ฐฐ์ด ํธ๋ฌ๋ธ์ํ ์ ๋๋ค.
์ฆ์: ํ์ฌ ๊ฐ์ง ํ๋๋ฅผ ๋ฐฐํฌํ๋๋ ๋ก๊ทธ์ ๊ณ์ ์ด๋ฐ ๋ฉ์์ง๋ง ๋น๋๋ค.
Failed to read frame from camera
No working camera found
์ฒ์์ ์ ๊ทผ:
# USB ์น์บ ๊ธฐ์ค์ ์ผ๋ฐ์ ์ธ ๋ฐฉ์์ผ๋ก ์๋
cap = cv2.VideoCapture(0)
v3, v4, v5๋ฅผ ๊ณ์ ๋น๋ํ๋ฉฐ ๋ค์ํ ๋ฐฉ์์ ์๋ํ์ต๋๋ค. v6์์๋ ์์ ๋น๋ ์์ฒด๊ฐ ์คํจํฉ๋๋ค.
Package 'libgl1-mesa-glx' has no installation candidate
Debian Trixie ๋ฒ ์ด์ค ์ด๋ฏธ์ง์์ libgl1-mesa-glx ํจํค์ง๋ช
์ด libgl1๋ก ํตํฉ ๋ณ๊ฒฝ๋ ๊ฒ์ด์์ต๋๋ค.
๊ทผ๋ณธ ์์ธ์ ๋ฐ๊ฒฌ: ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด 5๋ Pi 4์ ๋ฌ๋ฆฌ ์๋ก์ด ISP ์นฉ(RP1)์ ์ฌ์ฉํ๋ฉฐ, CSI ์นด๋ฉ๋ผ๊ฐ ๊ตฌํ V4L2 ๋๋ผ์ด๋ฒ๊ฐ ์๋ libcamera ์ ์ฉ ์ํคํ
์ฒ๋ก ๋์ํฉ๋๋ค.
# ์นด๋ฉ๋ผ ํ์ธ
rpicam-hello --list-cameras
# โ [0] : ov5647 [2592x1944] (/base/soc/i2c0mux/...)
# Modes: 'SRGGB10_CSI2P' ...
# libcamera ๋ฐฉ์์ผ๋ก ๋์ ํ์ธ โ
cv2.VideoCapture(0) + V4L2 ๋ฐฉ์์ผ๋ก๋ ์ด ์นด๋ฉ๋ผ์ ์ ๋ ์ ๊ทผํ ์ ์์์ต๋๋ค.
v7 ํด๊ฒฐ: GStreamer ํ์ดํ๋ผ์ธ(libcamerasrc)์ผ๋ก ์ ํ
# ๋ณ๊ฒฝ ์ (V4L2 ๋ฐฉ์ โ ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด 5 CSI ์นด๋ฉ๋ผ์ ๋์ ์ ํจ)
cap = cv2.VideoCapture(0)
# ๋ณ๊ฒฝ ํ (GStreamer + libcamerasrc โ v7 ์ต์ข
ํด๊ฒฐ)
pipeline = (
"libcamerasrc ! "
"video/x-raw, width=640, height=480, framerate=30/1 ! "
"videoconvert ! "
"appsink drop=True max-buffers=1"
)
cap = cv2.VideoCapture(pipeline, cv2.CAP_GSTREAMER)
YAML์ ๋ณผ๋ฅจ ๋ง์ดํธ๋ /dev/video0 ๋จ์ผ์์ /dev ๋๋ ํฐ๋ฆฌ ์ ์ฒด๋ก ๋ณ๊ฒฝํ์ต๋๋ค.
# ๋ณ๊ฒฝ ์ : ํน์ ์ฅ์น ๋ฒํธ๋ง ๋ง์ดํธ
volumes:
- name: camera-dev
hostPath:
path: /dev/video0
# ๋ณ๊ฒฝ ํ: /dev ์ ์ฒด ๋ง์ดํธ (์ค์ ์คํธ๋ฆผ ์ฅ์น ๋ฒํธ ์ ๊ทผ ํ์ฉ)
volumes:
- name: dev
hostPath:
path: /dev
๐ก ๊ตํ: ์๋ก์ด ํ๋์จ์ด๋ฅผ ์ฌ์ฉํ ๋๋ ์ธํฐ๋ท ์์ ์ฝ๋๋ฅผ ๋ฐ๋ก ์ ์ฉํ๊ธฐ ์ ์ ๊ณต์ ๋ฌธ์์์ ๋๋ผ์ด๋ฒ ์คํ์ ๋จผ์ ํ์ธํด์ผ ํฉ๋๋ค. ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด 5์ ์นด๋ฉ๋ผ๋ Pi 4์ ๊ทผ๋ณธ์ ์ผ๋ก ๋ค๋ฆ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ปจํ ์ด๋์์ ๋๋ฒ๊น ํ๊ธฐ ์ ์ ํธ์คํธ โ Docker โ Kubernetes ์์๋ก ํ ๋จ๊ณ์ฉ ๊ฒ์ฆํ๋ ๋ฐํ ์ ๋ฐฉ์์ด ์๊ฐ์ ๊ฐ์ฅ ์ ์ฝํฉ๋๋ค.
๐ InfluxDB ๋ฐ์ดํฐ ์คํค๋ง
| Measurement | ์ฃผ์ Field | ์๋ฏธ |
|---|---|---|
fire_detection | is_fire (0/1), confidence | ํ์ฌ ๊ฐ์ง ์ฌ๋ถ |
pose_detection | is_fallen (0/1), is_bent (0/1) | ์์ ์ ์์ธ ์ด์ |
acoustic_detection | is_danger (0/1), event_type | ์ด์ ์์ ๊ฐ์ง |
environment_data | temperature, humidity, pressure | ํ๊ฒฝ ์ผ์ |
๐ Grafana ๊ด์ ๋์๋ณด๋ โ mean()์ด ์๋๋ผ max()๋ฅผ ์จ์ผ ํ๋ ์ด์
์ฒ์์ Grafana ๊ทธ๋ํ์ ์ด์ํ ๊ฐ์ด ๋จ๊ธฐ ์์ํ์ต๋๋ค.
ํ์ฌ ๊ฐ์ง ๋ฐ์ดํฐ๊ฐ 0 ๋๋ 1์ด์ด์ผ ํ๋๋ฐ
โ 0.200, 0.600 ๊ฐ์ ์์์ ๊ฐ์ด ํ์๋จ
์์ธ: Grafana์ Time Series ํจ๋์ ๊ธฐ๋ณธ์ ์ผ๋ก mean()(ํ๊ท ) ์ง๊ณ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. 0๊ณผ 1๋ง ์๋ ์ด์ง ๋ฐ์ดํฐ์ ํ๊ท ์ ๋ด๋ฉด ๊ตฌ๊ฐ ๋ด ๊ฐ์ง ๋น์จ๋ก ๊ณ์ฐ๋์ด ์์์ ์ด ๋์ต๋๋ค.
ํด๊ฒฐ: max()๋ก ๋ณ๊ฒฝํฉ๋๋ค. ๊ตฌ๊ฐ ์์์ ๋จ ํ ๋ฒ์ด๋ผ๋ ๊ฐ์ง๋์ผ๋ฉด 1์ ํ์ํฉ๋๋ค. ๊ด์ ์์คํ
์์ “ํ ๋ฒ์ด๋ผ๋ ํ์ฌ๊ฐ ๊ฐ์ง๋์ผ๋ฉด ๊ฒฝ๋ณด”๊ฐ ์ฌ๋ฐ๋ฅธ ๋ก์ง์
๋๋ค.
-- ๋ณ๊ฒฝ ์
SELECT mean(is_fire) FROM fire_detection WHERE time > now()-5m GROUP BY time(10s)
-- ๋ณ๊ฒฝ ํ
SELECT max(is_fire) FROM fire_detection WHERE time > now()-5m GROUP BY time(10s)
4๊ฐ ํจ๋ ๊ตฌ์ฑ:
| ํจ๋ | ์ธก์ ๊ฐ | 0 (์ ์) | 1 (๊ฐ์ง) |
|---|---|---|---|
| ๐ฅ ํ์ฌ ๊ฐ์ง | max(is_fire) | โ ์ด๋ก / SAFE | ๐จ ๋นจ๊ฐ / FIRE |
| ๐จ ์ฐ๋ฌ์ง ๊ฐ์ง | max(is_fallen) | โ ์ด๋ก / SAFE | ๐จ ๋นจ๊ฐ / FALLEN |
| โ ๏ธ ๊ตฝํ ๊ฐ์ง | max(is_bent) | โ ์ด๋ก / SAFE | โ ๏ธ ๋ ธ๋ / BENT |
| ๐ ์ด์ ์์ | max(is_danger) | โ ์ด๋ก / SAFE | ๐จ ๋นจ๊ฐ / DANGER |
โ Edge AI ์์ฑ ์ํ
| ํญ๋ชฉ | ์ํ |
|---|---|
| YOLOv8 ํ์ฌ ๊ฐ์ง (libcamera + GStreamer) | โ |
| YOLOv8 ์์ธ ์ด์ ๊ฐ์ง | โ |
| YAMNet ์ด์ ์์ ๋ถ๋ฅ | โ |
| BME280 ํ๊ฒฝ ์ผ์ | โ |
| InfluxDB ๋ฐ์ดํฐ ์ ์ฅ | โ |
| Grafana 4ํจ๋ ์ค์๊ฐ ๊ด์ | โ |
์ด์ AI ํ๋๋ค์ด ํ์ฅ์ 24์๊ฐ ๊ฐ์ํ๊ณ ์์ต๋๋ค. ๋ค์ ๋ฌธ์ ๋ ์ด ๋ฐ์ดํฐ๊ฐ ๋์์ด ์์ด๋ ๊ฒ์ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ๋๋์ ๋๋ค. ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด SSD๋ ๋ฌดํํ์ง ์์ผ๋๊น์.
๐ ๋ค์ ํธ: 5ํธ โ ๋ฐ์ดํฐ ํฐ์ด๋ง: K3s CronJob์ด CPU๋ฅผ 1291%๊น์ง ํญ์ฃผ์ํจ ๋ ๐ Edge AI ์ํค ์ ์ฒด: GitHub Wiki โ Edge AI Wiki