专栏算法工具链人在途中:一文讲清图像处理中常用坐标系及使用

人在途中:一文讲清图像处理中常用坐标系及使用

Huanghui2026-03-02
53
0

1. 为什么必须理解坐标系

在视觉系统里,绝大多数 Bug 都不是模型本身的问题,而是“数据在不同空间里被误读”。

你看到的是一辆车在世界中的真实位置,但模型吃进去的是 tensor 的某个索引;中间要经过 world -> ego -> sensor -> camera -> image -> pixel -> tensor 多层映射。任何一层语义混淆,都会导致:
  • 检测框漂移、跟踪抖动、3D 框姿态错误

  • 多传感器融合失败(camera/lidar 时间或坐标不一致)

  • 部署后精度骤降(resize/quantize 后未修正坐标)

  • 调试困难(日志里都是 x,y,但不知道是米、像素还是索引)
坐标系的本质价值:让“同一个对象”在不同表示空间中保持可追踪的一致语义

2. 常用坐标系总览(World → Sensor → Image → Pixel → Tensor)

典型链路:

每个空间回答的问题不同:

  • world/global:物体在真实场景中在哪里?
  • ego:相对自车在哪里?
  • sensor/camera/lidar:相对某传感器在哪里?
  • image plane:3D 点投影到成像平面的几何位置是什么?
  • pixel:在图像像素网格中落在哪个像素?
  • tensor:在网络输入张量中对应哪个索引位置?

关键词区分(代码里最常见):

  • global:全局地图/惯性参考系,通常长期稳定
  • world:与 global 常近义,但也可能是局部重定位后的“世界系”
  • ego:自车坐标系(车体中心或后轴中心)
  • sensor:传感器本体系
  • camera:相机坐标系(通常 z 朝前)
  • image:理想成像平面连续坐标
  • pixel:离散像素坐标(u,v)
  • tensor:神经网络输入/特征图索引(h,w 或 y,x)

3. 世界坐标系(World / Global)

定义

描述物体在物理世界中的统一参考系。可选地图坐标、ENU、UTM 或任务自定义全局系。

坐标表示方式

  • 点:Pw = [Xw, Yw, Zw]^T
  • 位姿:Twb = [Rwb | twb](world 到 body/ego)

单位

  • 位置通常是米(m)
  • 姿态常用弧度(rad)或四元数

表达的语义

“这个目标在真实世界绝对/半绝对位置在哪里”。

存在的必要性

  • 多帧时序融合必须有稳定锚点

  • 地图关联、轨迹评估、重定位都依赖 global/world 一致性

典型应用场景

  • 自动驾驶定位与地图对齐

  • 多相机/多雷达跨时间融合

  • SLAM 后端优化

工程代码常见命名

  • p_world, T_world_ego, pose_global
  • global_xyz, world_frame, map_frame

4. 传感器坐标系(Sensor / Camera / LiDAR)

定义

每个传感器自身的本地坐标系,原点在传感器安装位置。

坐标表示方式

  • 点:Ps = [Xs, Ys, Zs]^T
  • 外参:Tws, Tsc, Tcl 等(注意方向)

单位

  • 米(m)

表达的语义

“目标相对这个传感器的空间位置”。

存在的必要性

  • 传感器观测是“本地”产生的,不先转到 sensor 系就无法做正确几何计算

  • 多传感器融合本质是外参驱动的坐标统一

典型应用场景

  • 相机投影、LiDAR 点云处理

  • Radar-Camera/LiDAR-Camera 对齐

  • 自车运动补偿(ego-motion compensation)

工程代码常见命名

  • p_cam, p_lidar, T_ego_cam, extrinsic, Rt
  • cam0_frame, lidar_frame, sensor2ego

补充:

  • 自动驾驶中 ego 与 sensor 都关键;视频纯视觉中常忽略 ego,但做稳像/SLAM 就必须引入。

5. 图像平面坐标系(Image Plane)

定义

3D 点通过针孔模型投影到理想成像平面的连续坐标(非离散像素)。

坐标表示方式

设相机系点为 Pc = [Xc, Yc, Zc]^T,Zc > 0:

齐次形式:

其中 [x,y] 属于归一化成像平面。

单位

  • 无量纲比例值(可理解为焦距归一化后的坐标)

表达的语义

“物体方向/视线在成像几何中的连续位置”。

存在的必要性

  • 将透视几何与像素采样解耦

  • 便于畸变校正、几何推导与标定

典型应用场景

  • 相机标定与重投影误差计算

  • 双目/多目三角化

  • PnP/SLAM 前端

