第一階段作業報告 / Phase 1 Assignment

AI 監視系統
Surveillance

整合 YOLO 物件偵測、MediaPipe 手部追蹤、臉部網格與即時影像串流的智慧監控平台

Python OpenCV YOLOv8 MediaPipe Flask WebRTC HTML/CSS/JS
姓名 // 阮文孟
學號 // 1111310035
01

AI 監視系統製作

本系統是以 Python 為後端核心,結合多種電腦視覺技術所建構的即時智慧監控平台。 透過 Web Camera 擷取影像,經由 YOLOv8 進行物件偵測、MediaPipe 實現手部追蹤與臉部網格偵測, 最終透過 Flask 將影像串流呈現於前端網頁,實現完整的 AI 監視功能。

開發語言:Python 3.10 / HTML5 / CSS3 / JavaScript
主要框架:Flask (後端)、OpenCV (影像處理)、Ultralytics YOLOv8
核心函式庫:MediaPipe、NumPy、PIL、threading
前端技術:Vanilla JS、Canvas API、Server-Sent Events
系統目標:即時偵測人員、車輛、手勢與臉部特徵,並記錄事件時間軸
核心功能
  • 即時影像串流(MJPEG / WebRTC)
  • YOLOv8 物件偵測與計數
  • 手部 21 點骨架追蹤
  • 468 點臉部網格偵測
  • 事件時間軸記錄
技術亮點
  • 多執行緒影像處理架構
  • Flask + MJPEG 串流輸出
  • 前後端分離設計
  • 模組化功能切換介面
  • 即時物件資訊疊加顯示
應用情境
  • 入口人員進出計數
  • 停車場車輛統計
  • 手勢控制互動介面
  • 門禁臉部辨識前處理
  • 異常行為事件記錄
02

資訊專案結構說明

project directory tree
ai_surveillance/ # 專案根目錄 ├── app.py # Flask 主程式入口 ├── requirements.txt # Python 套件清單 ├── core/ # 核心功能模組 │ ├── camera.py # Web Camera 擷取模組 │ ├── yolo_detector.py # YOLOv8 物件偵測模組 │ ├── hand_detector.py # MediaPipe 手部偵測模組 │ ├── face_mesh.py # MediaPipe 臉部網格模組 │ └── event_logger.py # 事件時間軸記錄模組 ├── models/ # AI 模型存放目錄 │ └── yolov8n.pt # YOLOv8 Nano 預訓練權重 ├── static/ # 前端靜態資源 │ ├── css/ │ │ └── style.css # 主樣式表 │ ├── js/ │ │ ├── main.js # 前端主邏輯 │ │ ├── timeline.js # 時間軸 UI 元件 │ │ └── overlay.js # 物件資訊疊加框 │ └── img/ # 圖示與截圖 ├── templates/ # Jinja2 HTML 模板 │ ├── index.html # 主監控介面 │ └── dashboard.html # 統計儀表板 ├── logs/ # 事件日誌輸出目錄 │ └── events_YYYYMMDD.json # 每日事件記錄檔 └── tests/ # 功能測試腳本 ├── test_camera.py ├── test_yolo.py ├── test_hand.py └── test_face.py
模組依賴關係
  • app.py 匯入所有 core/ 模組
  • 各偵測模組互相獨立,可單獨啟用
  • camera.py 提供影像幀給各偵測器
  • event_logger.py 接收各模組事件
Flask 路由設計
  • GET / — 主監控頁面
  • GET /video_feed — MJPEG 串流
  • GET /events — SSE 事件推送
  • POST /config — 切換偵測模式
03

資訊系統環境圖 (UML) 與程式邏輯說明

👤 使用者User
📷 Web CameraInput Device
🖥 Flask Web Server
app.py — HTTP / MJPEG Stream
📹 Cameracamera.py
🎯 YOLOyolo_detector.py
✋ Handhand_detector.py
😊 Face Meshface_mesh.py
📋 Event Loggerevent_logger.py — JSON Log
🖼 影像串流MJPEG Output
📊 物件資訊Overlay JSON
📅 時間軸SSE Events
程式邏輯說明 — 主迴圈 (app.py)
# Flask + OpenCV 核心串流邏輯 def generate_frames(): cap = cv2.VideoCapture(0) # 開啟攝影機 while True: ret, frame = cap.read() # 讀取影像幀 if not ret: break # ① 依照模式選擇偵測器 if mode == 'yolo': frame, detections = yolo_detector.detect(frame) event_logger.log(detections) elif mode == 'hand': frame, landmarks = hand_detector.detect(frame) elif mode == 'face': frame = face_mesh.draw_mesh(frame) # ② 將 OpenCV 幀編碼為 JPEG _, buffer = cv2.imencode('.jpg', frame) frame_bytes = buffer.tobytes() # ③ 以 multipart/x-mixed-replace 格式輸出 yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n')
04

功能測試一:Web Camera

📷
Web Camera 初始化與串流測試
OpenCV VideoCapture
PASS

