2026-09-24 14:38:42 +08:00
2026-07-23 18:00:15 +08:00
2026-09-24 14:38:42 +08:00
2026-07-29 16:25:16 +08:00
2026-09-15 11:32:36 +08:00
2026-09-10 17:06:56 +08:00
2026-07-23 18:00:15 +08:00
2026-09-15 09:53:00 +08:00
2026-09-15 11:32:36 +08:00
2026-09-15 11:32:36 +08:00
2026-09-24 14:38:42 +08:00
2026-09-15 11:32:36 +08:00
2026-09-15 09:53:00 +08:00

scan参数交互式配置向导

该工具用于在不同摄像头点位通过固定对话完成scan参数标定、配置替换、完整试扫和验证拼图, 适合批量部署RK3576和RK3588,并适用于smart-cam已支持的海康威视和天地伟业PTZ摄像头。 详细的底层命令和原理见手动配置README.md。

摄像头兼容性

标定工具不直接调用海康或天地伟业SDK,也不连接80/8000/3000等摄像头端口。 它只调用smart-cam在容器内提供的统一HTTP接口:

  • GET /api/v1/control/status:检查实际厂商、驱动状态和能力;
  • GET /api/v1/ptz:读取统一pan/tilt/zoom坐标;
  • POST /api/v1/ptz/absolute:绝对移动;
  • POST /api/v1/snapshot:抓取标定画面。

因此没有按型号写死的PTZ方向、视场角或zoom档位。程序会使用适配层实际回读的移动量, 通过实拍自动识别pan方向,并在zoom离散时向上选择最近的可达档位。pan或tilt某个方向遇到 机械/固件限位时,会换反方向探测。

install.sh会在不移动摄像头的前提下检查driver_ready、get_position和 move_absolute。只要当前型号已被当前smart-cam的对应厂商适配层正确支持, 本工具就无需增加型号分支。若驱动未就绪或型号不支持绝对PTZ,程序会在移动前明确拒绝标定, 不会盲目试转摄像头。

部分天地伟业型号的SDK不能像海康一样直接完成任意绝对坐标移动。smart-cam适配层会改用 “短方向动作 -> 回读实际位置 -> 继续逼近”,所以肉眼看起来会一小段一小段移动。 这是当前型号的控制方式,不是标定程序预先排了多个扫描点,也不能单凭这个现象判定电机故障。 标定时应等待程序自己完成到位回读,不要同时在Web端控制云台。

interactive.sh启动时会先执行docker exec smart-cam smart-camctl control pause, 同时停止扫图、巡航和自动追踪对云台的新控制。向导正常完成、发生错误或用户 按Ctrl+C退出时,Shell的EXIT trap都会执行smart-camctl control resume, 恢复巡航和自动追踪。

目录结构

scan-calibrator/
├── README.md                    # 交互式向导主文档
├── 手动配置README.md             # 完整手动流程和参数原理
├── install.sh                  # 首次部署时安装依赖并做完整环境自检
├── interactive.sh              # 交互式向导入口
├── interactive_calibrator.py
├── calibrate.sh                # 手动配置入口
├── scan_calibrator.py
├── history/                    # 每次交互向导的完整或中途标定记录(运行时生成)
├── src/measure_overlap.cpp
├── result/                     # 运行时生成的scan配置片段
└── scan-panorama/
    ├── stitch.sh
    ├── stitch_scan.py
    ├── README.md
    └── result/                 # 运行时生成的验证大图

启动

首次把本目录复制到一台RK3576或RK3588后,先执行一次安装与自检:

cd /home/zhangw/scan-calibrator
./install.sh
./interactive.sh

install.sh可重复运行,不会修改scan参数。它会在缺少时通过apt-get安装宿主机 python3和imagemagick,然后检查Docker、smart-cam容器、scan HTTP服务、数据目录写权限、 容器内C++/OpenCV编译环境以及拼图命令。非root账号安装缺失软件时需要具有sudo权限。

如果设备上曾出现“未找到ImageMagick identify”,就是宿主机缺少imagemagick; 运行install.sh会自动补齐。ImageMagick安装在RK3588宿主机,而不是smart-cam容器内, 因为验证拼图程序运行在宿主机。

验证拼图不会再把全部4K小图同时交给ImageMagick。程序会逐张缩图、逐行合并,最后只合并 已经缩小的行图;如果仍检测到缓存或可用内存不足,会自动缩小单格尺寸后重试两次。因此大型 扫描网格不需要现场修改ImageMagick策略,也不会靠放宽内存上限增加盒子OOM风险。

