PHASE 2: TRAFFIC LIGHT CONTROL

AI Car 紅綠燈辨識控制 實作報告

第二階段:以 YOLOv8 實現紅綠燈即時辨識,整合多執行緒 PID 循線與自動停車控制

PiCamera2 YOLOv8 時序平滑 PID Controller Flask WebUI Multithreading
👤 411106242 張晴茵 👤 611306007 吳運陽
YouTube Shorts

🎬實作錄影

小車實際行駛中辨識紅綠燈並自動停車、恢復前進的完整過程。

點擊前往 YouTube Shorts 觀看

Source Code

📦GitHub 專案連結

本專案為 AI Car 自駕小車的第二階段實作,在 Phase 1 循線基礎上,新增紅綠燈辨識模組(traffic_light_detection.py),以 YOLOv8 即時推論搭配時序平滑機制,實現穩定的紅燈停車與綠燈恢復行駛功能。完整程式碼於以下 branch 開放瀏覽。

前往 GitHub · branch:紅綠燈
YOLOv8 推論降頻 🛑 紅燈自動停車

📁專案結構

Project Directory

ai_car_project/

📁 ai_car_project/
├── 🐍 lane_detection.py 主程式 — PID循線 / 多執行緒
├── 🐍 traffic_light_detection.py ★ Phase 2 — YOLOv8 燈號辨識模組
├── 🐍 app.py Flask WebUI 後端
├── 🐍 pid_controller.py PID 演算法 — 誤差修正、抗飽和,輸出動力比例
├── 🐍 motor_control.py 底層驅動 — I²C 操控 PCA9685,封裝四輪運動邏輯
├── 🤖 best.pt YOLOv8 訓練權重
├── 📄 settings.json 參數持久化設定
└── 📁 templates/
└── 📄 index.html WebUI 前端控制介面

💻程式邏輯說明

System Architecture — Phase 2

紅綠燈辨識系統架構

系統以三條執行緒並行運作:capture_thread 持續從 PiCamera2 擷取影像並寫入共享緩衝區 raw_framelane_follow_threadinference_thread 分別讀取影像,呼叫 TrafficLightDetector 模組進行 YOLOv8 推論,將穩定燈號狀態寫入共享變數 tl_statelane_follow_thread 依據 tl_state 決策:偵測到紅燈則呼叫 motor.stop() 停車,否則繼續執行 PID 循線輸出馬達訊號。所有共享資源均以 Lock 保護(raw_frame_locktl_locki2c_lockframe_lock),確保多執行緒存取安全。
系統啟動 capture_thread «shared buffer» raw_frame 感知與推論層 lane_follow_thread inference_thread «module» ★ TrafficLightDetector «shared» tl_state (tl_lock) «shared buffer» annotated_frame ⚙️ motor_control 📺 VideoFeed 🌐 Flask WebUI 更新 (raw_frame_lock) 讀取 (AUTO 模式) 讀取 (MANUAL 模式) 呼叫辨識 呼叫辨識 更新燈號狀態 檢查燈號 (紅燈停車邏輯) 寫入標注畫面 (frame_lock) 寫入標注畫面 (frame_lock) 串流輸出 控制動力 (i2c_lock) 手動指令 (i2c_lock)

📸實測成果截圖

Red Light Detection

紅燈停等偵測

Green Light Detection

綠燈恢復通行

Web Dashboard

儀表板即時監控

前端可即時調整信心門檻 (tl_conf) 與強制停等開關。

🗃️Roboflow 訓練資料集

YOLOv8 Training Data

資料集建置與標註

使用 Roboflow 平台建置紅綠燈辨識訓練資料集,涵蓋 redgreenyellow 三個類別,經過多版本迭代標註與增強,最終匯出供 YOLOv8 訓練使用。

Classes

標註類別

共標註 3 個類別redgreenyellow,紅燈樣本數最多以確保停車判斷的穩定性。

Dataset

資料集總覽