使用 OpenCV 的 cv2.VideoCapture(0) 開啟預設攝影機, 讀取影像幀後透過 Flask 的 MJPEG 串流回應傳送至前端 <img> 標籤顯示。 測試重點為攝影機存取權限、幀率穩定性與串流延遲。

  • 安裝 OpenCV:pip install opencv-python
  • 測試攝影機開啟:cap = cv2.VideoCapture(0)
  • 驗證幀讀取:ret, frame = cap.read()
  • 啟動 Flask 伺服器,瀏覽器開啟 localhost:5000
  • 確認影像正常顯示且無明顯延遲(目標 < 200ms)
RESOLUTION640 × 480 px FPS30 fps LATENCY~80 ms STATUS✓ PASS
05

功能測試二:YOLO 物件偵測

🎯
YOLOv8 即時物件偵測
Ultralytics YOLOv8n — COCO 80 classes
PASS

載入 Ultralytics YOLOv8 Nano 模型(yolov8n.pt), 對每幀影像進行物件偵測,支援 COCO 資料集的 80 種類別。 重點偵測對象為人員(person)與車輛(car/truck/bus),並將偵測結果繪製邊界框與信心分數。

  • 安裝套件:pip install ultralytics
  • 載入模型:model = YOLO('yolov8n.pt')
  • 執行推論:results = model(frame)
  • 繪製邊界框與類別標籤至影像幀
  • 計算 person / vehicle 數量並輸出至事件系統
MODELYOLOv8n CLASSES80 CONF THRESH0.5 STATUS✓ PASS
YOLO 偵測程式片段
from ultralytics import YOLO import cv2 model = YOLO('models/yolov8n.pt') def detect(frame): results = model(frame, conf=0.5, verbose=False)[0] detections = [] for box in results.boxes: cls_id = int(box.cls) label = model.names[cls_id] conf = float(box.conf) x1,y1,x2,y2 = map(int, box.xyxy[0]) cv2.rectangle(frame, (x1,y1),(x2,y2), (0,229,255), 2) cv2.putText(frame, f'{label} {conf:.2f}', (x1, y1-8), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,229,255), 1) detections.append({'label': label, 'conf': conf}) return frame, detections
06

功能測試三:手部偵測 (MediaPipe)

MediaPipe Hands — 21 點骨架追蹤
google/mediapipe HandLandmark
PASS

使用 Google MediaPipe 的 Hands 解決方案,偵測畫面中的手部並標記 21 個關節點(Landmark)。 可同時偵測最多雙手,輸出每個關節的 3D 座標(x, y, z),並繪製手部骨架連線。

  • 安裝:pip install mediapipe
  • 初始化:mp_hands = mp.solutions.hands.Hands()
  • RGB 轉換後執行 hands.process(image)
  • 繪製 21 個 Landmark 點與連線骨架
  • 輸出座標用於手勢辨識邏輯(例:OK / Peace 手勢)
LANDMARKS21 points MAX HANDS2 DETECT CONF0.7 STATUS✓ PASS
07

功能測試四:臉部網格偵測

😊
MediaPipe FaceMesh — 468 點臉部網格
google/mediapipe FaceMesh
PASS

使用 MediaPipe FaceMesh 模型,對影像中的臉部偵測並輸出 468 個精密網格點(3D Landmark)。 可用於臉部特徵分析、頭部姿態估計(Head Pose Estimation)與眨眼偵測等應用。

  • 初始化:face_mesh = mp.solutions.face_mesh.FaceMesh()
  • 設定 refine_landmarks=True 以取得眼睛/嘴唇精細點
  • 執行 face_mesh.process(rgb_frame)
  • 使用 mp.solutions.drawing_utils 繪製網格
  • 計算 Eye Aspect Ratio (EAR) 偵測眨眼
LANDMARKS468 points REFINETrue MAX FACES2 STATUS✓ PASS
08

全系統功能

📹

即時影像串流

透過 Flask 的 MJPEG multipart 串流技術,將處理後的影像即時傳送至前端。支援多個客戶端同時觀看,幀率穩定於 25-30 fps。

📦

物件資訊顯示框

偵測到物件時,於影像上疊加彩色邊界框(Bounding Box)與資訊標籤,顯示物件類別、信心分數與編號。同時在側欄顯示結構化物件列表。

📅

事件時間軸 (Event Timeline)

以 Server-Sent Events (SSE) 技術,將偵測到的重要事件(如有人進入、車輛出現)即時推送至前端,以時序方式顯示於時間軸 UI 元件中。

事件標示

系統依據規則(如連續幀偵測到 person 超過閾值)自動觸發警示事件,於畫面角落顯示閃爍標示,並同步寫入 JSON 日誌檔。

🔢

計算人數 / 車數

YOLO 偵測結果按類別(person / car / truck / bus)分類統計,即時顯示當前幀中的人員數量與車輛數量,並繪製數量折線圖於儀表板。

偵測模式切換

