- 计算机视觉
- 深度学习
- 人工智能
- 图像处理
【免费下载链接】kornia
🐍 空间人工智能的几何计算机视觉库
本篇迁移指南面向使用 Kornia 几何变换 API 的开发者,完整解析 2D/3D 单应性归一化函数normalize_homography、denormalize_homography、normalize_homography3d形状守卫(shape guard)的破坏性变更(对应仓库 changelog.d/+migration-014.breaking.md 中的 migration-014 条目)。读完后你将掌握:新守卫精确接受哪些形状、哪些曾经"侥幸通过"的输入现在会立即抛出ValueError、为何torch.jit.trace会新增一条无害的TracerWarning,以及如何用最小改动完成代码迁移与测试适配。
一、变更总览:三个函数,一套更严格的行数形状规则
本次破坏性变更(仓库内以 PR #3999 落地,测试中以 kornia#3960 命名固定)只影响一个维度——输入矩阵的秩(rank)与末尾两维尺寸的校验。核心结论如下:
| 函数 | 维度 | 现在接受的形状 | 现在拒绝的形状 |
|---|---|---|---|
normalize_homography | 2D | (3, 3)、(B, 3, 3) | rank-4(如(2, 4, 3, 3))、(B, 4, 4)、任何非(3,3)尾维 |
denormalize_homography | 2D | (3, 3)、(B, 3, 3) | 同上,与normalize_homography完全一致 |
normalize_homography3d | 3D | (4, 4)、(B, 4, 4) | rank-4(如(2, 4, 4, 4))、(B, 3, 3)、任何非(4,4)尾维 |
三条不变的行为规则值得单独强调:
- 未批处理的
(3, 3)/(4, 4)矩阵依旧被接受,并会被提升为带前导批维的(1, 3, 3)/(1, 4, 4)—— 这是本次收紧刻意保留的旧行为,而不是新引入的(见下文测试固定点的说明)。 - rank-4 输入曾经能通过守卫并以原秩返回,现在一律抛出
ValueError。 - 尺寸错误的输入(例如把
(B, 4, 4)传给 2D 函数)曾经能通过守卫、直到在matmul内部才失败,现在在守卫处立即抛出,且错误消息指向参数名与期望形状。
二、破坏性细节:三种曾经"通过"的输入,现在如何失败
2.1 rank-4 输入:从"原秩返回"到直接拒绝
文档给出了精确的复现用例:
import torch from kornia.geometry.conversions import normalize_homography # 旧行为:返回 (2, 4, 3, 3),秩保持不变 # out = normalize_homography(torch.eye(3).expand(2, 4, 3, 3), (4, 5), (8, 9)) # 新行为:立即抛出 ValueError normalize_homography(torch.eye(3).expand(2, 4, 3, 3), (4, 5), (8, 9))新守卫抛出形如Input dst_pix_trans_src_pix must be a Bx3x3 tensor. Got torch.Size([2, 4, 3, 3])的ValueError,直接点名参数与收到的形状。3D 版本同理,normalize_homography3d(torch.eye(4).expand(2, 4, 4, 4), (2, 4, 5), (3, 8, 9))会以must be a Bx4x4 tensor的措辞拒绝。
2.2 尺寸错误:失败点从matmul前移到守卫
把一个(B, 4, 4)矩阵传给 2D 函数,过去守卫的or结构会让它放行,最终在dst_norm_trans_dst_pix @ (dst_pix_trans_src_pix @ src_pix_trans_src_norm)这条矩阵链里以难以解读的matmul错误告终;现在则在进入任何算术之前就被守卫拦截,错误消息同时给出参数名和期望形状,定位成本显著下降。
2.3 3D 错误消息修正:从Bx3x3到Bx4x4
normalize_homography3d是操作(B, 4, 4)矩阵的函数,但旧守卫的错误消息却错误地写着must be a Bx3x3 tensor。本次变更一并修正为Bx4x4。仓库测试 tests/geometry/test_conversions.py 专门用pytest.raises(ValueError, match="must be a Bx4x4 tensor")固定了这一措辞,并解释了原因:如果只收紧守卫的"条件"而不修正"名词",测试表格里的尺寸用例依然会通过,错误消息缺陷会被悄悄掩盖。
三、源码级验证:新守卫到底长什么样
三个函数的守卫实现位于 kornia/geometry/conversions.py,逻辑完全一致、仅尾维尺寸不同:
- normalize_homography 与 denormalize_homography:
if not isinstance(dst_pix_trans_src_pix, torch.Tensor): raise TypeError(f"Input type is not a torch.Tensor. Got {type(dst_pix_trans_src_pix)}") if not (dst_pix_trans_src_pix.ndim in (2, 3) and dst_pix_trans_src_pix.shape[-2:] == (3, 3)): raise ValueError(f"Input dst_pix_trans_src_pix must be a Bx3x3 tensor. Got {dst_pix_trans_src_pix.shape}")- normalize_homography3d:
if not (dst_pix_trans_src_pix.ndim in (2, 3) and dst_pix_trans_src_pix.shape[-2:] == (4, 4)): raise ValueError(f"Input dst_pix_trans_src_pix must be a Bx4x4 tensor. Got {dst_pix_trans_src_pix.shape}")新旧守卫的差别正是文档所指出的:
# 旧结构:len(shape) == 3 对任意 rank-3 输入短路为 True, # shape[-2:] == (3, 3) 永远不会被评估,导致 (1, 4, 4) 也能放行 # len(shape) == 3 or shape[-2:] == (3, 3) # 新结构:秩与尾维两个条件同时成立才放行 # ndim in (2, 3) and shape[-2:] == (3, 3)旧结构里or的短路语义是两次事故的共同根源:rank-3 输入只验证了秩、跳过了尾维校验,于是(1, 4, 4)能进入 3x3 的 2D 函数;rank-4 输入则因为shape[-2:] == (3, 3)恰好成立而被整条放行。
四、测试固定:仓库如何锁定这条约定
本次行为被仓库以三组测试固定(pin)在 tests/geometry/test_conversions.py 中,全部围绕 kornia#3960 展开:
- 尺寸错误用例(L4720-L4751):通过共享表格
_WRONG_SIZE_CASES = [("normalize_homography", 4), ("denormalize_homography", 4), ("normalize_homography3d", 3)]驱动,为每个函数传入一个"错误尺寸的单位阵"(2D 函数传(1, 4, 4)、3D 函数传(1, 3, 3)),断言异常必须由 Kornia 守卫抛出(而非 matmul 内部),从而防止守卫条件回退。 - 3D 消息措辞(L4753-L4766):断言消息包含
must be a Bx4x4 tensor。 - 秩与未批处理行为(L4768-L4797):断言
(N, N)与(1, N, N)输入均被接受且返回形状为(1, N, N)(未批处理输入被提升到前导批维 1,而不会还原为无批维形状);断言eye.expand(2, 1, size, size)这类 rank-4 输入抛出ValueError且消息包含参数名dst_pix_trans_src_pix。
测试注释还明确了两点设计意图:未批处理路径是旧行为、必须保留,否则"更窄的修复"(只写ndim == 3 and shape[-2:] == (N, N))会破坏它;rank-4 拒绝则是本次刻意的收紧,因为三个函数文档声明的参数就是Bx3x3/Bx4x4。
五、调用方影响:谁在内部使用这三个函数
从源码看,这三个函数是透视/仿射 warp 管线的核心环节,调用点集中在 kornia/geometry/transform/imgwarp.py:
- warp_perspective 与 warp_affine 内部调用
normalize_homography,把像素坐标系的M归一化到grid_sample所需的[-1, 1]坐标系; - warp_affine3d 与 3D 透视 warp 内部调用
normalize_homography3d。
这些内部调用点传入的都是由convert_affinematrix_to_homography/convert_affinematrix_to_homography3d产生的标准(B, 3, 3)/(B, 4, 4)矩阵,不受此次收紧影响。真正受影响的是直接调用这三个函数、且曾依赖宽松守卫放行非常规形状的代码——典型场景是把(B, D, 3, 3)这样的多批维张量直接传入(旧版本会广播并原秩返回),或错误地把 4x4 矩阵传给 2D 函数。
一个值得注意的实现细节:normalize_homography的归一化矩阵逆采用无 cusolver 的闭式 3x3 伴随矩阵(eager 模式走 kornia/core/_small_linalg.py 的_inverse_3x3_cross,三次torch.linalg.cross融合;trace/导出模式走 kornia/core/utils.py 的标量余子式展开),而denormalize_homography与normalize_homography3d在 eager 模式走torch.linalg.inv(经 kornia/core/utils.py 的_torch_inverse_cast)。这意味着守卫收紧后,形状校验发生在任何求逆或矩阵乘法之前,此前"守卫放行、下游爆炸"的场景现在全部提前到入口处报错,错误可读性大幅提升。
六、TracerWarning 副作用:噪音,不是正确性信号
本次变更有一个波及torch.jit.trace用户的副作用,文档明确将其定性为"噪音,而非正确性信号":
重写的守卫会无条件评估其形状比较;旧
or形式对 rank-3 输入会短路跳过它。因此对三个函数中任意一个执行torch.jit.trace,现在都会发出一条此前不存在的TracerWarning,提示"将张量转换为 Python bool"。
机制解释:旧守卫len(shape) == 3 or shape[-2:] == (3, 3)对 rank-3 输入因第一个条件为真而短路,shape[-2:] == (3, 3)这个涉及张量的比较根本不会执行;新守卫ndim in (2, 3) and shape[-2:] == (3, 3)则无论输入如何都会评估尾维比较,trace 阶段 torch 检测到张量参与 Python 布尔运算便会发出警告。
但请放心:
- 守卫是静态形状检查,不参与计算图;
- trace 出的图与变更前逐算子一致,无任何数值或结构差异;
- 若你的 CI 将
TracerWarning视为错误(-W error),需要在该处显式过滤此警告;否则可直接忽略。
七、迁移清单:三步完成升级适配
- 排查直接调用点:全局搜索
normalize_homography(、denormalize_homography(、normalize_homography3d(,确认传入矩阵的形状严格为(3, 3)/(B, 3, 3)或(4, 4)/(B, 4, 4)。所有通过 warp 高层 API(warp_perspective、warp_affine、warp_affine3d等)的路径无需改动。 - 消除非常规形状:若有
(B, D, 3, 3)这类多批维输入,需手动reshape/view合并批维为(B', 3, 3),归一化后再还原;若有(B, 4, 4)误入 2D 函数,改为对应的 3D 语义或修正为 3x3。 - 处理 trace 警告:如使用
torch.jit.trace,为上述三个函数的新增TracerWarning添加显式过滤(例如 pytest 的filterwarnings或warnings.catch_warnings),并确认图中算子无变化。
配套验证方式:直接运行 tests/geometry/test_conversions.py 中与 kornia#3960 相关的三个测试用例,可确认你所在环境的行为与仓库固定约定一致。
八、延伸阅读
- 函数定义与完整 docstring:
normalize_homography(kornia/geometry/conversions.py)、denormalize_homography(kornia/geometry/conversions.py)、normalize_homography3d(kornia/geometry/conversions.py); - 守卫行为的测试固定:tests/geometry/test_conversions.py;
- 闭式逆与 trace 回退实现:kornia/core/utils.py、kornia/core/_small_linalg.py;
- 内部调用方:kornia/geometry/transform/imgwarp.py、kornia/geometry/transform/imgwarp.py;
- 关联变更记录:changelog.d/+migration-014.breaking.md。
- 计算机视觉
- 深度学习
- 人工智能
- 图像处理
【免费下载链接】kornia
🐍 空间人工智能的几何计算机视觉库
相关推荐
kornia 同源性归一化函数形状守卫收紧迁移指南:normalize_homography 系列从宽松到严格的 breaking change
kornia 同源性归一化函数形状守卫收紧迁移指南:normalize_homography 系列从宽松到严格的 breaking change 本篇迁移指南以
计算机视觉人工智能深度学习图像处理Kornia 迁移指南:`unproject_meshgrid` 内参形状校验收紧——从 `(B,3,3)` 严格要求到调用方形状报错
Kornia 迁移指南: unproject_meshgrid 内参形状校验收紧——从 B,3,3 严格要求到调用方形状报错 本篇文章聚焦 Kornia 仓库
计算机视觉深度学习人工智能图像处理Kornia `pixel2cam` 深度张量形状校验修复:`Bx1xHxW` 规范与迁移指南
Kornia pixel2cam 深度张量形状校验修复: Bx1xHxW 规范与迁移指南 pixel2cam 是 Kornia 中将像素坐标反投影到相机坐标系的
计算机视觉深度学习人工智能图像处理
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考