常用输入:

  • 1:确认、执行或选择野外部署;
  • 2:只在第一个问题中表示办公室测试;
  • 历史记录选择处输入1、2、3等序号:复用对应记录,输入0新建,输入q退出;
  • 左上角和右下角既可回复1读取摄像头,也可直接粘贴 pan=21720 (217.20°), tilt=1268 (12.68°), zoom=4580 (45.80×);
  • 除历史记录选择处外,3:结束对话并保留当前标定进度;
  • Ctrl+C:等同于退出。

每次启动都会建立一条独立历史记录。退出不会删除已记录的角点、已测得的单轴step、 已生成的配置、历史扫描目录,也不会回滚已经明确确认替换并重启的config.json。 临时标定截图仍会清理,避免长期占用设备磁盘。

完整对话示例

下面以办公室测试、28张小图为例。>后面的1或2是现场人员输入;PTZ、step、 文件名和扫描目录只是示例,实际值由当前摄像头返回。

您好!我们现在开始配置扫图参数!
标定进度会逐步保存;中途回复 3 或按 Ctrl+C 退出后,下次运行仍可选择本次记录继续。

① 当前是【野外部署阶段】(回复 1)还是【办公室测试阶段】(回复 2)?
> 2

在第②步之前发现以下历史标定记录(最新的排在前面):
1. 2026-09-10T10:20:30+08:00,安装方式=办公室正放,左上角=有,右下角=有,pan_step=有,tilt_step=无
2. 2026-09-09T16:10:00+08:00,安装方式=野外倒挂,左上角=有,右下角=无,pan_step=无,tilt_step=无
输入对应序号复用;回复 0 不复用并新建;回复 q 退出。
> 0

② 请在Web界面中设置左上角zoom,再手动把摄像头移到扫描区域的【左上角】。
摄像头到位后回复 1 读取当前位置;也可以直接输入pan、tilt、zoom;回复 3 随时退出。
> 1
已读取: pan=19120 (191.20°), tilt=990 (9.90°), zoom=810 (8.10×)

③ 请手动把摄像头移到扫描区域的【右下角】。
右下角可以使用不同zoom,程序会从两个角点zoom的平均值向上选择最近可达的最终扫描zoom。
摄像头到位后回复 1 读取当前位置;也可以直接输入pan、tilt、zoom;回复 3 随时退出。
> pan=13420 (134.20°), tilt=-340 (-3.40°), zoom=810 (8.10×)
已采用手动输入: pan=13420 (134.20°), tilt=-340 (-3.40°), zoom=810 (8.10×)

④ 这一步用于测量当前zoom下的水平/垂直视场。
请把摄像头移到扫描区域内部、距离较远且纹理分布在整幅画面的位置。
请避开纯天空、纯墙面、水面、玻璃、近距离物体和重复图案;
回复1后不要再操作Web云台,程序会自动移动、拍照并返回起点。
到位后回复 1;回复 3 随时退出。
> 1

正在计算,请不要操作摄像头或Web控制页面……
已读取: pan=16220 (162.20°), tilt=440 (4.40°), zoom=810 (8.10×)

正在标定 pan_step,摄像头会自动移动并回到起点……
  step=250: 重叠约 77.0%,有效特征=286,内点率=91.7%
  step=450: 重叠约 58.6%,有效特征=191,内点率=84.5%
  step=700: 重叠约 35.5%,有效特征=116,内点率=73.9%

正在标定 tilt_step,摄像头会自动移动并回到起点……
  step=120: 重叠约 81.3%,有效特征=302,内点率=92.0%
  step=220: 重叠约 65.8%,有效特征=215,内点率=86.7%
  step=350: 重叠约 45.6%,有效特征=143,内点率=78.1%

⑤ 本次得到的扫图参数:
{
  "pan_start": 13420,
  "pan_end": 19870,
  "pan_step": 1075,
  "tilt_start": -340,
  "tilt_end": 1511,
  "tilt_step": 617,
  "zoom": 810
}
安装方式:desktop
范围检查:视觉左→右pan=decreasing,指定弧段=57.00°
整步扩边:pan_step=1075,向终点外扩=750(7.50°)
整步扩边:tilt_step=617,向终点外扩=521(5.21°)
预计网格:7列 × 4行 = 28张

⑥ 是否替换 smart-cam 容器内的/smart-cam/config/config.json?
替换并重启回复 1;不替换并结束回复 3。
> 1
替换完成,smart-cam已重启。

⑦ 是否现在进行一次完整扫图测试?
开始测试回复 1;不测试并结束回复 3。
> 1
已启动测试扫描。

扫图日志:
已保存第 1/28 张图
已保存第 2/28 张图
……
已保存第 27/28 张图
已保存第 28/28 张图

