首页/新闻资讯/正文详情

Kornia 修复空批次几何变换的 ZeroDivisionError:`transform_points` 与 `PinholeCamera.project` 的 empty-batch 语义

发布时间:2026/9/24 15:36:05 来源:云帆数科 栏目:资讯中心
Kornia 修复空批次几何变换的 ZeroDivisionError:`transform_points` 与 `PinholeCamera.project` 的 empty-batch 语义
Kornia 修复空批次几何变换的 ZeroDivisionErrortransform_points与PinholeCamera.project的 empty-batch 语义【免费下载链接】kornia Geometric Computer Vision Library for Spatial AI项目地址: https://gitcode.com/gh_mirrors/ko/kornia导读本文围绕 Kornia 变更记录 changelog.d/4487.fixed.md对应上游 issue #4466展开剖析transform_points在“空变换批次 非空点轴”这一组合输入下引发的ZeroDivisionError崩溃及其修复方案。文章从底层0 // 0的成因出发结合 transform_points 源码、PinholeCamera.project 实现 与回归测试讲清 Kornia 对空批次empty batch输入的统一约定空输入应返回同形状的空输出而不是崩溃。读完你将掌握这一修复的完整来龙去脉以及在实际几何/相机管线中如何规避同类问题。一、问题背景Kornia 的空批次empty batch约定在 Kornia 的几何管线中张量普遍以批处理batched方式组织。例如 3D 点云形状为(B, N, 3)对应的齐次变换矩阵形状为(B, 4, 4)。当某些输入批次恰好为空batch size 为 0即B 0时Kornia 的既定语义是空输入进空输出出empty-in / empty-out对空集执行变换结果仍为空集且形状与输入保持一致这一约定对批处理数据加载、滑动窗口推理、无标注样本的预处理等场景至关重要——例如一张图像裁剪块image chip内没有任何标注点时变换逻辑不应中断整个管线。本变更记录所修复的正是这一约定被破坏的边角场景变换批次为空(0, 4, 4)而点张量的点轴非空(0, 5, 3)。注意这里点张量的 batch 轴也为 0但由于点轴N5非空旧实现会在广播broadcast变换矩阵时触发崩溃。二、崩溃根因展开变换矩阵时的0 // 0在修复前transform_points的核心逻辑依赖torch.repeat_interleave将变换矩阵广播到与点张量相同的 batch 数量。相关实现见 kornia/geometry/linalg.py广播部分位于repeats points_1.shape[0] // trans_01.shape[0] trans_01 torch.repeat_interleave(trans_01, repeatsint(repeats), dim0)当输入为trans_01.shape (0, 4, 4)空变换批次且points_1.shape (0, 5, 3)时points_1.shape[0] // trans_01.shape[0]即0 // 0Python 中整数0 // 0直接抛出ZeroDivisionError于是整个transform_points在真正开始矩阵乘法之前就崩溃了。值得注意的是0 // 0只有在两个 batch 维度都为 0时才会触发。若只有变换批次为空、点张量 batch 也完全为空(0, 0, 3)除数与被除数同为 0同样崩溃而若变换批次非空如(1, 4, 4)0 // 1 0反而能正常返回空结果。这正是该 bug 表现“不一致”的原因——同样是“空输入”有的形状能通过、有的形状崩溃。三、修复方案提前短路与除零保护本次修复对transform_points做了两处关键改动见 kornia/geometry/linalg.py1. 空点轴提前返回# No points to transform (e.g. an image chip with no annotations): transforming an empty set # yields the same empty set. Return early — the reshape below cannot infer -1 from a # 0-element tensor, so this also avoids a spurious crash on valid empty inputs. if points_1.shape[-2] 0: return points_1当点张量的点轴N 0时直接原样返回。除了规避0 // 0这一早退还有另一层原因后续points_1.reshape(-1, ...)需要从 0 元素张量推断-1维度-1无法从空张量推断本身也会引发运行时错误。提前返回同时规避了这一隐患。2. 除法加保护repeats points_1.shape[0] // trans_01.shape[0] if trans_01.shape[0] 0 else 0当变换批次为空trans_01.shape[0] 0时不再执行除法而是直接将repeats置为 0。此时torch.repeat_interleave对空张量的 repeat 次数为 0结果仍为空张量随后的torch.bmm在空输入下自然产出空输出最终返回与输入形状一致的空结果。3. 修复后的完整行为修复后transform_points的输入输出对应关系为变换矩阵形状点张量形状修复前行为修复后行为(B, 4, 4)B0(B, N, 3)N0正常变换正常变换不变(B, 4, 4)(B, 0, 3)reshape 崩溃或0//0原样返回空点集(0, 4, 4)(0, 5, 3)ZeroDivisionError0//0返回(0, 5, 3)空结果(1, 4, 4)(0, 5, 3)正常返回空结果正常返回空结果不变另外需要说明transform_points的形状校验linalg.py#L203-L210要求两个输入 batch 大小相等或变换批次为 1且最后一维相差 1如 4x4 变换对应 3 维点这些校验在修复前后保持一致未做放宽。四、PinholeCamera.project的连带修复ZeroDivisionError不仅影响transform_points本身还通过调用链传染给了PinholeCamera.project。从 kornia/geometry/camera/pinhole.py#L382-L419 可以看到其投影实现def project(self, point_3d: torch.Tensor) - torch.Tensor: if len(point_3d.shape) 2: raise ValueError(fInput must be at least a 2D tensor. Got {point_3d.shape}) P self.intrinsics self.extrinsics return convert_points_from_homogeneous(transform_points(P, point_3d))project将内参矩阵与外参矩阵相乘得到投影矩阵P形状(B, 4, 4)后直接委托给transform_points完成齐次变换与透视除法。因此当相机批次为空内参/外参为(0, 4, 4)、点张量为(0, 3)时旧实现恰好能“侥幸”通过而当点张量为(0, N, 3)N0时transform_points内部的0 // 0崩溃被直接继承project也随之抛ZeroDivisionError。修复transform_points后PinholeCamera.project对空相机批次 任意点轴形状的空点集均能正确返回空结果无需单独改动project本身——这正是“在底层修复、在上层受益”的典型回归修复模式。从源码结构看kornia.geometry.pose中的同名transform_points入口以及convert_points_from_homogeneous的调用路径也遵循同样的 empty-in/empty-out 约定。五、回归测试如何验证修复本次修复配有专门的回归测试覆盖了此前崩溃的精确输入组合1.transform_points空批次测试见 tests/geometry/test_linalg.py#L56-L79pytest.mark.parametrize(num_dims, [2, 3]) pytest.mark.parametrize(points_shape, [(0, 1), (0, 5)]) def test_transform_points_empty_batch_with_points(self, num_dims, points_shape, device, dtype): # An empty transform batch with a non-empty point axis divided 0 // 0 while expanding the # transforms (kornia#4466); it must return the same empty shape as a B1 transform does. points torch.zeros(*points_shape, num_dims, devicedevice, dtypedtype) empty_trans torch.eye(num_dims 1, devicedevice, dtypedtype).expand(0, -1, -1) single_trans torch.eye(num_dims 1, devicedevice, dtypedtype)[None] out kgl.transform_points(empty_trans, points) assert out.shape points.shape assert out.dtype dtype assert out.shape kgl.transform_points(single_trans, points).shape该测试的断言设计值得注意空批次的结果形状必须与B1变换作用于同一点集的结果形状一致即空输入的结果语义应与“只有一个变换”时的广播结果对齐而不是凭空多出维度。2.PinholeCamera.project继承修复测试见 tests/geometry/camera/test_pinhole.py#L923-L931def test_project_an_empty_batch_with_a_point_axis_4466(self, device, dtype): # Regression for kornia#4466: an empty camera batch projected (0, 3) points but raised # ZeroDivisionError on (0, N, 3), inside transform_points. trans torch.eye(4, devicedevice, dtypedtype).expand(0, 4, 4) empty torch.zeros(0, devicedevice, dtypedtype) camera kornia.geometry.camera.PinholeCamera(trans, trans, empty, empty) assert camera.project(torch.zeros(0, 3, devicedevice, dtypedtype)).shape (0, 2) assert camera.project(torch.zeros(0, 1, 3, devicedevice, dtypedtype)).shape (0, 1, 2)测试同时验证了(0, 3)与(0, 1, 3)两种点形状前者是修复前就能通过的路径后者是修复前崩溃的路径两者修复后均返回正确形状的空张量。此外 tests/geometry/camera/test_pinhole.py#L900-L921 还验证了空相机批次在构造、形状与 dtype 上的一致性以及kornia.geometry.camera.project_points自由函数遵循同样的空进空出约定。六、对开发者代码的影响与建议从本次修复可以提炼出几条对 Kornia 使用者有价值的实践升级后行为变化是“变好”而非“破坏”修复只影响此前抛异常的输入组合。如果你的代码曾依赖捕获ZeroDivisionError来识别空批次升级后需改为直接检查输出形状如out.shape[0] 0或提前判断输入是否为空因为异常不再抛出。空批次语义是 Kornia 的通用约定从 transform_points 到 PinholeCamera.project再到PinholeCamera构造器的空批次支持见 test_pinhole.py#L900-L931 中对kornia#4281的回归Kornia 正在系统性地统一“空输入 → 空输出”的约定。在自己封装几何工具时建议对 batch 维度为 0 的输入做短路返回避免在0 // 0、reshape(-1)等位置踩坑。形状校验仍然有效修复并未放宽输入合法性检查。transform_points仍要求 batch 相等或变换批次为 1linalg.py#L205-L208project仍要求点张量至少为 2 维pinhole.py#L416-L417非法形状依旧会以ValueError明确拒绝便于尽早发现调用方错误。小结变更 4487.fixed.md 修复的是一个小而典型的边界缺陷transform_points在空变换批次配合非空点轴时因0 // 0抛出ZeroDivisionError并通过调用链波及PinholeCamera.project。修复通过“空点轴提前返回 除零保护”双保险让空批次输入在任意形状组合下都稳定返回同形状空结果并配套了 test_linalg.py 与 test_pinhole.py 两组回归测试锁定行为。这一修复也再次印证了 Kornia 几何模块“空进空出”的设计约定为批处理数据管线的健壮性提供了保障。【免费下载链接】kornia Geometric Computer Vision Library for Spatial AI项目地址: https://gitcode.com/gh_mirrors/ko/kornia创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

