Kornia 针孔相机形状校验修复解析:PinholeCamera、PinholeCamerasList 与 pixel2cam / cam2pixel 的 ValueError 契约
2026/9/23 23:24:51 网站建设 项目流程
  • 计算机视觉
  • 人工智能
  • 深度学习
  • 图像处理

【免费下载链接】kornia

🐍 Geometric Computer Vision Library for Spatial AI

项目地址:https://gitcode.com/gh_mirrors/ko/kornia
点击查看免费下载

本指南聚焦 Kornia 中针孔相机(Pinhole Camera)核心模块的一次输入校验修复(issue #4387):PinholeCameraPinholeCamerasList共享的矩阵形状检查、pixel2cam的坐标形状检查,以及cam2pixel的坐标/投影矩阵检查被修正,无效输入现在会在入口处抛出预期的ValueError,而不是被静默接受或在后续张量运算中才暴露问题。读完本文,你将掌握 Kornia 针孔相机各 API 的精确输入形状约定、形状校验的源码实现与测试验证方式,并理解PinholeCamerasList的四维(rank-4)矩阵为何保持兼容。

修复背景:形状校验为什么重要

Kornia 的针孔相机模块位于 kornia/geometry/camera/pinhole.py,它同时提供面向对象 API(PinholeCamera类)和函数式 API(pixel2camcam2pixelproject_points等)。这类 API 的输入是带批次的张量,形状约定高度结构化:

  • 内参intrinsics(B, 4, 4)标定矩阵,左上 3×3 块为[[fx, 0, cx], [0, fy, cy], [0, 0, 1]]
  • 外参extrinsics(B, 4, 4)的世界到相机变换[R | t]
  • height/width(B,)的一维张量;
  • 网格类输入pixel_coords/cam_coords_src(B, H, W, 3)

在修复之前,部分非法形状(例如非方阵、错误秩、多通道 depth)会被默认接受,直到矩阵乘法或逐元素除法等深层张量操作才以难以理解的错误失败。本次修复(changelog.d/+migration-026.fixed.md)把检查前移到 API 入口,统一以带具体形状信息的ValueError拒绝无效输入。

共享矩阵形状检查:_check_valid_params

PinholeCamera构造函数在存储参数之前会调用一组校验方法。其中核心的矩阵形状检查是_check_valid_params(pinhole.py 第 102-108 行):

@staticmethod def _check_valid_params(data: torch.Tensor, data_name: str) -> bool: if len(data.shape) not in (3, 4) or data.shape[-2:] != (4, 4): raise ValueError( f"Argument {data_name} shape must be in the following shape Bx4x4 or BxNx4x4. Got {data.shape}" ) return True

这段代码是本次修复的核心证据,它定义了精确的形状契约:

  • 张量秩(len(data.shape))必须是 3 或 4——即Bx4x4BxNx4x4
  • 最后两维必须恰好是(4, 4),任何非方阵(如(1, 3, 4)(1, 5, 4))都会被拒绝;
  • 错误信息会携带参数名data_name与实际形状data.shape,方便调用者定位问题。

PinholeCamera.__init__依次对intrinsicsextrinsics调用该方法,并对height/width调用_check_valid_shape(要求一维(B,)),再通过_check_valid保证四个参数的 batch size 一致(不匹配时抛出ValueError: Arguments shapes must match)。此外_check_consistent_device通过KORNIA_CHECK_SAME_DEVICE保证所有张量在同一设备上。

pixel2cam:像素坐标系到相机坐标系

函数pixel2cam(pinhole.py 第 815-845 行)将像素坐标网格反投影到相机坐标系,输入约定为:

参数要求形状失败时抛出的错误
depthBx1xHxWValueError: Input depth has to be in the shape of Bx1xHxW. Got ...
intrinsics_invBx4x4ValueError: Input intrinsics_inv has to be in the shape of Bx4x4. Got ...
pixel_coordsBxHxWx3ValueError: Input pixel_coords has to be in the shape of BxHxWx3. Got ...

注意intrinsics_inv的检查条件是len(intrinsics_inv.shape) == 3 and intrinsics_inv.shape[-2:] == (4, 4)——它要求的是PinholeCamera布局的(B, 4, 4)逆标定矩阵,而非函数式 API 常用的(*, 3, 3)K。这一点在修复中特别关键:一个"仅检查秩"的宽松守卫会让非方阵通过并返回错误数量的坐标分量,而本次修复改为同时校验后两维是否为(4, 4)depth必须为单通道,多通道 depth 会被拒绝,避免"每个坐标分量被不同通道深度缩放"的静默错误。

通过校验后,函数以transform_points(intrinsics_inv[:, None], pixel_coords)施加逆内参,再乘上深度得到BxHxWx3的相机坐标。

cam2pixel:相机坐标系到像素坐标系

函数cam2pixel(pinhole.py 第 852-895 行)执行正向投影,同样在入口处完成两项检查:

参数要求形状失败时抛出的错误
cam_coords_srcBxHxWx3ValueError: Input cam_coords_src has to be in the shape of BxHxWx3. Got ...
dst_proj_srcBx4x4ValueError: Input dst_proj_src has to be in the shape of Bx4x4. Got ...

dst_proj_src(B, 4, 4)的投影矩阵(PinholeCamera布局),而非(*, 3, 3)K。投影过程为:先用transform_points施加投影矩阵得到(x, y, z),再做透视除法u = x / (z + eps)v = y / (z + eps)(默认eps=1e-12),最终返回BxHxWx2的像素坐标。从源码结构看,该除法不做除零保护,z = 0时会在float32/float64/bfloat16下得到约1e14量级的有限值、在float16下得到inf,这一行为在测试中被标记为已知缺陷(kornia#4267)并单独固定。

PinholeCamerasList的四维矩阵兼容

PinholeCamerasList(pinhole.py 第 522-576 行)继承自PinholeCamera,表示一组相机。其_initialize_parameters将每台相机的参数沿新维度堆叠:给定 N 台PinholeCameraintrinsics/extrinsics的形状为(B, N, 4, 4)。因此共享的_check_valid_params必须同时接受秩 3(Bx4x4)与秩 4(BxNx4x4)——这正是本次修复中len(data.shape) not in (3, 4)data.shape[-2:] != (4, 4)两个条件的设计动机:收紧到精确的4x4后两维的同时,保留对 rank-4 列表布局的兼容。

测试 tests/geometry/camera/test_pinhole.py 第 866-875 行 的test_camera_list_preserves_rank_four_parameters验证了这一点:构造两台相机组成的PinholeCamerasList后,cameras.intrinsics.shape == (1, 2, 4, 4)cameras.extrinsics.shape == (1, 2, 4, 4),且get_pinhole(1).project(...)与单台相机的投影结果一致。num_cameras属性通过intrinsics.shape[1]返回相机数量。

测试验证:无效形状一律ValueError

本次修复由参数化测试完整覆盖(tests/geometry/camera/test_pinhole.py):

  • test_invalid_parameter_shape_4266(第 852-864 行):对intrinsics/extrinsics遍历(4, 4)(1, 3, 3)(1, 3, 4)(1, 5, 5)(1, 2, 3, 3)(1, 1, 1, 4, 4)等形状,断言抛出ValueError且消息匹配Argument {parameter} shape must be ...
  • test_invalid_projection_shape_4266(第 186-191 行):cam2pixel的投影矩阵遍历()(4, 4)(3, 3)(1, 3, 3)(1, 3, 4)(1, 5, 4)(1, 1, 4, 4)等非法形状;
  • test_invalid_coordinate_shape_4266(第 193-207 行):cam2pixelpixel2cam的坐标张量遍历()(3,)(1, 3)(1, 2, 3, 2)(1, 2, 3, 4)(1, 2, 3, 1, 3)等形状,并断言错误信息中包含调用者传入的实际形状;
  • test_invalid_depth_shape(第 209-216 行)与test_invalid_intrinsics_shape_4266(第 325-338 行):覆盖pixel2cam的多通道 depth 与非4x4逆内参。

这些测试同时验证了错误消息的"自解释性":例如pytest.raises(ValueError, match="Input dst_proj_src has to be in the shape of Bx4x4")assert str(pixel_coords.shape) in str(exc_info.value),确保用户从异常文本即可得知期望形状与实际形状。此外test_convention_pixel2cam_rejects_multi_channel_depth_4266(第 356-388 行)专门固定了"单通道 depth 缩放整条射线、多通道 depth 被拒绝"的语义。

在修复序列中的位置

本次修复并非孤立事件,而是 Kornia 针孔相机输入契约收紧系列的一部分,同目录的变更记录可互为参照:

  • changelog.d/+migration-022.fixed.md:PinholeCamera.project对秩 1 输入抛出与点转换 API 一致的显式ValueError
  • changelog.d/+migration-014.fixed.md:unproject_meshgrid要求(B, 3, 3)内参并拒绝额外相机轴(#4383);
  • changelog.d/+migration-032.fixed.md:PinholeCameraStereoCamerawarp_frame_depth支持空批次(#4386)。

可以推断,这一系列修复的目标是让整个kornia.geometry.camera子模块在"输入形状合法性"上遵循统一契约:非法输入在入口即抛ValueError,合法但受限的输入(如 rank-4 列表布局、空批次)保持显式支持。对使用pixel2cam/cam2pixel做深度图重投影、光流采样或双目几何计算的开发者而言,这意味着可以在更早的调用点捕获形状错误,而无需在深层张量运算的晦涩报错中排查。

小结

  • PinholeCamera/PinholeCamerasList共享的_check_valid_params现在精确校验Bx4x4BxNx4x4,非法矩阵形状立即抛ValueError(kornia/geometry/camera/pinhole.py);
  • pixel2cam校验depthBx1xHxW)、intrinsics_invBx4x4)、pixel_coordsBxHxWx3)三者的形状;
  • cam2pixel校验cam_coords_srcBxHxWx3)与dst_proj_srcBx4x4);
  • rank-4 的(B, N, 4, 4)布局仍受支持,保证PinholeCamerasList的多相机场景不受影响;
  • 全部行为由参数化测试固定,错误消息携带参数名与真实形状,便于快速定位。

若你正在迁移依赖旧版宽松行为的代码,只需对照上文的形状表检查调用处的张量布局——凡是矩阵不是4x4、坐标网格不是...x3、深度不是Bx1xHxW的输入,都应在进入pixel2cam/cam2pixel或构造PinholeCamera之前显式 reshape 或修复。

  • 计算机视觉
  • 人工智能
  • 深度学习
  • 图像处理

【免费下载链接】kornia

🐍 Geometric Computer Vision Library for Spatial AI

项目地址:https://gitcode.com/gh_mirrors/ko/kornia
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询