-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathheadless.py
More file actions
118 lines (104 loc) · 4.1 KB
/
Copy pathheadless.py
File metadata and controls
118 lines (104 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
"""CLI / headless mode for RaceVideoToLog."""
from __future__ import annotations
import argparse
import os as _os
import sys
import time
import traceback
from pathlib import Path
import config
import monitor as _monitor
from segment_flow import SegmentPipeline
def _monitor_settings(args: argparse.Namespace) -> tuple[bool, float]:
"""解析资源监测开关与间隔。
优先级:--no-monitor > RVTOL_MONITOR env > config.MONITOR_ENABLED;
间隔:--monitor-interval > RVTOL_MONITOR_INTERVAL env > config.MONITOR_INTERVAL_S。
"""
enabled = config.MONITOR_ENABLED
_env = _os.environ.get("RVTOL_MONITOR", "").strip().lower()
if _env in ("0", "off", "false", "no"):
enabled = False
elif _env in ("1", "on", "true", "yes"):
enabled = True
if getattr(args, "no_monitor", False):
enabled = False
interval = config.MONITOR_INTERVAL_S
if getattr(args, "monitor_interval", None):
interval = float(args.monitor_interval)
elif _os.environ.get("RVTOL_MONITOR_INTERVAL"):
try:
interval = float(_os.environ["RVTOL_MONITOR_INTERVAL"])
except ValueError:
pass
return enabled, interval
def run_headless(args: argparse.Namespace) -> None:
"""命令行无头模式:不启动 GUI,直接分析并输出 CSV。"""
from logging_setup import configure_logging
configure_logging(getattr(args, "log_level", "normal"))
if not args.roi:
print("错误: 命令行模式需要 --roi X1 Y1 X2 Y2")
sys.exit(1)
video_path = Path(args.video)
if not video_path.exists():
print(f"错误: 找不到文件 {video_path}")
sys.exit(1)
output_path = Path(args.output) if args.output else video_path.with_suffix(".csv")
region = (args.roi[0], args.roi[1], args.roi[2], args.roi[3])
print(f"视频: {video_path}")
print(f"识别范围: {region}")
print(f"最大速度: {args.max_speed} km/h, 最大加速度: {args.max_accel} m/s^2")
print(f"分段流水线: diff分段 → 段值OCR → 段级纠错")
t_total_start = time.perf_counter()
if getattr(args, 'progress', False):
def _progress(msg: str, pct: float) -> None:
print(f" [{pct:5.1f}%] {msg}")
else:
def _progress(msg: str, pct: float) -> None:
print(f"\r {msg}", end="", flush=True)
if pct >= 100.0:
print()
pipeline = SegmentPipeline(
video_path=str(video_path),
roi=region,
max_speed_kmh=args.max_speed,
max_accel_mps2=args.max_accel,
buffer_size=args.buffer,
decode_backend=args.decode_backend,
ocr_backend=args.ocr_backend,
fill_width=args.fill_width,
speed_format=args.format,
frame_start=args.frame_start,
frame_end=args.frame_end,
progress_cb=_progress,
force_aspect=getattr(args, 'force_aspect', 0.0),
fps=None,
# 代表帧保留 YUV(rep_crop_format="yuv";内部恒为单通道灰度链),
# 最终检查前转 RGB 预览
rep_crop_format="yuv",
)
t0 = time.perf_counter()
_mon_enabled, _mon_interval = _monitor_settings(args)
if _mon_enabled:
_monitor.start(interval_s=_mon_interval, with_gpu=config.MONITOR_GPU)
try:
pipeline.run(output_path)
except Exception as e:
print(f"\n错误: {e}")
if args.log_level == "debug":
traceback.print_exc()
sys.exit(1)
finally:
_stats = _monitor.stop()
t_total = time.perf_counter() - t0
print(f"总耗时: {t_total:.1f}s")
# 输出详细的阶段计时(标量键)
for stage, elapsed in pipeline.timing_flat().items():
print(f" {stage}: {elapsed:.1f}s")
if getattr(pipeline, "profile", None):
for group in sorted(pipeline.profile):
for key, secs in sorted(pipeline.profile[group].items()):
print(f" profile: {group}.{key}={secs:.4f}s")
if _stats:
_monitor.log_run(video_path.name, _stats, pipeline.timing_flat())
print("资源: " + _monitor.format_stats(_stats))
print(f"导出: {output_path}")