VoltAgent 集成 Pinecone 向量数据库:构建双模式 RAG 知识检索 Agent 实战指南
VoltAgent 集成 Pinecone 向量数据库:构建双模式 RAG 知识检索 Agent 实战指南

人工智能AI AgentAgent 框架后端多智能体RAG工具调用Agent 记忆 【免费下载链接】voltagent AI Agent Engineering Platform built on an Open Source TypeScript AI Agent Framework 项目地址: https://gitcode.com/gh_mirrors/vo/voltagent 点击查看 免费下载 导… · 2026/9/24 15:36:05

Flink SQL DELETE 语句详解:行级删除原理、SupportsRowLevelDelete 接口与实战示例
Flink SQL DELETE 语句详解:行级删除原理、SupportsRowLevelDelete 接口与实战示例

大数据流处理批处理数据工程 【免费下载链接】flink 项目地址: https://gitcode.com/gh_mirrors/fli/flink 点击查看 免费下载 本篇文章系统讲解 Apache Flink 中 SQL DELETE 语句的使用方法与底层实现。DELETE 是 Flink Table 模块提供的行级删除能力,… · 2026/9/24 15:36:05

F´ 框架中的 Svc::FatalHandler 组件:FATAL 事件处理与平台差异化实现解析
F´ 框架中的 Svc::FatalHandler 组件:FATAL 事件处理与平台差异化实现解析

