From df8511608897400a20d489175d6ce0b1e170fdbe Mon Sep 17 00:00:00 2001 From: JianMiau Date: Wed, 3 Jun 2026 22:39:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=9C=9F=E8=B5=B7=E6=AD=A5?= =?UTF-8?q?=E9=80=9F=E5=BA=A6=E9=96=80=E6=AA=BB=20depart=5Fmin=5Fspeed:=20?= =?UTF-8?q?=E6=8E=92=E9=9A=8A=E9=BE=9C=E9=80=9F=E5=89=AA=E6=8E=89=E3=80=81?= =?UTF-8?q?=E7=9C=9F=E8=B5=B7=E6=AD=A5=E4=BF=9D=E7=95=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 使用者規則: 剪到『穩定起步』為止,之前的停車+龜速蠕動全剪;從穩定起步開始保留。 作法: 把移動段串起來(橋接 --- README.md | 1 + auto_remove_redlight.py | 31 +++++++++++++++++++++++++++++++ config.json | 1 + 3 files changed, 33 insertions(+) diff --git a/README.md b/README.md index f2755d9..99b6233 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ python auto_remove_redlight.py 01.MOV 03.MOV 05.MOV | `min_confidence` | `0.7` | OCR 信心低於此值視為「讀不到」(交給平滑用前後判斷)| | `smooth_window` | `5` | 中位數濾波視窗(取樣點數) | | `depart_seconds` | `8.0` | 起步門檻(秒):兩段停車間「持續行駛」需達到(滿)此秒數才算起步成功並保留(含這 8 秒);不足者(起步 N 秒內又停)視為仍在等待,連同短暫蠕動一起剪掉(處理車陣走走停停) | +| `depart_min_speed` | `15` | 真起步速度門檻(km/h):一段移動要「加速到」此速度才算真起步/行駛而保留(連同前面龜速起點一起留);若整段最高速都低於此(只是排隊龜速、從未真正騎走),整段改判停止剪掉 | | `cut_before_stop` | `2.0` | 進入紅燈端(速度到 0)移除起點再往前幾秒,連減速進站一起砍 | | `keep_after_stop` | `2.0` | 綠燈起步端(速度從 0 開始跑)移除終點提早幾秒,多留卡達起步畫面 | | `min_keep` | `0.8` | 保留片段短於此秒數即丟棄 | diff --git a/auto_remove_redlight.py b/auto_remove_redlight.py index 5e0469f..b78f348 100644 --- a/auto_remove_redlight.py +++ b/auto_remove_redlight.py @@ -106,6 +106,10 @@ SMOOTH_WINDOW = 7 # 中位數濾波視窗(取樣點數,奇數) DEPART_SECONDS = 8.0 # 起步門檻(秒): 兩段停車中間「持續行駛」需『達到(滿)』此秒數, # 才算真正起步成功並保留(含這 8 秒);不足者(起步 N 秒內又停) # 視為仍在等待,連同那段短暫蠕動一起剪掉(處理車陣走走停停)。 +DEPART_MIN_SPEED = 15 # 真起步速度門檻(km/h): 一段移動要「加速到」此速度才算真起步/行駛 + # 而保留(連同前面的龜速起點一起留);若整段移動最高速都低於此 + # (只是排隊龜速、從未真正騎走),則整段改判為停止一起剪掉。 + # 這能分辨「龜速後加速騎走(留)」vs「龜速後又停(剪)」。 # --- 剪輯 / 輸出參數 ---------------------------------------- # 紅燈移除段的頭尾「不對稱」微調: @@ -342,6 +346,32 @@ def find_keep_intervals(samples: List[Sample], duration: float, interval: float smoothed = smooth_speeds(samples, SMOOTH_WINDOW) stopped = [v <= SPEED_THRESHOLD for v in smoothed] + # 0) 龜速重新歸類: 把「從未加速到真正速度」的移動段改判為停止(會被剪)。 + # 先把移動段串起來(中間 < STOP_SECONDS 的短暫停頓視為 OCR 瞬斷,併入同一段), + # 若整段最高速 < DEPART_MIN_SPEED → 只是排隊龜速,整段改判停止; + # 有加速到 DEPART_MIN_SPEED 的(真起步/行駛)才保留,且連龜速起點一起留。 + stop_gap = max(1, int(round(STOP_SECONDS / interval))) # 可橋接的最大停頓取樣數 + i = 0 + while i < n: + if not stopped[i]: + j = i + while True: + while j + 1 < n and not stopped[j + 1]: + j += 1 + k = j + 1 # 數一數後面連續停了幾格 + while k < n and stopped[k]: + k += 1 + if k < n and (k - (j + 1)) < stop_gap: # 短暫停頓 → 橋接,移動繼續 + j = k + else: + break + if max(smoothed[i:j + 1]) < DEPART_MIN_SPEED: # 整段都沒加速到真速度 + for x in range(i, j + 1): + stopped[x] = True # → 龜速排隊,改判停止 + i = j + 1 + else: + i += 1 + # 1) 先抓出所有「原始連續停止」區段(不論長短) raw_runs: List[List[float]] = [] i = 0 @@ -1014,6 +1044,7 @@ _CONFIG_KEYS = { "min_confidence": "MIN_CONFIDENCE", "smooth_window": "SMOOTH_WINDOW", "depart_seconds": "DEPART_SECONDS", + "depart_min_speed": "DEPART_MIN_SPEED", "cut_before_stop": "CUT_BEFORE_STOP", "keep_after_stop": "KEEP_AFTER_STOP", "min_keep": "MIN_KEEP", diff --git a/config.json b/config.json index 6a17e20..aff6580 100644 --- a/config.json +++ b/config.json @@ -12,6 +12,7 @@ "min_confidence": 0.7, "smooth_window": 7, "depart_seconds": 8.0, + "depart_min_speed": 15, "cut_before_stop": 2.0, "keep_after_stop": 2.0, "min_keep": 0.8,