資料集包含 Train / Valid / Test 三個分割,並套用翻轉、亮度調整等資料增強,提升模型對不同光源環境的泛化能力。

Versions

版本迭代

透過多版本管理追蹤每次標註修正與增強策略的差異,選用效果最佳的版本匯出 YOLOv8 格式進行訓練。

🛠️Trouble Shooting

Issue Log - Phase 2

實作過程遇到的挑戰

挑戰項目問題描述解決方案AI 協助狀態
多執行緒死鎖同時讀寫 I2C 導致 PCA9685 卡死。引入 i2c_lock 互斥鎖。Claude已修復
推論延遲YOLO 運算過重影響循線反應。實施降頻推論與縮小解析度。Claude已優化
偵測閃爍紅燈距離較遠時信心值不穩。增加時序平滑與低門檻機制。Claude已優化
面積誤判遠處路燈被偵測為紅燈,觸發誤停車。加入 TL_MIN_AREA_RATIO=0.003 面積過濾。Claude已解決
停等不恢復紅燈移出畫面後小車未能恢復行駛。實作 no_detect_frames 計數,≥10 幀無偵測則重設狀態。Claude已解決
最小面積上限TL_MIN_AREA_RATIO 過高導致近距離燈號也被過濾。將上限從 0.01 調整為 0.003,兼顧遠近距離偵測。Claude已調整

💡學習心得

Reflection — Phase 1 vs Phase 2

與第一階段比較分析

面向Phase 1 — 車道辨識循線Phase 2 — 紅綠燈控制
感知方式 HSV 顏色過濾 + 六邊形 ROI 遮罩,純影像處理 YOLOv8 深度學習推論,搭配面積過濾與時序平滑
控制邏輯 PID 閉環控制偏差值,輸出馬達 PWM 在 PID 循線之上疊加燈號狀態判斷,偵測紅燈則停車
多執行緒 影像擷取 + WebUI 串流,以 frame_lock 保護 新增 inference_threadtl_locki2c_lock 等多把鎖,複雜度明顯提升
主要挑戰 大轉彎單線遺失、反光地板干擾 Canny 偵測 偵測閃爍(時序平滑解決)、遠距誤判(面積過濾解決)
AI 工具使用 透過 Claude 理解 HSV 原理、PID 參數調整方向 透過 Claude JSONL 記錄追蹤整個調校過程,共 3 個 session

第一階段主要依賴傳統影像處理(HSV 色彩空間、ROI 遮罩、PID 控制),在八樓走廊測試時,最大挑戰是反光地板讓 Canny 邊緣偵測失效,以及大轉彎時單側車道線消失導致轉向失控。透過 Claude 的輔助,理解了從灰階改用 HSV 亮度通道過濾白線的原理,也學會了 Single Lane Fallback 的補償思路。

第二階段引入 YOLOv8 後,系統複雜度大幅提升。最直觀的差異是從「被動偵測畫面」進化到「主動辨識語義目標」——不再只是看到白線,而是能理解「這是紅燈」並做出停車決策。但隨之而來的是推論延遲、偵測閃爍、誤判等新問題,需要靠降頻推論、時序平滑、面積過濾等機制逐一解決。

兩個階段最大的共同收穫是:有效使用 AI 的前提是把問題描述清楚。當提供完整的錯誤現象、已嘗試的方法與預期結果,Claude 的回應才會精準有用;反之,模糊的提問只會得到模糊的回答。第二階段開始用 JSONL 記錄每次對話,讓這個過程變得可追溯,也讓學習歷程更清晰。

🤖AI 工具使用記錄

AI Assistant — Claude

Claude 本地對話記錄(JSONL)

共 3 個 Session,涵蓋 TL 辨識調校、SSH 斷線排查、面積過濾參數調整等核心開發過程。

Session 1 · 2026-04-27
Session 2 · 2026-05-04
Session 3 · 2026-05-11
📄 查看完整對話記錄