扫描完成,共保存 28 张图。
保存目录:/smart-cam/data/scan/2026-07-23_16-53-51

⑧ 本次扫描已完成,是否立即进行拼图测试?
开始拼图回复 1;不拼图并结束回复 3。
> 1

拼图完成。
大图存储位置:/home/zhangw/scan-calibrator/scan-panorama/result/2026-07-23_16-53-51_desktop_scan_grid_panorama.jpg

配置向导已完成,对话结束。

每个问题背后执行了什么

① 选择部署环境

  • 回复1:使用hanging,表示球机在野外正常倒挂;
  • 回复2:使用desktop,表示办公室桌面正放且摄像头后台旋转了180度。

它决定验证拼图时的画面方向。摄像头的pan数值递增/递减方向不再由安装姿态写死, 而是在第④步根据实拍画面位移自动识别。生成配置仍等价于最后执行:

./calibrate.sh generate --mount hanging
# 或
./calibrate.sh generate --mount desktop

② 记录左上角

现场人员先在Web界面设置左上角zoom,并移动到扫描区域左上角。回复1后,向导通过 smart-cam的HTTP接口读取PTZ并记录,等价于:

./calibrate.sh ptz
./calibrate.sh mark top-left

记录的是当前画面中心的pan/tilt/zoom。

③ 记录右下角

移动到右下角;这里允许根据覆盖范围使用不同zoom。回复1后等价于:

./calibrate.sh ptz
./calibrate.sh mark bottom-right

向导会显示两个角点的zoom,并以算术平均值作为选择最终扫描zoom的下界。第四步开始测量前, 程序会自动把镜头切换到该平均zoom;即使摄像头当前已经显示为这个zoom,也会明确下发一次 绝对zoom命令并回读。若算术平均值不是摄像头可达档位,程序会在平均值上方查找最近的可达档位, 例如平均值4565只能落到4550或4580时采用4580。视场标定和最终生成配置都会使用 回读确认的同一个可达zoom,不会再把不可达平均值写入配置。

④ 自动计算pan_step和tilt_step

现场人员把镜头移到扫描区域内部、距离较远且纹理丰富的位置。 回复1后,向导会:

  1. 抓取基准图;
  2. 沿pan方向先从小角度探测;取得首个有效样本后立即反算当前zoom的视场, 并自适应补测约82%、72%、60%、48%、35%重叠附近的候选角度,每次抓图后回到起点;
  3. 用ORB特征、RANSAC和单轴画面位移求水平视场;
  4. 沿tilt方向重复测量;
  5. 每个方向统一筛选相互一致的视场样本;获得4个覆盖充分、离散度不超过8%的 可靠样本后提前停止,不再测试更大且通常没有公共画面的step;
  6. 两组结果只有在特征质量高且视场差不超过8%时才接受,否则要求至少三组一致结果;
  7. 水平方向按4.5%、垂直方向按2%目标重叠计算step;这是根据完整扫图接缝分别设置的轴向补偿;
  8. 默认使用ORB特征和RANSAC几何变换;当局部图案重复导致几何内点不足时,自动使用整幅图 相位相关复核纯单轴位移,相位响应不得低于0.20;
  9. 要求至少50个几何内点且内点率至少45%,否则拒绝结果;
  10. 根据配置中的图像宽高比,用可靠的tilt视场按普通透视公式反算pan视场;若与pan实测相差 不超过15%,取“直接pan结果”和“tilt推导结果”的几何平均值,避免任一模型单独产生偏差;
  11. 若pan实测与tilt透视预测相差超过15%,不强制套用比例,并明确提示镜头畸变或不同tilt行 水平覆盖不一致;这种摄像头使用单一pan_step无法保证所有行同时零重叠且无缺口;
  12. 根据多个水平样本的带符号位移,自动识别该型号摄像头从画面左到右时pan是递增还是递减;
  13. 每次标定会话只编译一次OpenCV重叠分析器,后续step直接复用;
  14. 标定开始前检查摄像头适配层已就绪且具备位置读取/绝对移动能力;
  15. 如果smart-cam因RTSP采集看门狗而短暂重启,向导会等待scan HTTP恢复, 然后重试当前PTZ或拍照操作,不会直接丢失整个第四步;
  16. 删除本次自动标定产生的临时截图。

这一步不能省略。两个角点只能确定扫描范围,无法确定当前摄像头型号和zoom下的一幅画面 覆盖多少角度。

不要把画面对准纯天空、纯墙、纯水面、玻璃、近距离物体或重复图案。水面场景应让岸线、 浮标等固定物体横向分布在画面中,不能只依赖不断变化的水纹。 测量过程中程序会锁定上述实际可达的扫图zoom;自动对焦不影响zoom。标定失败时可以只更换 第四步的位置重试,不需要重新记录左上角和右下角。pan或tilt任一方向已经成功时会立刻保存, 另一方向失败或退出后,下次可以只继续尚未完成的方向。

