透视缩放系数标定工具(calib_tool)
公路灾害检测系统的离线标定辅助工具:交互式框选同一物理尺寸目标,拟合五种透视缩放系数曲线 scale(y),并支持目标测量与 ROI 多边形标注,结果直接导出为主系统可消费的 YAML
透视缩放系数标定工具(calib_tool.py)技术文档
1. 文档目标与背景
calib_tool.py 是公路灾害 AI 检测系统的离线标定辅助工具,通过交互式图形界面解决一个物理问题:球机画面存在透视效应,同一物理尺寸的目标(如一棵倒树、一块落石)在画面近处显得大、远处显得小,其像素边长随目标在画面中的纵向位置(中心点 y 坐标)变化。
系统对灾害目标按”归一化尺寸”分级(I~IV 级)时,必须先把任意距离处测得的像素尺寸折算到同一物理尺度。折算依赖一条曲线——透视缩放系数函数 (表示画面第 y 行处像素尺寸与近景基准的比例)。该曲线无法从理论上精确求得(取决于相机安装高度、俯仰角、焦距、预置点视角等),必须对每个相机、每个云台预置点实测标定。
本工具即完成这件事:在 RTSP 实时流 / 本地视频 / 单张图片上,人工框选同一物理尺寸物体在不同远近位置的画面尺寸,自动拟合出 的五种候选数学模型,实时评估拟合质量,并将结果导出为系统可直接消费的 YAML 配置(与 alarm_manager 的归一化分级模块完全对接)。同时,工具还内置了测量模式(用已标定曲线反推任意目标的归一化尺寸/物理尺寸/报警等级,辅助确定分级阈值)与 ROI 多边形绘制模式(为相机各预置点标注检测区域并写入 roi_config.yaml)。
2. 标定原理
2.1 归一化尺寸的定义
系统分级逻辑(alarm_manager._normalize_size)对任一检测框采用:
其中 为框宽高(像素), 为框中心点纵坐标。若 能准确刻画该处的透视比例,则同一物理尺寸的物体在任何位置算出的 norm_size 应恒等于同一常数——这就是”归一化”的含义,也是整个标定的可验证基准。
2.2 标定流程(数据采集)
- 从视频/流中选择一幅包含”已知同一物理尺寸物体”的画面(如放置路面上的标定石、一段护栏、车辆等,通常推荐倒树或标定石),暂停画面。
- 按住鼠标左键拖出一个恰好框住该物体的矩形(松手确认)。
- 换一个更远/更近的位置再框一次,如此采集多个样本点。每个标定点记录四元信息:
- 框左上/右下坐标 ;
- 中心纵坐标 (决定所在行,即透视位置);
- 目标像素边长 (取最大边消除方向性差异)。
- 当样本点 ≥ 3 时自动进行曲线拟合,并在界面实时显示参数与误差;可切换公式对比,选择误差最小的模型导出。
2.3 目标函数与待拟合曲线
理想情况下,同一物体近/远两点满足:
即像素尺寸是 的等比例采样。工具对以下五类数学模型分别求”使各样本归一化尺寸最一致”的参数:
| 公式 | 数学形式 | 拟合方法 | 参数 |
|---|---|---|---|
| linear(线性) | 一元最小二乘(polyfit 1 次) | [a, b] | |
| quadratic(二次) | 一元最小二乘(polyfit 2 次) | [a, b, c] | |
| fractional_linear(分式线性) | 将方程改写为 ,对 三元最小二乘;并对分母 在样本范围内做非零数值保护 | [a, b, c] | |
| robust_fractional(鲁棒倒数分式,推荐) | 网格搜索 + 倒数线性化最小二乘(见 2.4) | [y_v, k, gamma] | |
| piecewise_linear(分段线性) | 以样本点做折线插值表 | 直接以 样本建立分段表;区间内线性插值,区间外按首/末段斜率外推 | [[y0,s0], [y1,s1], …] |
2.4 鲁棒倒数分式(robust_fractional)的拟合原理
该模型基于针孔相机成像推导,物理意义最贴近真实透视关系:
- 为地平线消失点(画面中路面灭点)的纵坐标,目标成像尺寸近似与其到消失点的图像距离 成正比,并随距离进一步非线性收缩(分母项 补偿”远处每行对应的实际距离增大”这一效应)。
- 由于参数间非线性耦合,直接最小二乘易陷入局部解,工具改用全局网格搜索:
- 在 的合理区间内(画面底部 10% 之外向下延伸至画面顶部上方 10%,即约 倍图高,逐像素步进)遍历候选消失点;
- 对每个候选 ,把样本做倒数线性化变换 ,退化为标准一元线性拟合求 ;
- 反推模型参数 、;
- 施加物理与数值约束筛选:要求 (远端正收缩)、画面最底部 处分母 保持安全正值(防除零发散);
- 用全部样本重算该候选的残差平方和,选取全局残差最小的一组
[y_v, k, gamma]作为最优解。
- 该算法鲁棒性最强,适合高位俯视球机,因此界面标记为 recommended;缺点是点集若分布不佳(如全部集中在近景,缺少远景采样)会无法解出有效参数,工具此时会明确提示”重新采集远/近点”。
2.5 求值的数值安全保护
无论哪种公式,求值器统一施加两类保护:
- 分母保护:分式类公式分母过小(趋近 0)时按图像底部最大分母约束与极小值兜底;
- 缩放下限:返回值下限 1e-3,杜绝除零/负缩放导致的归一化尺寸异常。
2.6 拟合质量评估(误差体系)
拟合完成后按如下方式评估:
- 用每个样本点的中心 代回 ,计算各点归一化尺寸 ;
- 因为所有样本是”同一物理尺寸”,理想的 应当全部相等 → 取平均值为参考基准
mean_norm; - 逐点相对误差 统计出 平均误差 avg 与 最大误差 max(百分比),并在界面列出每个点的 norm 值——若某点 norm 明显偏离均值,说明该点框选不准或选用了不同尺寸的物体,便于剔除重标。
导出 YAML 时同时写入 calib_points(点数)、avg_error、max_error、points_detail(逐点明细),使标定质量可追溯、可复核。
3. 工具功能
工具在单个窗口内集成了三大交互模式:透视标定(主模式)、测量模式、ROI 多边形绘制模式,另有视频控制与配置编号编辑等辅助功能。
3.1 主模式:透视标定
- 多源输入:支持 RTSP 实时流(强制 TCP 传输、解码缓冲调为 1 降低延迟、断流自动重连并提示)、本地视频、单张静态图片;图片源进入即自动暂停。
- 交互标注:暂停状态下按住鼠标左键拖拽矩形框,松手完成一个标定点;拖拽过程实时显示框坐标/尺寸/中心 y。已确认点以绿色框 + 编号显示,拖拽中的点以黄色显示。
- 即时拟合与刷新:标注点 ≥ 3 个后每次增删立即重拟合,右侧面板实时显示当前公式、参数、平均/最大误差、参考归一化尺寸以及逐点 norm 明细(异常点一目了然)。
- 五公式切换对比:按
f循环切换 linear → quadratic → fractional_linear → robust_fractional → piecewise_linear,切换即重拟合,可快速挑选误差最小的模型。 - 标定点管理:按
d删除最后一个点、c清空全部点(均自动重拟合)。 - 导出 YAML:按
s将当前公式与参数导出(见第 5 节格式),导出内容携带完整标定质量信息。 - 单帧精确定位:暂停后可用方向键对本地视频单帧前进/后退,便于在运动场景中精确截取目标所在帧。
- 原始精度保证:显示窗口按
display_scale(默认 0.5,2560×1440 缩为 1280×720)缩放显示,但所有标注坐标均按原始分辨率换算存储,缩放只影响观感不影响精度。
3.2 测量模式(确定分级阈值)
- 前提:已在本会话完成 ≥3 点拟合,或通过
--calib载入历史标定 YAML;两者都不满足时提示”无标定可用”。 - 功能:对画面中任意未知目标(不限于标定物)拖出橙色测量框,工具即刻用当前 计算:
- 归一化尺寸
norm = size / scale(center_y); - (可选)结合标定石物理尺寸 (按键
3可随时输入,单位米)换算物理尺寸 ; - (可选)结合
--levels提供的区间档位显示其所属报警等级。
- 归一化尺寸
- 用途:在标定完成后,用已知物理尺寸的真实目标(倒树、坍塌范围等)反向测量其 norm 落在哪个档位,从而为各灾害类别的”尺寸→等级”阈值确定提供一手数据;按
x可将全部测量结果打印到控制台,作为填表依据。 - 测量框同样支持
d删除、c清空,结果同步绘制在画面与面板中。
3.3 ROI 多边形绘制模式(标检测区域)
- 按
r进入/退出,进入时自动暂停视频并清除残留输入状态。 - 顶点交互:鼠标左键逐点添加多边形顶点(原始分辨率坐标,画面实时预览连线与闭合填充);
b删除上一个顶点;最多 20 个顶点;Enter 闭合多边形(≥3 顶点)进入确认态。 - 确认态:Enter 确认写入配置;
z/ESC 返回选点编辑继续修改;ESC(绘制态)放弃本次绘制。 - 相机/预置点归属:按键
1/2激活相机编号/预置点编号的数字输入框(0-9 输入、Enter 确认、ESC 取消),绘制结果写入对应 “相机 N + 预置点 M” 条目。 - 参考叠加:进入模式时自动读取该相机+预置点已存在的 ROI,以半透明多边形叠加显示,便于在旧区域基础上修正。
- 增量写入:保存时仅更新
roi_config.yaml中当前camera_N → preset_id的单条记录,其余相机/预置点配置保持原样;文件格式(紧凑[[x,y],…]多边形)与手写风格 100% 一致;写入前自动备份.bak。主系统在巡航切到该预置点时会自动加载生效,无需重启。
3.4 界面呈现
- 画面区域 + 右侧 420px 实时信息面板:输入源、分辨率、播放状态、当前公式(含顺序指示)、标定点数、拟合参数/误差/每点明细、测量框列表、ROI 状态与当前相机/预置点、各类按键提示,按模式动态切换内容。
- 画面底部叠加操作提示消息(3 秒自动消隐),顶部叠加状态提示条。
- 兼容 Win32 / GTK / Qt 多种 GUI 后端的按键差异(Enter、ESC、方向键、普通键统一归一化),保证在不同图形环境(含 SSH 转发)下行为一致。
3.5 视频控制与健壮性
- 空格播放/暂停;
q/ESC 退出;RTSP 断流自动重连(仅提示一次,避免刷屏);本地视频播到结尾自动暂停等待标注;窗口被关闭时自动退出并释放资源。
4. 命令行参数
| 参数 | 默认值 | 说明 |
|---|---|---|
--source(必填) | — | 输入源:RTSP 地址(rtsp://…,自动 TCP)或本地视频/图片路径 |
--output | calib_result.yaml | 标定结果导出路径 |
--roi_config | config/roi_config.yaml | ROI 配置文件路径(ROI 绘制模式写入目标) |
--camera_id | 1 | 默认相机编号(运行中按键 1 修改) |
--preset_id | 1 | 默认预置点编号(运行中按键 2 修改) |
--display_scale | 0.5 | 显示缩放(0,1] 区间,仅影响显示 |
--calib | calib_result.yaml | 测量模式载入的既有标定 YAML |
--stone_size | 无 | 标定石物理尺寸(米),测量模式换算物理尺寸(运行中按键 3 修改) |
--levels | 无 | 报警等级区间:"lo,hi,等级;lo,hi,等级;…"(如 "0,0.203,L4;0.203,0.609,L3;…"),用于测量框等级提示 |
5. 导出文件格式
导出 YAML 顶层为 perspective_calib:
perspective_calib:
image_height: 1440 # 标定所用图像高度(求值/搜索算法依赖)
formula: quadratic # 五选一的公式标识
params: [a, b, c] # 对应公式参数(piecewise 为 [[y,s],…])
calib_points: 7 # 标定点数
avg_error: 0.77 # 平均相对误差 %
max_error: 1.82 # 最大相对误差 %
points_detail: # 逐点明细(含各点 norm,复核用)
- {id, center_y, size, norm_size}
该结构与系统 config/alarm.yaml(及全局 config.yaml)中 disaster_levels.perspective_calib 的格式完全一致,导出后可直接合并/复制进预置点分级配置。
6. 与主检测系统的集成关系
- 归一化分级消费端:
alarm_manager的_eval_perspective_scale实现了与工具ScaleFitter完全同构的五种公式求值(含分母/下限保护),标定时选定哪种公式,运行时就按同公式求scale(center_y);配置校验失败(公式名/参数非法)会回退旧经验公式(scale_offset/scale_multiplier)并输出告警日志,防止静默误判。 - 语义一致性:测量模式的
norm与运行时检测框的norm_size采用完全相同的算法,因此工具中标定出的--levels阈值可直接作为alarm.yaml中该类目标的尺寸分级区间。 - 逐预置点标定:由于每个预置点视角不同,要求每个预置点单独标定,工具通过
--camera_id/--preset_id(或运行中1/2键)标记归属;alarm.yaml中preset_alarm → camera_N → preset_id即承载这些”各自标各的”结果。 - ROI 配置消费端:ROI 绘制写入的
config/roi_config.yaml由流水线在云台巡航切换预置点时热加载(目标中心点命中多边形过滤 + 滑坡路面接触判定),因此工具提示”下个巡航周期自动生效,无需重启”。
7. 典型使用流程
7.1 标定一个预置点的 scale(y)
- 相机对准某预置点后执行:
python3 calib_tool.py --source "rtsp://…" --camera_id 1 --preset_id 2 --output preset2_calib.yaml - 等待画面稳定,按空格暂停;
- 在画面近、中、远不同位置依次拖框框选同一个物理尺寸已知的目标(推荐在路面上放置标定石,或将已知高度的倒树/护栏作为参照),至少采集 4~7 个点(须覆盖画面近端与远端);
- 观察右侧面板每点 norm 是否一致,剔除/重标明显偏离的点;
- 按
f依次尝试五种公式,观察 avg/max 误差,选误差最小的(一般优先 robust_fractional); - 按
s导出 YAML,将formula/params写入alarm.yaml对应相机+预置点(或合并进对应阈值文件); - 切到下一预置点重复上述过程。
7.2 确定某类目标的等级阈值(测量模式)
- 运行带
--calib 已标定文件 --levels "…区间…"的工具并进入测量模式(m); - 框选一个已知物理尺寸(可用标定石
D0,按键3输入)的同类目标,读取其norm/物理尺寸/等级; - 换不同距离的目标反复测量,即可确定该类目标”多大 norm 对应哪一级”的合理分档。
7.3 绘制某预置点的 ROI
--camera_id 1 --preset_id 3运行并暂停到合适画面;- 按
r进入 ROI 模式,沿检测区域边界左键逐点画多边形,Enter 闭合; - 核对叠加的半透明旧区域,
b可撤回顶点,Enter 确认写入(自动备份.bak); - 如需绘制其它相机/预置点,按
1/2改编号后再画。
8. 代码组织与可维护性
工具按职责拆分为低耦合的类,便于单元测试与扩展:
| 类 | 职责 |
|---|---|
VideoReader | 输入源抽象(RTSP/视频/图片)、帧缓存、断流重连、单帧后退 |
PointAnnotator | 鼠标回调、标定点与测量框的数据结构管理、各类框的绘制 |
ScaleFitter | 五种拟合算法 + 统一求值 + 误差计算(纯计算,不依赖界面,可单测) |
RoiDrawer | ROI 顶点管理、鼠标交互、多边形渲染(独立于标定逻辑) |
CalibApp | 主流程状态机、按键分发、信息面板/画面渲染、导出 |
GUI 按键处理采用”归一化键码 + 分优先级状态机”(编号输入态 → 激活输入 → ROI/测量模式切换 → 模式内按键 → 全局按键),保证不同后端与状态下的按键行为不冲突。
9. 注意事项
- 样本要求:至少 3 点才能拟合;robust_fractional 强依赖样本在画面远近方向上的合理分布,全部集中在一侧会报”样本分布异常”,需补充远景/近景点。
- 框选一致性:所有样本必须框选同一物理尺寸的目标,否则 norm 离散、误差虚高;测量时以目标最大边作为尺寸口径,与运行时检测一致。
- 显示缩放不影响精度:任何标注均按原始分辨率换算回存。
- 每个预置点单独标定:切勿跨预置点混用参数,否则透视补偿失真导致分级漂移。
- 仅依赖少量通用库(opencv-python / numpy / pyyaml),可在开发机离线标定,也可直接对现场 RTSP 实时标定。