平滑改為『只對可信讀數取中位數、空白跳過』+ 信心門檻 0.7
原本『讀不到一律當0』會把行駛中的慢速起步(creep, 如3/7/12km/h)+空白蓋成停, 誤剪掉起步畫面(實例: 02 的 03:25 起步被剪到 03:32)。 改為: 平滑時跳過空白/低信心,只對可信讀數取中位數;整個視窗都讀不到才當0。 停車段空白被周圍0判成停、行駛段空白被周圍車速判成動,兩者兼顧。 信心門檻 0.5->0.7,濾掉停車時的低信心誤讀(如把0看成70@0.57)。 實測 02: #3 由 03:11~03:32 縮為 03:13~03:20(creep 保留)。 本次調整由 Claude Opus 4.8 (1M context) 協助處理。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+12
-12
@@ -91,8 +91,8 @@ SAMPLE_INTERVAL = 1.0 # 每隔幾秒辨識一次 (秒)。1.0 = 每
|
||||
STOP_SECONDS = 4.0 # 時速為 0 連續超過幾秒,才算等紅燈 (秒)
|
||||
SPEED_THRESHOLD = 0 # 時速 <= 此值視為「停止」。0 = 只有讀到 0 才算停
|
||||
# 若想把「龜速 1~2 km/h」也當停止,可改成 1 或 2
|
||||
MIN_CONFIDENCE = 0.50 # OCR 信心低於此值的結果視為「未知」(交給平滑補值)
|
||||
# 提高到 0.5 可濾掉停車時偶發的低信心雜訊(如 60@0.39)
|
||||
MIN_CONFIDENCE = 0.70 # OCR 信心低於此值的結果視為「未知」(交給平滑用前後判斷)
|
||||
# 0.7 可濾掉停車時的低信心誤讀(如把 0 看成 70@0.57)
|
||||
MAX_SPEED = 300 # 合理時速上限,超過視為誤判(雜訊),當成未知
|
||||
|
||||
# --- 平滑濾波(關鍵!解決停車時 OCR 在 0 與雜訊間跳動的問題)----
|
||||
@@ -306,27 +306,27 @@ def is_stopped(s: Sample) -> bool:
|
||||
|
||||
def smooth_speeds(samples: List[Sample], window: int) -> List[int]:
|
||||
"""
|
||||
對逐秒速度做「讀不到當 0 + 中位數濾波」,壓掉停車時的跳動雜訊。
|
||||
1. 讀不到(None/??)一律當作 GPS=0(停止)。停車時 OCR 常讀不到或誤讀成小數字,
|
||||
當 0 處理後,孤立的誤讀(如把 0 看成 70)會被中位數吃掉,避免假性「起步」。
|
||||
2. 中位數濾波: 每個點取前後 window//2 範圍的中位數,孤立雜訊(單格 6/60/70)會被吃掉。
|
||||
對逐秒速度做平滑,壓掉停車時的跳動雜訊,同時不誤殺慢速起步(creep)。
|
||||
做法:每個取樣點取前後 window//2 範圍內「可信讀數(speed 不為 None)」的中位數;
|
||||
空白/低信心(None)『跳過不計』,而不是當 0。
|
||||
- 讀不到時改由前後決定: 前後都在停(0)→中位數 0(停);前後在動→中位數非0(動)。
|
||||
這樣停車段的空白會被周圍的 0 判成停,行駛段的空白會被周圍的車速判成動。
|
||||
- 整個視窗都讀不到才視為 0(停止)。
|
||||
- 孤立的誤讀(被高信心門檻 + 中位數雙重過濾)會被周圍多數吃掉。
|
||||
回傳與 samples 等長的整數速度陣列。
|
||||
"""
|
||||
n = len(samples)
|
||||
if n == 0:
|
||||
return []
|
||||
|
||||
# --- 1) 讀不到(None)一律當 0 ---
|
||||
filled: List[int] = [s.speed if s.speed is not None else 0 for s in samples]
|
||||
|
||||
# --- 2) 中位數濾波 ---
|
||||
half = max(0, window // 2)
|
||||
smoothed: List[int] = [0] * n
|
||||
for i in range(n):
|
||||
lo = max(0, i - half)
|
||||
hi = min(n, i + half + 1)
|
||||
win = sorted(filled[lo:hi])
|
||||
smoothed[i] = win[len(win) // 2]
|
||||
vals = sorted(samples[k].speed for k in range(lo, hi)
|
||||
if samples[k].speed is not None)
|
||||
smoothed[i] = vals[len(vals) // 2] if vals else 0 # 全讀不到 → 視為停止
|
||||
return smoothed
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user