新增 min_real_zeros(真紅燈需≥N個真實0) + keep_after_stop 改 0

- min_real_zeros(3): 一段停止要含至少 N 個『真實讀到的 GPS=0』才算紅燈剪掉,
  讀不到(??)不算 → 濾掉『整段都讀不到』的假停車(OCR 失敗區,如 02 的 09:48/20:06)
- keep_after_stop 2->0: 不留卡達緩衝,直接剪到停車結束點(偵測到開始動那一刻)
實測 02: 假停車濾掉剩 9 段紅燈;#3 剪到 03:20、#9 剪到 19:17(真正起步點)。

本次調整由 Claude Opus 4.8 (1M context) 協助處理。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-04 00:02:05 +08:00
parent b26c32d410
commit c4a3fdde97
3 changed files with 16 additions and 4 deletions
+2 -1
View File
@@ -89,7 +89,8 @@ python auto_remove_redlight.py 01.MOV 03.MOV 05.MOV
| `max_accel_kmh` | `25` | 物理合理加速上限(km/h 每秒):機車不可能一秒從 4 衝到 70,超過此加速度的讀數視為高信心誤讀丟棄(只擋暴增,煞車減速不受限)|
| `depart_seconds` | `8.0` | 起步門檻(秒):一段移動要持續達到(滿)此秒數、且其中沒有 ≥`stop_seconds` 的 GPS=0,才算「穩定起步」而保留;不足者(短暫蠕動/排隊龜速/誤讀)併入停止一起剪掉 |
| `cut_before_stop` | `2.0` | 進入紅燈端(速度到 0)移除起點再往前幾秒,連減速進站一起砍 |
| `keep_after_stop` | `2.0` | 綠燈起步端(速度從 0 開始跑)移除終點提早幾秒,多留卡達起步畫面 |
| `keep_after_stop` | `0.0` | 綠燈起步端(速度從 0 開始跑)移除終點提早幾秒`0` = 剪到停車結束點(偵測到開始動的那一刻),不留卡達緩衝 |
| `min_real_zeros` | `3` | 真紅燈門檻:一段停止裡至少要有幾個「真實讀到的 GPS=0」才算紅燈而剪掉。讀不到(`??`)不算數——避免整段都讀不到被誤當停車剪掉 |
| `min_keep` | `0.8` | 保留片段短於此秒數即丟棄 |
| `use_gpu` | `true` | 是否使用 GPU(無 CUDA 時自動退回 CPU |
| `reencode` | `false` | `false` = 無損快剪;`true` = 重新編碼,切點精準到幀但較慢 |
+12 -2
View File
@@ -106,14 +106,17 @@ MAX_ACCEL_KMH = 25 # 物理合理加速上限(km/h 每秒)。
DEPART_SECONDS = 8.0 # 起步門檻(秒): 一段移動要持續『達到(滿)』此秒數,且其中
# 沒有 ≥STOP_SECONDS 的 GPS=0,才算「穩定起步」而保留;
# 不足者(短暫蠕動/排隊龜速/誤讀)併入停止一起剪掉。
MIN_REAL_ZEROS = 3 # 真紅燈門檻: 一段停止裡至少要有幾個『真實讀到的 GPS=0』
# 才算紅燈而剪掉。讀不到(??)不算數 —— 避免「整段都讀不到」
# 被誤當成停車剪掉(可能只是 OCR 失敗,其實在動)。
SMOOTH_WINDOW = 0 # (已停用,保留相容;雜訊改由上述兩段邏輯處理)
# --- 剪輯 / 輸出參數 ----------------------------------------
# 紅燈移除段的頭尾「不對稱」微調:
CUT_BEFORE_STOP = 2.0 # 進入紅燈端(速度到 0 那邊): 移除起點再往前幾秒,
# 連減速進站那段也一起砍掉 (秒)
KEEP_AFTER_STOP = 2.0 # 綠燈起步端(速度從 0 開始跑): 移除終點提早幾秒,
# 多留幾秒「卡達起步」的畫面 (秒)
KEEP_AFTER_STOP = 0.0 # 綠燈起步端(速度從 0 開始跑): 移除終點提早幾秒
# 0 = 剪到停車結束點(偵測到開始動的那一刻),不留卡達緩衝
MIN_KEEP = 0.8 # 保留片段若短於此秒數就丟棄,避免產生超碎片段 (秒)
USE_GPU = True # EasyOCR 是否用 GPU。需 CUDA + GPU 版 PyTorch。
# 設 True 時若沒有 CUDA,EasyOCR 會自動退回 CPU(不會壞)
@@ -402,6 +405,12 @@ def find_keep_intervals(samples: List[Sample], duration: float, interval: float
run_dur = run_end - run_start
at_end = run_end >= duration - 1e-3 # 是否一路停到影片結尾
# 這段裡「真實讀到的 GPS=0」數量(?? 讀不到不算)。不足門檻 → 不確定真的停了,不剪。
real_zeros = sum(1 for s in samples
if run_start <= s.t < run_end and s.speed == 0)
if real_zeros < MIN_REAL_ZEROS:
continue
# 列為移除: 達到紅燈門檻,或停到影片結尾(結尾停車一律砍掉)
if run_dur >= STOP_SECONDS or at_end:
# 進入紅燈端往前多砍 CUT_BEFORE_STOP 秒(連減速進站一起砍)。
@@ -1043,6 +1052,7 @@ _CONFIG_KEYS = {
"min_confidence": "MIN_CONFIDENCE",
"max_accel_kmh": "MAX_ACCEL_KMH",
"depart_seconds": "DEPART_SECONDS",
"min_real_zeros": "MIN_REAL_ZEROS",
"cut_before_stop": "CUT_BEFORE_STOP",
"keep_after_stop": "KEEP_AFTER_STOP",
"min_keep": "MIN_KEEP",
+2 -1
View File
@@ -12,8 +12,9 @@
"min_confidence": 0.5,
"max_accel_kmh": 25,
"depart_seconds": 8.0,
"min_real_zeros": 3,
"cut_before_stop": 2.0,
"keep_after_stop": 2.0,
"keep_after_stop": 0.0,
"min_keep": 0.8,
"use_gpu": true,
"reencode": false,