嵌入式系统编程 【免费下载链接】fprime F - A flight software and embedded systems framework 项目地址: https://gitcode.com/gh_mirrors/fp/fprime 点击查看 免费下载 导读 Svc::FatalHandler 是 F(F Prime)飞行软件与嵌入式系统框架中… · 2026/9/24 15:35:52

应用案例 | 船舶海洋:基于MBSE 的船舶系统电磁兼容性设计专用软件开发
应用案例 | 船舶海洋:基于MBSE 的船舶系统电磁兼容性设计专用软件开发

一、项目背景随着船舶系统复杂度的不断提升,舰载电子设备的数量持续增加,系统间的电磁耦合关系也日益变得复杂,传统的基于文档的电磁兼容性设计方式已暴露出流程衔接性差、协同作业效率低、知识复用度不足等问题。以基于模型的系统工程&#… · 2026/9/24 16:03:02

软件测试的分类
软件测试的分类

软件测试的分类按手段划分:手工测试、自动化测试按是否运行代码划分:静态测试、动态测试按技术划分:黑盒测试、白盒测试、灰盒测试按阶段划分:单元测试、集成测试、系统测试、验收测试性能测试冒烟测试:对软件的基本功… · 2026/9/24 16:03:02

高精度三维线圈动态屏蔽系统:弱磁实验环境优化核心方案
高精度三维线圈动态屏蔽系统:弱磁实验环境优化核心方案