工程代码常见命名

  • x_norm, y_norm, bearing, normalized_plane
  • undist_pt, cv::undistortPoints 输出常在该空间

6. 像素坐标系(Pixel)

定义

图像离散网格中的坐标系,通常左上角为原点,向右 u+,向下 v+。

坐标表示方式

  • 连续像素坐标:(u, v)(float)
  • 离散索引:(col,row) 或 (x,y)(int)

单位

  • 像素(px)

表达的语义

“这个点/框在当前图像数组里的位置”。

存在的必要性

  • 图像处理算子(resize/crop/pad/warp)全部发生在像素空间

  • 标注、检测框、关键点结果都先落在像素空间

典型应用场景

  • 检测框后处理(NMS/解码)

  • 图像增强

  • 可视化绘制

工程代码常见命名

  • u,v, x,y, cx,cy, bbox_xyxy, bbox_xywh
  • img_w,img_h, principal_point

工程提醒:

  • xyxy 与 xywh 必须显式标注,禁止“默认理解”。
  • 像素中心是 0.5 偏移还是整数点,必须统一。

7. 张量索引坐标系(Tensor Index)

定义

神经网络输入或中间特征图在内存中的离散索引空间。

坐标表示方式

  • 常见布局:NCHW 或 NHWC
  • 空间索引:(h,w),通道:c
  • 多尺度特征:P3/P4/P5 上的不同步长索引

单位

  • 索引(index),不是像素,不是米

表达的语义

“数据在 tensor 网格上的位置与通道语义”。

存在的必要性

  • 模型推理与部署只认识 tensor,不认识世界坐标

  • 后处理要把 tensor 输出映射回 pixel/image/world

典型应用场景

  • anchor/grid 解码

  • heatmap 峰值定位

  • 多任务头输出解析

工程代码常见命名

  • feat_h, feat_w, stride

  • grid_x, grid_y, idx, anchor_idx
  • input_tensor, output_blob

8. 不同坐标系之间的转换关系

8.1 标准链路与公式

  1. world -> sensor(camera)

或齐次:

  1. sensor(camera) -> image plane

  1. image plane -> pixel

  1. pixel -> tensor(以 resize+pad 为例)

再根据步长映射到特征图:

8.2 转换为何必须做

  • 算法目标空间和数据所在空间不同
    例如:跟踪在 world 评估,但检测输出在 tensor。
  • 多模块接口空间不同
    例如:ISP 输出 pixel,感知融合需要 ego/world。
  • 不同硬件链路对输入格式有约束
    例如:NPU 只接受固定尺寸 tensor。

8.3 转换需要的数据

  • 外参:R, t 或 T_ab
  • 内参:K = [[fx,0,cx],[0,fy,cy],[0,0,1]]
  • 畸变参数:k1,k2,p1,p2,...
  • 图像预处理参数:resize scale, crop roi, padding, flip
  • 网络参数:stride, anchor, grid definition

8.4 转换前后数据形式

  • world/sensor: float32/float64,3D 点或位姿
  • image/pixel: float 连续坐标 + int 像素索引
  • tensor: int 索引 + quantized/int8 数值张量

9. 为什么必须做坐标转换

从工程角度,转换不是“数学洁癖”,是系统协同的必要条件:

  • 时空统一:跨帧、跨传感器需要同一语义空间

  • 精度可控:每一步变换都能度量误差来源

  • 接口可维护:模块边界清晰,易于替换和部署

  • 问题可定位:知道错误发生在几何、采样还是量化环节

不同场景的核心坐标关注点:

  • 视频算法:pixel <-> tensor 最关键(预处理/后处理一致性)
  • SLAM:camera/sensor <-> world 最关键(位姿与重投影)
  • 自动驾驶:global/world/ego/sensor 全链路都关键(融合与规划)
  • 部署推理:pixel -> tensor -> pixel 与量化参数最关键

10. 量化与坐标空间的关系

量化通常不直接改变“坐标值定义”,但会改变与坐标相关的数值精度、解码精度和稳定性。

10.1 INT8 量化基础

常见线性量化:

反量化:

其中 r 是实数,q 是 INT8/UINT8。

10.2 对空间精度的影响

  • 框回归输出量化后,最小可分辨位移增大,导致框抖动

  • 深度/距离回归量化后,远距离误差放大

  • 关键点 heatmap 峰值受量化噪声影响,亚像素定位变差

10.3 fixed-point / Q 格式

定点表示:Qm.n(整数位 m,小数位 n)。
  • 实值到定点:x_fixed = round(x * 2^n)
  • 定点回实值:x = x_fixed / 2^n

工程含义:

  • n 越大,分辨率越高,但动态范围越小
  • 坐标变换链路里多次乘加容易溢出或截断误差累积