历史记录复用

进入第②步前,向导会读取history/session_*.json并按时间倒序编号,逐条显示是否已经包含:

  • 左上角位置;
  • 右下角位置;
  • pan_step;
  • tilt_step。

输入序号后,已有角点会直接跳过;只有一个角点时只补录另一个;只有一个轴的step时只补测另一个。 如果四项都齐全,向导会询问直接复用还是重新测量step。复用会建立一条新的本次记录,原历史文件 不会被覆盖。升级前已有的calibration.json也会自动导入历史记录一次。

⑤ 显示最终参数

向导按完整step向终点扩展扫描范围,保证范围只能比手动选择的区域稍大,不能少扫。 它会显示:

pan_start / pan_end / pan_step
tilt_start / tilt_end / tilt_step
zoom
预计行数、列数、图片总数和向外扩展角度

同时将片段保存到:

/home/zhangw/scan-calibrator/result/

⑥ 替换配置并重启

回复1后,向导会:

  1. 从容器读取/smart-cam/config/config.json;
  2. 只更新scan中的七个运动参数,保留定时时间、等待时间、容差和HTTP设置;
  3. 用python3 -m json.tool验证新JSON;
  4. 原子替换配置,不另外备份原配置;
  5. 若宿主机存在smart-cam.service,通过systemd重启,避免systemd与docker restart同时管理容器;否则执行docker restart smart-cam;
  6. 等待scan HTTP服务连续稳定15秒后再进入试扫。

回复3不会替换配置。

⑦ 立即完整试扫

回复1等价于:

docker exec smart-cam curl -fsS -X POST \
  http://127.0.0.1:18080/api/v1/scan/start

向导会在后台轮询扫描状态,但不会把HTTP请求日志显示到终端。终端只显示图片保存进度:

已保存第 1/28 张图
已保存第 2/28 张图
……

后台状态查询等价于:

docker exec smart-cam curl -fsS \
  http://127.0.0.1:18080/api/v1/scan/status

扫描完成或失败后自动停止日志跟随,并显示结果目录。

扫描过程中需要中断时,直接按Ctrl+C。向导会主动调用停止接口并结束本次扫描, 已经保存的小图和meta.json会保留。也可以在另一个终端执行:

docker exec smart-cam curl -fsS -X POST \
  http://127.0.0.1:18080/api/v1/scan/stop

⑧ 拼图测试

只有本次试扫成功完成后才会出现这个问题。回复1后,向导将本次扫描的结果目录和第①步 选择的安装方式传给:

/home/zhangw/scan-calibrator/scan-panorama/stitch.sh \
  <本次扫描目录> --mount <desktop或hanging> \
  --pan-direction <increasing或decreasing>

mount只决定上下行顺序;左右列顺序使用第④步实拍得到的pan方向。交互式向导会自动传入, 不需要现场人员额外选择。

拼图完成后,终端返回大图的绝对存储路径,然后结束对话。回复3则不拼图并结束。

大型网格采用分阶段低内存拼图。若终端提示缓存不足,程序会自行降低验证图尺寸并重新拼图, 部署人员不需要重新扫图或手工重复第⑧步;只有源图缺失、磁盘空间耗尽或图片损坏时才会停止并 给出明确错误。

拼图结果统一保存在:

/home/zhangw/scan-calibrator/scan-panorama/result/

应打开大图检查实际拼图是否存在超过5%的重叠或画面缺口。

批量部署注意事项

  • 每一个摄像头点位都要重新记录角点;
  • 摄像头型号或zoom变化时必须重新自动计算step;
  • 不同厂商和型号的球机可能有相反的pan数值方向;向导会实拍识别,不能用desktop/hanging 或“默认走短弧”代替;
  • 标定期间不要同时从Web界面控制PTZ;
  • 向导按轴设置目标重叠:水平4.5%、垂直2%;最终以完整试扫的接缝结果为准;
  • 自动标定会完整测试全部候选step,再从所有可靠结果中筛选一致样本;
  • 机械回差、镜头畸变和近景视差可能导致不同位置略有差异,最终必须完整试扫并拼图复核;
S
Description
该工具用于在不同摄像头点位通过固定对话完成scan参数标定、配置替换、完整试扫和验证拼图,适合批量部署RK3588和rk3576。
Readme
341 KiB
0 Stars 1 Watchers 0 Forks
Languages
Python 89.9%
Shell 6.6%
C++ 3.5%