返回列表
相机标定 2026年8月8日 · 39 分钟

透视缩放系数标定工具(calib_tool)

公路灾害检测系统的离线标定辅助工具:交互式框选同一物理尺寸目标,拟合五种透视缩放系数曲线 scale(y),并支持目标测量与 ROI 多边形标注,结果直接导出为主系统可消费的 YAML

透视缩放系数标定工具(calib_tool.py)技术文档

1. 文档目标与背景

calib_tool.py 是公路灾害 AI 检测系统的离线标定辅助工具,通过交互式图形界面解决一个物理问题:球机画面存在透视效应,同一物理尺寸的目标(如一棵倒树、一块落石)在画面近处显得大、远处显得小,其像素边长随目标在画面中的纵向位置(中心点 y 坐标)变化。

系统对灾害目标按”归一化尺寸”分级(I~IV 级)时,必须先把任意距离处测得的像素尺寸折算到同一物理尺度。折算依赖一条曲线——透视缩放系数函数 scale(y)scale(y)(表示画面第 y 行处像素尺寸与近景基准的比例)。该曲线无法从理论上精确求得(取决于相机安装高度、俯仰角、焦距、预置点视角等),必须对每个相机、每个云台预置点实测标定

本工具即完成这件事:在 RTSP 实时流 / 本地视频 / 单张图片上,人工框选同一物理尺寸物体在不同远近位置的画面尺寸,自动拟合出 scale(y)scale(y) 的五种候选数学模型,实时评估拟合质量,并将结果导出为系统可直接消费的 YAML 配置(与 alarm_manager 的归一化分级模块完全对接)。同时,工具还内置了测量模式(用已标定曲线反推任意目标的归一化尺寸/物理尺寸/报警等级,辅助确定分级阈值)与 ROI 多边形绘制模式(为相机各预置点标注检测区域并写入 roi_config.yaml)。


2. 标定原理

2.1 归一化尺寸的定义

系统分级逻辑(alarm_manager._normalize_size)对任一检测框采用:

norm_size=max(w,h)scale(yc)\text{norm\_size} = \frac{\max(w, h)}{scale(y_c)}

其中 w,hw,h 为框宽高(像素),ycy_c 为框中心点纵坐标。若 scale(y)scale(y) 能准确刻画该处的透视比例,则同一物理尺寸的物体在任何位置算出的 norm_size 应恒等于同一常数——这就是”归一化”的含义,也是整个标定的可验证基准。

2.2 标定流程(数据采集)

  1. 从视频/流中选择一幅包含”已知同一物理尺寸物体”的画面(如放置路面上的标定石、一段护栏、车辆等,通常推荐倒树或标定石),暂停画面。
  2. 按住鼠标左键拖出一个恰好框住该物体的矩形(松手确认)。
  3. 换一个更远/更近的位置再框一次,如此采集多个样本点。每个标定点记录四元信息:
    • 框左上/右下坐标 (x1,y1,x2,y2)(x_1,y_1,x_2,y_2)
    • 中心纵坐标 yc=(y1+y2)/2y_c = (y_1+y_2)/2(决定所在行,即透视位置);
    • 目标像素边长 size=max(w,h)\text{size} = \max(w, h)(取最大边消除方向性差异)。
  4. 当样本点 ≥ 3 时自动进行曲线拟合,并在界面实时显示参数与误差;可切换公式对比,选择误差最小的模型导出。

2.3 目标函数与待拟合曲线

理想情况下,同一物体近/远两点满足:

size(y)=const×scale(y)\text{size}(y) = \text{const} \times scale(y)

即像素尺寸是 scale(y)scale(y) 的等比例采样。工具对以下五类数学模型分别求”使各样本归一化尺寸最一致”的参数:

公式数学形式拟合方法参数
linear(线性)s=ay+bs = a\,y + b一元最小二乘(polyfit 1 次)[a, b]
quadratic(二次)s=ay2+by+cs = a\,y^2 + b\,y + c一元最小二乘(polyfit 2 次)[a, b, c]
fractional_linear(分式线性)s=ay+bcy+1s = \dfrac{a\,y+b}{c\,y+1}将方程改写为 ay+bscy=sa\,y + b - s\,c\,y = s,对 (a,b,c)(a,b,c) 三元最小二乘;并对分母 cy+1c\,y+1 在样本范围内做非零数值保护[a, b, c]
robust_fractional(鲁棒倒数分式,推荐)s=k(yyv)1γ(yyv)s = \dfrac{k\,(y-y_v)}{1-\gamma\,(y-y_v)}网格搜索 + 倒数线性化最小二乘(见 2.4)[y_v, k, gamma]
piecewise_linear(分段线性)以样本点做折线插值表直接以 (y,s)(y,s) 样本建立分段表;区间内线性插值,区间外按首/末段斜率外推[[y0,s0], [y1,s1], …]

2.4 鲁棒倒数分式(robust_fractional)的拟合原理

该模型基于针孔相机成像推导,物理意义最贴近真实透视关系:

  • yvy_v地平线消失点(画面中路面灭点)的纵坐标,目标成像尺寸近似与其到消失点的图像距离 d=yyvd = y - y_v 成正比,并随距离进一步非线性收缩(分母项 1γd1-\gamma d 补偿”远处每行对应的实际距离增大”这一效应)。
  • 由于参数间非线性耦合,直接最小二乘易陷入局部解,工具改用全局网格搜索
    1. yvy_v 的合理区间内(画面底部 10% 之外向下延伸至画面顶部上方 10%,即约 0.10.6-0.1 \sim 0.6 倍图高,逐像素步进)遍历候选消失点;
    2. 对每个候选 yvy_v,把样本做倒数线性化变换 1s=a1d+b\frac{1}{s} = a\,\frac{1}{d} + b,退化为标准一元线性拟合求 (a,b)(a,b)
    3. 反推模型参数 k=1/ak = 1/aγ=b/a\gamma = -b/a
    4. 施加物理与数值约束筛选:要求 γ>0\gamma > 0(远端正收缩)、画面最底部 y=img_hy=img\_h 处分母 1γ(img_hyv)1-\gamma(img\_h-y_v) 保持安全正值(防除零发散);
    5. 用全部样本重算该候选的残差平方和,选取全局残差最小的一组 [y_v, k, gamma] 作为最优解。
  • 该算法鲁棒性最强,适合高位俯视球机,因此界面标记为 recommended;缺点是点集若分布不佳(如全部集中在近景,缺少远景采样)会无法解出有效参数,工具此时会明确提示”重新采集远/近点”。

2.5 求值的数值安全保护

无论哪种公式,求值器统一施加两类保护:

  • 分母保护:分式类公式分母过小(趋近 0)时按图像底部最大分母约束与极小值兜底;
  • 缩放下限:返回值下限 1e-3,杜绝除零/负缩放导致的归一化尺寸异常。

2.6 拟合质量评估(误差体系)

拟合完成后按如下方式评估:

  1. 用每个样本点的中心 ycy_c 代回 scale(y)scale(y),计算各点归一化尺寸 normi=sizei/scale(yi)norm_i = size_i / scale(y_i)
  2. 因为所有样本是”同一物理尺寸”,理想的 norminorm_i 应当全部相等 → 取平均值为参考基准 mean_norm
  3. 逐点相对误差 normimean/mean|norm_i - mean|/mean 统计出 平均误差 avg最大误差 max(百分比),并在界面列出每个点的 norm 值——若某点 norm 明显偏离均值,说明该点框选不准或选用了不同尺寸的物体,便于剔除重标。

导出 YAML 时同时写入 calib_points(点数)、avg_errormax_errorpoints_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;两者都不满足时提示”无标定可用”。
  • 功能:对画面中任意未知目标(不限于标定物)拖出橙色测量框,工具即刻用当前 scale(y)scale(y) 计算:
    • 归一化尺寸 norm = size / scale(center_y)
    • (可选)结合标定石物理尺寸 D0D_0(按键 3 可随时输入,单位米)换算物理尺寸 phys=norm×D0\text{phys} = norm \times D_0
    • (可选)结合 --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)或本地视频/图片路径