在弱磁精密检测、磁性材料研发、传感器标定、生物磁学研究等高端科研领域,环境磁场干扰是影响实验数据精度的核心难题。地磁场固有偏移、地铁、电梯、电气设备产生的动态交变磁干扰,会直接导致微弱磁场实验数据漂移、重复性差、误差超标。传统被动磁屏蔽… · 2026/9/24 16:03:02

GEO技术原理深度解析:AI引用概率=权威度×结构化×语义匹配×多源一致×时效性
GEO技术原理深度解析:AI引用概率=权威度×结构化×语义匹配×多源一致×时效性

总有人把 GEO 说成玄学。其实它有清清楚楚的技术原理——业内把核心逻辑总结成一个公式:AI 引用概率 权威度 结构化程度 语义匹配 多源一致性 时效性。五个变量,缺一不可。下面逐个拆开说。 变量一:权威度——占了快一半 AI 打分时&… · 2026/9/24 16:03:02

Koin 在 Kotlin Multiplatform(KMP)中的完整配置指南:依赖、模块划分与多平台启动
Koin 在 Kotlin Multiplatform(KMP)中的完整配置指南:依赖、模块划分与多平台启动

后端 【免费下载链接】koin Koin - a pragmatic lightweight dependency injection framework for Kotlin & Kotlin Multiplatform 项目地址: https://gitcode.com/gh_mirrors/ko/koin 点击查看 免费下载 Koin 为 Kotlin Multiplatform(KMP&#xf… · 2026/9/24 16:02:55

douyin-downloader 抖音批量下载教程:三步从零跑通,去水印下载与自动归档
douyin-downloader 抖音批量下载教程:三步从零跑通,去水印下载与自动归档

douyin-downloader 抖音批量下载教程:三步从零跑通,去水印下载与自动归档 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplicatio… · 2026/9/24 16:02:55

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13

1D-CNN时间序列建模实战:从Conv1d原理到工业落地
1D-CNN时间序列建模实战:从Conv1d原理到工业落地

简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26

柔软的L:汉语语流中被忽视的舌肌张力控制
柔软的L:汉语语流中被忽视的舌肌张力控制

1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码