建议:

  • 几何主链路(投影/反投影)尽量保持 FP32

  • 仅在模型内部算子或末端后处理做定点化

  • 对关键坐标量单独做误差预算(px 级、m 级)


11. 工程常见错误与踩坑总结

  1. 外参方向写反

T_cam_ego 与 T_ego_cam 混用,投影完全错误。
  1. 右手系/左手系混淆

尤其在图形引擎、SLAM、自动驾驶模块拼接时。

  1. xy 与 row/col 混淆
x=col,y=row;在 numpy 中访问是 [row, col]。
  1. resize 后忘记同步标注/内参

只缩放图像,不缩放 bbox/keypoint/K。
  1. letterbox padding 未回退

后处理直接用网络输出还原原图,位置整体偏移。

  1. crop ROI 坐标基准错误

ROI 内坐标当作全图坐标使用,框错位。

  1. 畸变处理顺序错误

未去畸变就直接几何计算,重投影误差异常。

  1. 时间戳对齐忽略

坐标正确但时刻不一致,融合后仍漂移。

  1. 量化参数漏传

部署端后处理没使用训练导出的 scale/zero_point。
  1. 单位不统一

上游米、下游毫米;角度弧度/度混用。


12. 完整工程示例串讲(world → sensor → image → pixel → tensor)

假设目标点在世界坐标为 Pw=[10, 2, 0]^T (m),流程如下:
  1. world -> camera

  • 输入:Pw,Tcw=(Rcw, tcw)
  • 输出:Pc=[Xc,Yc,Zc]^T (m)
  1. camera -> image plane

  • 输入:Pc
  • 输出:(x,y)=(Xc/Zc, Yc/Zc)(无量纲)
  1. image plane -> pixel

  • 输入:(x,y),相机内参 K(fx,fy,cx,cy)
  • 输出:(u,v)(像素坐标,float)
  1. pixel -> preprocessed pixel(resize + crop + padding)
  • 输入:原图 (u,v),预处理参数
  • 输出:网络输入图坐标 (u',v')
  1. preprocessed pixel -> tensor index

  • 输入:(u',v'),stride
  • 输出:(grid_x, grid_y) 或 heatmap 索引 (h,w)
  1. tensor output -> pixel/world(反向恢复)
  • 输入:网络输出、量化参数、预处理逆变换参数、K/R/t
  • 输出:原图框/关键点,或 3D/world 结果

关键检查点(每一步都应记录):

  • 坐标系名(字符串标签)

  • 单位(m/px/index)

  • 数据类型(fp32/int8/int)

  • 时间戳与相机ID


13. 阅读代码快速判断坐标空间的方法

实战中最快的方法不是看注释,而是看“变量 + 变换 + 单位 + 调用点”。

13.1 四步法

  1. 看变量命名后缀

  • _world/_global/_map:世界系
  • _ego/_vehicle:自车系
  • _cam/_lidar/_sensor:传感器系
  • _uv/_xy:像素或图像平面(需结合类型判断)
  • _grid/_feat/_idx:tensor 索引
  1. 看是否出现 K/R/t/T
  • 出现 K:大概率 camera/image/pixel 转换
  • 出现 R,t:大概率 world/ego/sensor 变换
  • 出现 stride/anchor:大概率 pixel/tensor 转换
  1. 看单位与数值范围

  • 10~100 量级常是米

  • 0~W/H 常是像素

  • 0~feature map 尺寸常是索引

  • -1~1 常是归一化坐标

  1. 看数组访问方式

  • img[v][u]/img[row,col]:像素索引
  • tensor[n,c,h,w]:张量索引
  • 线代乘法 R@p+t:几何空间

13.2 快速排错清单

  • 这个 x,y 的单位是什么?
  • 当前坐标相对哪个原点?

  • 是连续值还是离散索引?

  • 是否经历过 resize/crop/pad/flip?

  • 是否在量化域(int8)中做了几何运算?


14. 总结

真正可落地的空间认知体系不是“记住几个公式”,而是建立以下闭环:

  • 明确每个坐标系回答的问题

  • 明确每次转换的输入参数与输出数据形式

  • 明确单位、精度与量化影响

  • 明确预处理/后处理对坐标的扰动

  • 明确代码命名与坐标语义的一一对应关系

当你能稳定把 world -> sensor -> image -> pixel -> tensor 以及逆向链路讲清楚,并在代码中快速定位“当前点到底在哪个空间”,视觉系统的大部分隐性错误都将从“玄学问题”变成“可验证、可修复的工程问题”。
算法工具链
杂谈
评论0
0/1000