前端介面提供切換按鈕,可在 Raw Camera、YOLO、手部偵測、臉部網格、全功能模式間即時切換,POST 請求更新後端 mode 變數。

EVENT TIMELINE — 事件時間軸範例
2025-06-01 09:02:14
人員偵測 — 進入區域
YOLO 偵測到 person (conf: 0.92),位置:Frame 左側 1/3 區域,持續 3 幀以上觸發事件。
2025-06-01 09:05:37
車輛計數更新
偵測到 2 輛車輛(car × 2),計數器更新,寫入日誌 events_20250601.json。
2025-06-01 09:08:55
手勢偵測 — Peace 手勢
MediaPipe Hands 偵測到 Peace 手勢,食指與中指展開角度 > 閾值,觸發互動事件。
2025-06-01 09:12:03
臉部偵測 — 眨眼事件
FaceMesh EAR 值低於 0.25 持續 2 幀,判定為眨眼動作,記錄事件時間點。
09

使用 AI 工具對話連結

Google Gemini
用於查詢 MediaPipe 設定參數、解釋 YOLO 模型差異、協助撰寫 Flask SSE 事件推送邏輯。
↗ gemini.google.com
Claude (Anthropic)
用於程式碼除錯、HTML/CSS 介面設計建議、系統架構規劃與報告內容組織。
↗ claude.ai
ChatGPT (OpenAI)
用於查詢 OpenCV 函數用法、YOLOv8 訓練流程、Python 多執行緒影像處理最佳實踐。
↗ chatgpt.com
AI 工具使用紀錄 — 主要對話紀錄說明
  • Gemini 詢問:「MediaPipe FaceMesh refine_landmarks 選項有什麼效果?」→ 取得眼睛 Iris 及嘴唇精細 Landmark 說明
  • Claude 詢問:「如何在 Flask 中使用 Server-Sent Events 推送即時事件?」→ 取得 Response(stream_with_context(...)) 完整範例
  • ChatGPT 詢問:「YOLOv8n 與 YOLOv8s 在 CPU 推論速度上的差異?」→ 確認選用 nano 版本以確保即時性
  • Gemini 詢問:「Python threading 與 multiprocessing 哪個更適合影像處理迴圈?」→ 採用 threading 避免 GIL 在 I/O 操作上的限制
10

Trouble Shooting 與學習心得

⚠ 問題 01 — Flask 串流 <img> 標籤無法顯示影像
原因:MJPEG 串流需要正確設定 Content-Type 標頭與 multipart boundary。
解決:確認 Response 設定為 mimetype='multipart/x-mixed-replace; boundary=frame', 並在 <img src="/video_feed"> 中直接指向串流路由即可。
⚠ 問題 02 — YOLOv8 推論在 CPU 上速度過慢(<5 fps)
原因:預設推論未使用 half precision,每幀影像解析度過高。
解決:輸入前將影像縮小至 320×240,並設定 model(frame, imgsz=320),推論速度提升至 18-22 fps。
⚠ 問題 03 — MediaPipe Hands 偵測在背光環境失效
原因:強烈背光導致手部區域對比度不足,MediaPipe 無法初始化偵測。
解決:在送入 MediaPipe 前加入直方圖均衡化(cv2.equalizeHist)預處理,顯著提升偵測穩定性。
⚠ 問題 04 — 多模式同時執行時瀏覽器頁面卡頓
原因:YOLO 與 MediaPipe 同時推論造成 CPU 飽和,Flask 串流幀率驟降。
解決:改為在每 N 幀才執行一次 YOLO(frame skip = 3),MediaPipe 每幀執行,兩者結果疊加至同一輸出幀,整體幀率恢復至 20+ fps。
⚠ 問題 05 — SSE 事件在 Safari 瀏覽器無法接收
原因:Safari 對 EventSource 的 CORS 標頭要求較嚴格。
解決:在 Flask 回應中加入 Access-Control-Allow-Origin: *,並使用 Flask-CORS 套件統一處理。

學習心得

  • 透過本專案深刻理解了電腦視覺 Pipeline 的完整流程:影像擷取 → 前處理 → AI 推論 → 後處理 → 串流輸出,每個環節都有其優化空間。
  • YOLOv8 的使用非常直觀,但在 CPU 環境下需要謹慎設計推論策略(frame skip、解析度調整),才能維持即時性。
  • MediaPipe 的模型已高度優化,手部與臉部偵測在一般筆電上就能達到流暢的效果,非常適合入門級 AI 應用開發。
  • Flask 的 MJPEG 串流方案雖然簡單易實作,但在多人連線場景下需要考慮改用 WebRTC 或 WebSocket 以獲得更佳的擴展性。
  • AI 工具(Gemini、Claude、ChatGPT)在除錯與概念釐清方面幫助極大,但最終的系統整合與效能調優仍需要親自動手實驗才能真正理解。
  • 事件驅動設計(Event-driven)讓監控系統的擴展變得容易,未來可輕鬆加入更多觸發規則(如異常聚集、越線偵測)而不影響核心串流邏輯。