Kornia `depth_from_disparity` 批量增强:为每批次立体相机独立设置基线与焦距
计算机视觉人工智能深度学习图像处理【免费下载链接】kornia Geometric Computer Vision Library for Spatial AI项目地址https://gitcode.com/gh_mirrors/ko/kornia点击查看免费下载本篇技术指南讲解 Kornia 几何模块中depth_from_disparity函数的一项关键能力升级baseline与focal参数现在支持每批次元素独立的(B,)张量形式让来自不同基线与焦距的立体相机组成的 batch 可以一次性完成视差到深度的转换而无需拆分后逐样本处理。读完本文你将掌握depth_from_disparity的全部四种参数形式、逐元素配对语义、形状约束与错误处理规则以及如何在项目中使用这一功能。视差与深度立体视觉中的三角测量关系在双目立体视觉中深度depth与视差disparity满足三角测量关系depth baseline * focal / disparity其中baseline是两个相机光心之间的物理距离focal是以像素为单位的焦距disparity是同一物理点在左右视图中的像素偏移。Kornia 的depth_from_disparity正是按此约定逐元素计算深度例如disparity为 2、baseline为 0.5、focal为 100 时得到的深度为 25。该函数位于kornia.geometry.depth子模块经由 kornia/geometry/init.py 的from .depth import *对外导出可直接以kornia.geometry.depth.depth_from_disparity(...)调用并收录于官方 API 文档 docs/source/geometry.depth.rst。变更概览一个 batch一次调用本变更对应变更记录 changelog.d/4648.added.md的核心是baseline与focal新增对每批次元素(B,)张量的支持一批来自不同基线或不同焦距的立体相机对stereo rig不再需要被拆分成单个样本逐一处理元素b的相机参数与disparity[b]配对共享形式Python 数字、标量张量、(1,)张量的行为与之前完全一致两种形式可以混合使用。在此之前若一个 batch 中的立体相机配置各不相同唯一可行的做法是循环逐样本调用将每个样本拆开分别传入共享参数再拼接结果现在这一过程可以在一次向量化调用中完成既减少了样板代码也避免了逐样本处理带来的开销。四种参数形式一览baseline与focal各自接受以下四种形式前三种是变更前的既有形式共享一个值作用于整个 disparity第四种是本变更新增的形式形式示例语义Python 数值0.5、100.0对整个 disparity 共享同一个值标量张量()torch.tensor(0.5)对整个 disparity 共享同一个值单元素张量(1,)torch.tensor([100.0])对整个 disparity 共享同一个值每批次元素张量(B,)torch.tensor([0.5, 2.0])元素b与disparity[b]配对一值对应一个 batch 样本从源码实现看这一分派逻辑集中在辅助函数_per_sample_camera_parameter中if not isinstance(parameter, torch.Tensor) or parameter.ndim 0 or parameter.shape (1,): return parameter # 共享形式原样返回行为不变 if parameter.ndim 1 and disparity.ndim 3: KORNIA_CHECK_SHAPE(parameter, [str(disparity.shape[0])]) # 必须等于 B return parameter.reshape(disparity.shape[0], *([1] * (disparity.ndim - 1))) # (B,) - (B, 1, ..., 1) KORNIA_CHECK_SHAPE(parameter, [1]) return parameter非张量输入int/float、标量张量与(1,)张量直接原样返回走与以前完全相同的广播路径只有(B,)形式才会被整形为(B, 1, ..., 1)从而借助 PyTorch 的广播机制实现元素b只作用于disparity[b]的配对。逐元素配对语义b ↔ disparity[b]当baseline或focal以(B,)形式传入时配对规则为参数的元素b仅与该 batch 中的第b个样本disparity[b]配对这要求disparity必须至少是秩 3即(B, H, W)或更高秩如(B, 1, H, W)且前导维度大小必须为B。测试 test_convention_per_batch_camera_parameters_4272 对(2, 1, 2, 3)与(2, 2, 3)两种 disparity 形状、以及baseline/focal/ 两者都按批次传入的三种组合进行了验证。测试精心设计了两组不同的相机数值baselines torch.tensor([0.5, 2.0]) focals torch.tensor([100.0, 30.0])这样如果配对发生错位例如第 0 个样本用了第 1 个样本的相机参数结果必然不同。测试把批量调用的结果与逐样本使用(1,)共享参数调用再拼接的结果逐位对比atol0.0, rtol0.0从而严格锁定配对语义per_sample torch.cat([ depth_from_disparity(disparity[b:b 1], baselines[b:b 1] if per_batch in (baseline, both) else shared_baseline, focals[b:b 1] if per_batch in (focal, both) else shared_focal) for b in range(2) ]) self.assert_close(depth, per_sample, atol0.0, rtol0.0)形状约束与错误处理不匹配即抛ShapeError新增的(B,)形式带来了一条明确的形状约束参数批次大小必须与 disparity 的前导批次大小一致。不匹配时抛出ShapeError这一点由_per_sample_camera_parameter中的KORNIA_CHECK_SHAPE保证。测试 test_convention_per_batch_camera_parameters_must_match_the_batch_4272 系统覆盖了错误场景three torch.ones(3, devicedevice, dtypedtype) with pytest.raises(ShapeError, matchexpected 2, got 3): depth_from_disparity(disparity, three, 100.0) # (3,) 参数 vs 批次为 2 的 disparity with pytest.raises(ShapeError, matchexpected 2, got 3): depth_from_disparity(disparity, 0.5, three) with pytest.raises(ShapeError, matchexpected 1, got 3): depth_from_disparity(torch.ones(2, 3, devicedevice, dtypedtype), three, 100.0)需要注意第三例当 disparity 是(2, 3)这样没有批次轴的形状时(3,)的参数理论上可以与宽度 3 发生广播但这正是设计上要拦截的歧义因此同样抛出ShapeError。与此同时测试确认了合法的共享形式与空批次行为不受影响depth_from_disparity(disparity, 1.0, 100.0)对(2, 1, 2, 3)的 disparity 正常返回(2, 1, 2, 3)(1,)形式torch.tensor([0.5])正常共享空批次torch.ones(0, 1, 2, 3)搭配空的(0,)参数仍返回(0, 1, 2, 3)不会误报错误。此外类型校验同样严格baseline/focal必须是int、float或torch.Tensor布尔值被明确排除字符串、复数、布尔值等非法输入会在 depth_from_disparity 入口处被KORNIA_CHECK拦截。两种形式混合使用新形式与共享形式可以自由混合这是批量场景中最实用的能力。例如一批立体相机对中baseline各不相同如不同型号的相机对但focal相同如统一分辨率与内参则可以只对baseline传(B,)张量、对focal传共享值import torch import kornia.geometry.depth as D disparity torch.rand(4, 1, 480, 640) # B4 的批量视差图 baseline torch.tensor([0.12, 0.20, 0.35, 0.08]) # 每样本独立基线米 focal 1000.0 # 共享焦距像素 depth D.depth_from_disparity(disparity, baseline, focal) print(depth.shape) # torch.Size([4, 1, 480, 640])测试 test_scalar_camera_parameters_4272 与test_convention_per_batch_camera_parameters_4272分别覆盖了全部共享与混合/全部逐样本的组合。源码级实现一次向量化的完整路径depth_from_disparity的完整执行流程如下kornia/geometry/depth.py入参校验KORNIA_CHECK_IS_TENSOR(disparity, ...)确认 disparity 是张量KORNIA_CHECK_SHAPE(disparity, [*, H, W])确认其至少为(*, H, W)对baseline/focal做类型检查并排除布尔值参数整形分别调用_per_sample_camera_parameter将(B,)张量整形为(B, 1, ..., 1)共享形式原样通过逐元素计算执行baseline * focal / (disparity 1e-8)。由于所有操作都是纯张量算术(B,)参数与批量 disparity 在整形后自然广播整个过程是完全可微的——测试 test_gradcheck 对()、(1,)、(2,)对应批次为 2 的批量场景三种参数形状均通过gradcheck验证说明该函数可以直接用于需要梯度回传的深度估计训练管线。数值细节epsilon、零视差与 float16 注意事项实现中有一个值得注意的细节epsilon 参与算术运算而非作为分支保护即除数为disparity 1e-8。这意味着立体匹配器在没有匹配处通常写入视差 0此时返回的是baseline * focal / 1e-8—— 对于baseline0.5、focal100结果是5e9一个有限的大数而非inffloat32、float64、bfloat16 均如此但该值由 epsilon 主导随baseline * focal缩放无法作为可靠的阈值依据在float16下1e-8本身会被舍入为 0除法实际是除以零仍然返回inf。该行为被测试 test_wart_zero_disparity_gives_a_finite_depth_4272 锁定测试注释明确标注这是对当前行为的 pin 而非契约待上游 issue 修复后应删除并与上游问题kornia#4272关联。此外depth_from_disparity不检查disparity的符号负视差会得到负深度。完整可运行示例将上述内容组合为一个完整示例模拟 4 台不同基线/焦距的立体相机对的批量视差图转换。import torch import kornia.geometry.depth as D torch.manual_seed(0) # 批量视差图4 个样本每个为 (1, H, W) disparity torch.rand(4, 1, 120, 160) # 场景 A每样本独立的基线与焦距 baseline torch.tensor([0.12, 0.20, 0.35, 0.08]) focal torch.tensor([1200.0, 900.0, 1500.0, 1100.0]) depth D.depth_from_disparity(disparity, baseline, focal) assert depth.shape (4, 1, 120, 160) # 输出形状与 disparity 一致 # 场景 B混合 —— 独立基线 共享焦距 depth_mixed D.depth_from_disparity(disparity, baseline, 1000.0) assert torch.allclose(depth_mixed[0], 0.12 * 1000.0 / disparity[0]) # 场景 C保持旧行为 —— 全部共享向后兼容 depth_shared D.depth_from_disparity(disparity, 0.2, 1000.0) assert torch.allclose(depth_shared[0], depth_shared[3]) # 错误用法参数批次大小与 disparity 批次不匹配 try: D.depth_from_disparity(disparity, torch.ones(3), 1000.0) # B4 vs 参数长度 3 except Exception as exc: print(type(exc).__name__, exc) # ShapeError: ...总结与适用场景本次增强让depth_from_disparity在真实的多相机系统中具备了实用价值。当你的批量数据满足disparity 前导维度为 B、且每个样本有独立相机参数这一条件时推荐直接使用(B,)形式完成向量化转换当所有样本共享相机参数时继续使用 Python 数值、标量张量或(1,)张量即可行为与此前完全一致两种形式也支持在同一调用中混用。进一步阅读完整实现与文档字符串kornia/geometry/depth.py#L801-L877配套测试套件tests/geometry/test_depth.py#L1060-L1237官方 API 文档入口docs/source/geometry.depth.rst变更记录原文changelog.d/4648.added.md赞分享计算机视觉人工智能深度学习图像处理【免费下载链接】kornia Geometric Computer Vision Library for Spatial AI项目地址https://gitcode.com/gh_mirrors/ko/kornia点击查看免费下载相关推荐Kornia depth_from_disparity 支持逐批次相机参数混合基线立体视觉批处理的深度估计Kornia depth_from_disparity 支持逐批次相机参数混合基线立体视觉批处理的深度估计 导读 本文讲解 Kornia 几何深度模块中 de计算机视觉深度学习人工智能图像处理Kornia 深度估计 API 增强depth_from_disparity 正式接受 Python 整数与标量张量基线/焦距参数Kornia 深度估计 API 增强 depth_from_disparity 正式接受 Python 整数与标量张量基线/焦距参数 本篇技术指南聚焦 Kor计算机视觉深度学习人工智能图像处理EMQX MQTT Connector 的 static_clientids 增强为每个 ClientID 配置独立用户名与密码EMQX MQTT Connector 的 static_clientids 增强为每个 ClientID 配置独立用户名与密码 导读 在 EMQX 5.10后端物联网消息队列通信上一篇Vant 4 Picker 选择器完整指南从基础用法到级联选择与源码原理下一篇在 Refine v5 中实现 MUI 的 Multipart 文件上传基于 React Hook Form 的完整实践指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考