--outputcalib_result.yaml标定结果导出路径
--roi_configconfig/roi_config.yamlROI 配置文件路径(ROI 绘制模式写入目标)
--camera_id1默认相机编号(运行中按键 1 修改)
--preset_id1默认预置点编号(运行中按键 2 修改)
--display_scale0.5显示缩放(0,1] 区间,仅影响显示
--calibcalib_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.yamlpreset_alarm → camera_N → preset_id 即承载这些”各自标各的”结果。
  • ROI 配置消费端:ROI 绘制写入的 config/roi_config.yaml 由流水线在云台巡航切换预置点时热加载(目标中心点命中多边形过滤 + 滑坡路面接触判定),因此工具提示”下个巡航周期自动生效,无需重启”。

7. 典型使用流程

7.1 标定一个预置点的 scale(y)

  1. 相机对准某预置点后执行: python3 calib_tool.py --source "rtsp://…" --camera_id 1 --preset_id 2 --output preset2_calib.yaml
  2. 等待画面稳定,按空格暂停;
  3. 在画面近、中、远不同位置依次拖框框选同一个物理尺寸已知的目标(推荐在路面上放置标定石,或将已知高度的倒树/护栏作为参照),至少采集 4~7 个点(须覆盖画面近端与远端);
  4. 观察右侧面板每点 norm 是否一致,剔除/重标明显偏离的点;
  5. f 依次尝试五种公式,观察 avg/max 误差,选误差最小的(一般优先 robust_fractional);
  6. s 导出 YAML,将 formula/params 写入 alarm.yaml 对应相机+预置点(或合并进对应阈值文件);
  7. 切到下一预置点重复上述过程。

7.2 确定某类目标的等级阈值(测量模式)

  1. 运行带 --calib 已标定文件 --levels "…区间…" 的工具并进入测量模式(m);
  2. 框选一个已知物理尺寸(可用标定石 D0,按键 3 输入)的同类目标,读取其 norm/物理尺寸/等级;
  3. 换不同距离的目标反复测量,即可确定该类目标”多大 norm 对应哪一级”的合理分档。

7.3 绘制某预置点的 ROI

  1. --camera_id 1 --preset_id 3 运行并暂停到合适画面;
  2. r 进入 ROI 模式,沿检测区域边界左键逐点画多边形,Enter 闭合;
  3. 核对叠加的半透明旧区域,b 可撤回顶点,Enter 确认写入(自动备份 .bak);
  4. 如需绘制其它相机/预置点,按 1/2 改编号后再画。

8. 代码组织与可维护性

工具按职责拆分为低耦合的类,便于单元测试与扩展:

职责
VideoReader输入源抽象(RTSP/视频/图片)、帧缓存、断流重连、单帧后退
PointAnnotator鼠标回调、标定点与测量框的数据结构管理、各类框的绘制
ScaleFitter五种拟合算法 + 统一求值 + 误差计算(纯计算,不依赖界面,可单测)
RoiDrawerROI 顶点管理、鼠标交互、多边形渲染(独立于标定逻辑)
CalibApp主流程状态机、按键分发、信息面板/画面渲染、导出

GUI 按键处理采用”归一化键码 + 分优先级状态机”(编号输入态 → 激活输入 → ROI/测量模式切换 → 模式内按键 → 全局按键),保证不同后端与状态下的按键行为不冲突。


9. 注意事项

  • 样本要求:至少 3 点才能拟合;robust_fractional 强依赖样本在画面远近方向上的合理分布,全部集中在一侧会报”样本分布异常”,需补充远景/近景点。
  • 框选一致性:所有样本必须框选同一物理尺寸的目标,否则 norm 离散、误差虚高;测量时以目标最大边作为尺寸口径,与运行时检测一致。
  • 显示缩放不影响精度:任何标注均按原始分辨率换算回存。
  • 每个预置点单独标定:切勿跨预置点混用参数,否则透视补偿失真导致分级漂移。
  • 仅依赖少量通用库(opencv-python / numpy / pyyaml),可在开发机离线标定,也可直接对现场 RTSP 实时标定。