首页 / 资讯中心 / 文章详情

kornia 立体视觉指标实战:用 kitti_d1_error 复现 KITTI 2015 官方评测口径

kornia 立体视觉指标实战:用 kitti_d1_error 复现 KITTI 2015 官方评测口径 ★ FEATURED ARTICLE
计算机视觉深度学习人工智能图像处理【免费下载链接】kornia 空间人工智能的几何计算机视觉库项目地址https://gitcode.com/kornia/kornia点击查看免费下载导读KITTI 2015 立体匹配基准stereo benchmark的排行榜只认一个数字——D1 异常点比率outlier ratio它与常见的坏点率bad pixel ratio有着本质区别一个像素只有当绝对误差与相对误差同时超限时才被计入异常。kornia 在kornia.metrics模块中新增了kitti_d1_error把 KITTI devkit 的官方判定逻辑evaluate_scene_flow.cpp以可微 Tensor API 的形式移植进 PyTorch 生态。读完本文你将掌握 D1 的数学定义与判定边界、kitti_d1_error的完整参数语义阈值、valid_mask、reduction、它和mean_bad_pixel_error的取舍差异以及如何在自己的立体匹配模型上按 KITTI 官方口径计算可复现的评测分数。一、KITTI D1 是什么从基准定义到开源实现kitti_d1_error于 2024 年通过 PR #3931 合入 kornia对应 changelog.d/3931.added.md其定位在 changelog 中写得很清楚the outlier ratio reported by the KITTI 2015 stereo benchmark——即 KITTI 2015 立体基准上报的异常点比率论文出处为 M. Menze 与 A. Geiger 的Object Scene Flow for Autonomous VehiclesCVPR 2015。在 KITTI 2015 的官方评测脚本中异常点的判定谓词是这样的测试注释中给出了 devkit 的对应位置evaluate_scene_flow.cpp:13-14,51d_err fabs(d_gt - d_est) 3.0 fabs(d_gt - d_est) / fabs(d_gt) 0.05一个像素要成为异常点必须同时满足两个严格不等式绝对视差误差大于绝对阈值abs_threshold默认 3.0 像素相对视差误差大于相对阈值rel_threshold默认 0.05即 5%且分母是真实视差ground truth的绝对值而非预测值。这就是 changelog 中强调的那句That conjunction is what separates it frommean_bad_pixel_error, which applies the absolute criterion aloneKITTI 的 D1 在纯绝对判据之上叠加了相对判据。二、数学定义与实现剖析在 kornia/metrics/disparity.py 中kitti_d1_error的 docstring 给出了完整公式。给定预测视差图 $D$ 与真实视差图 $D^{gt}$以及有效像素集合 $\mathcal{V}$$$\text{D1}(D, D^{gt}) \frac{1}{|\mathcal{V}|}\sum_{p \in \mathcal{V}}\left[|D_{p} - D^{gt}{p}| \tau{abs} ;\wedge; \frac{|D_{p} - D^{gt}{p}|}{|D^{gt}{p}|} \tau_{rel}\right]$$结果是一个落在 $[0, 1]$ 区间内的分数fraction不是百分数。核心实现只有三行见 disparity.pymask _check_disparity_inputs(input, target, valid_mask) error (input - target).abs() outlier ((error abs_threshold) (error / target.abs() rel_threshold)).to( torch.promote_types(input.dtype, target.dtype) ) return _reduce_disparity_error(outlier, mask, reduction)值得注意的实现细节相对误差分母取绝对值error / target.abs()与 devkit 中的fabs(d_gt)完全对应。若分母不取绝对值负真实视差会导致比值为负永远不会超过阈值结果将与官方评测不一致测试用例negative-gt专门钉死了这一行为。与运算短路 NaN两个判据用连接任何与 NaN 的比较都为假因此 NaN 会被计入 inlier详见下文边界行为。指标张量无梯度这是一个由比较构造的指示indicator指标输出不携带requires_grad不能直接当 loss 用——这是文档明确记载的设计约束。三、API 全参数详解kitti_d1_error的函数签名如下与模块中其他三个视差指标保持完全一致的约定kitti_d1_error( input: torch.Tensor, # 预测视差图任意形状 (*) target: torch.Tensor, # 真实视差图形状须与 input 相同 abs_threshold: float 3.0, # 绝对误差阈值像素 rel_threshold: float 0.05, # 相对误差阈值比例 valid_mask: Optional[torch.Tensor] None, # 可广播到 input 的布尔/数值掩码 reduction: str mean, # none | mean | sum ) - torch.Tensor3.1 参数语义与取值建议参数默认值含义说明input—预测视差图任意形状(*)须为浮点 dtypetarget—真实视差图与input同形状须为浮点 dtypeabs_threshold3.0绝对视差误差上限KITTI 官方固定为 3 像素两判据均为严格大于等于阈值不算异常rel_threshold0.05相对视差误差上限KITTI 官方固定为 5%相对误差以fabs(d_gt)为分母valid_maskNone参与统计的像素掩码非布尔掩码会自动转布尔须可广播到input形状None表示评估全部像素reductionmean归约方式mean在所有有效像素上取平均sum返回异常点个数none返回逐像素异常图被掩码位置置零3.2 reduction 的三种返回语义reductionmean有效像素中的异常点比例标量。若valid_mask未选中任何像素返回nan。reductionsum有效像素中的异常点数量标量。reductionnone逐像素异常图形状与input一致被掩码剔除的位置置零而非填充其他占位值这一约定同时保证了torch.compile下输出形状的静态性见 disparity.py 中的实现注释。3.3 快速上手示例先看 docstring 中自带的 doctest 示例disparity.pyimport torch import kornia input torch.tensor([1.0, 5.0, 104.0, 20.0]) # 预测视差 target torch.tensor([1.0, 1.0, 100.0, 10.0]) # 真实视差 kornia.metrics.kitti_d1_error(input, target) # tensor(0.5000)逐项拆解这个结果四个像素的绝对误差为[0.0, 4.0, 4.0, 10.0]相对误差为[0.0, 4.0, 0.04, 1.0]。绝对阈值 3 判定为[F, T, T, T]相对阈值 0.05 判定为[F, T, F, T]两者取与后异常点为[0, 1, 0, 1]比例恰为 0.5。带掩码的典型评测写法pred torch.rand(2, 1, 4, 5) * 100.0 # 批量预测视差 (B, 1, H, W) gt torch.rand(2, 1, 4, 5) * 100.0 # 批量真实视差 # KITTI 的 valid mask 标记了有真实标注的像素 valid (gt 0) (gt 256) score kornia.metrics.kitti_d1_error(pred, gt, valid_maskvalid) print(fD1 {score.item():.4f}) # 输出 [0, 1] 区间内的分数四、与 mean_bad_pixel_error 的本质差异mean_bad_pixel_error对应 Middlebury 基准的坏点率口径只应用绝对判据|D_p - D_gt_p| threshold见 disparity.py。它的 docstring 明确警告It isnotthe number KITTI reports: that benchmark uses D1。两者在真实场景中的分歧可以用测试中的对照用例tests/metrics/test_disparity.py说明# 场景一大视差上的小误差 —— 绝对超限、相对不超限 input torch.tensor([104.0]); target torch.tensor([100.0]) kornia.metrics.kitti_d1_error(input, target) # tensor(0.0) —— D1 不认为是异常 kornia.metrics.mean_bad_pixel_error(input, target) # tensor(1.0) —— 坏点率认为是坏点 # 场景二小视差上的大相对误差 —— 相对超限、绝对不超限 input torch.tensor([12.0]); target torch.tensor([10.0]) kornia.metrics.kitti_d1_error(input, target) # tensor(0.0) —— 两个判据都不单独定罪这正是 changelog 所强调的设计动机the additional relative criterion keeps large disparities from being penalised for errors that are small compared to their magnitude——对视差为 100 像素的近处物体4 像素误差在相对意义下微不足道KITTI 认为它合格而mean_bad_pixel_error会把它计为坏点。反之mean_bad_pixel_error对远景小视差上相对误差巨大但绝对误差很小的预测同样显得过于宽松D1 的双判据取与则要求两类错误都成立才定罪。五、必须掌握的边界行为5.1 整数视差图一律拒绝Breaking ChangeKITTI 官方以uint16PNG 存储视差图直接用torch.from_numpy(imread(...))读出来就是整数张量。而kitti_d1_error的归约在float32中累加后会再转回输入 dtype——对整数图而言0.5 这样的比例会被截断成 0产生看起来合理但完全错误的分数。因此_check_disparity_inputs对非浮点输入直接抛出 kornia 错误disparity.py错误信息会指明两个实际 dtypekitti_d1_error(torch.tensor([10, 20]), torch.tensor([10, 10])) # kornia error: Disparity maps must have a floating point dtype. # Got: torch.int64 and torch.int64. Convert them first, # for example with .float().这一行为是 #3931 的 breaking change正式记录在 changelog.d/3931.breaking.md 中此前reductionsum和reductionnone在整数图上会悄悄返回被截断的结果。正确姿势是在调用前统一.float()转换。5.2 零真实视差与 NaN零真实视差相对误差的分母为 0比值非有限。但由于两个判据必须同时成立此类像素退化为仅由绝对阈值判定输出保持有限test_zero_target_disparity验证了输出torch.isfinite全真。不过 KITTI 官方将零视差像素标记为 invalid推荐显式传入valid_mask剔除。NaN 输入任何与 NaN 的比较都为假因此 NaN 像素会被计为 inlier而mean_absolute_disparity_error会直接传播 NaN。文档明确建议不要依赖任何一种默认行为用valid_mask显式掩掉非有限像素。5.3 边界判定的两个陷阱测试test_convention_boundary_cases钉死了 D1 最容易写错的两处细节tests/metrics/test_disparity.py两个比较都是严格的误差恰好等于阈值如 3.0 像素、5% 相对误差不算异常——(10, 13)误差 3.0 判 0(100, 105)相对误差 0.05 判 0。把任一比较改成非严格都会翻转这两个用例。相对误差的分母是真实值而非预测值(78, 82)这一对除以真实值得4/78 0.05128除以预测值得4/82 0.04878恰好横跨 0.05 阈值换分母结果即翻转。5.4 半精度输入的精度保护_reduce_disparity_error对float16/bfloat16输入统一在float32中累加后再转回输入 dtypedisparity.py。原因很实际float16累加和超过 65504 会饱和成inf图像尺寸的视差图必然触发bfloat16在 10 万项求和时也会损失约 0.5% 精度。这一修复记录在 changelog.d/3931.fixed.md 中。代价是reductionsum在float16下总数超过 65504 仍会饱和文档建议此时改用reductionnone并在更宽 dtype 中自行求和。六、批次统计语义Pooling 而非逐图平均这是 D1 与常见实现最容易踩的坑也是 changelog 明确指出的要点A batch is pooled over every valid pixel, as the devkit accumulates it, rather than averaged per image.kornia 的实现把整批所有有效像素拼成一个池子每个有效像素等权贡献一个全局比例——这正是 KITTI devkit 的累加方式和排行榜的统计口径。它与先逐图算 D1 再取平均并不等价当批内各图的有效像素数不同时两种算法结果必然不同。例如测试test_valid_mask中掩码[True, True, True, False]下有效像素为 3 个、其中 1 个异常mean 归约结果为1/3 ≈ 0.3333而不是 4 像素下的 0.5。因此在 batch 评测时务必保持与官方一致的 pooling 语义不要自行逐图平均。七、测试与官方一致性验证kitti_d1_error的正确性在 tests/metrics/test_disparity.py 的TestKittiD1Error中得到了系统验证覆盖devkit 谓词逐字对照测试注释直接引用了evaluate_scene_flow.cpp:13-14,51的谓词并用(10,13)、(100,105)、(78,82)、(-100,-90)四组数值精确复现官方判定双判据独立性test_absolute_criterion_alone_is_not_an_outlier与test_relative_criterion_alone_is_not_an_outlier分别证明单判据不成立时不算异常阈值可调性调低rel_threshold到 0.01 使 4% 相对误差变成异常再调高abs_threshold到 5.0 又将其排除test_thresholdsmask 与 reduction 组合、零视差、dtype 混合提升float32×float64返回float64、torch.compileDynamo兼容性test_dynamo等。与同一模块的另外三个指标mean_absolute_disparity_error、root_mean_squared_disparity_error、mean_bad_pixel_error一起kitti_d1_error已纳入kornia.metrics的公共 API 导出见 kornia/metrics/init.py并在 docs/source/metrics.stereo.rst 中通过 autodoc 生成 API 文档。mean_bad_pixel_error的 docstring 也以交叉引用See :func:kitti_d1_error引导用户区分两种口径。八、实践建议把 D1 接入你的评测管线数据侧从 KITTI 读取的uint16视差图务必先.float()再传入用官方提供的 valid mask或自行构造gt 0的掩码剔除无标注像素。评测侧保持默认阈值abs_threshold3.0, rel_threshold0.05与官方一致reductionmean的批 pooling 语义就是排行榜口径不要再做逐图平均。报告侧D1 输出是 $[0, 1]$ 分数如需百分数自行乘以 100并在论文/报告中注明使用的是 KITTI 2015 官方口径。训练侧D1 是指示指标、无梯度不能作为损失函数训练仍建议使用可微的平滑损失如 MAE/RMSED1 仅用于离线评测对齐排行榜。赞分享计算机视觉深度学习人工智能图像处理【免费下载链接】kornia 空间人工智能的几何计算机视觉库项目地址https://gitcode.com/kornia/kornia点击查看免费下载相关推荐使用 Kornia 的 kitti_d1_error 复现 KITTI 2015 立体匹配基准的 D1 离群点指标使用 Kornia 的 kitti_d1_error 复现 KITTI 2015 立体匹配基准的 D1 离群点指标 KITTI 2015 立体匹配基准用 D1计算机视觉人工智能深度学习图像处理Kornia 立体视觉评估指南disparity 视差图四大误差指标MAE / RMSE / 坏点率 / KITTI D1的公式、参数与源码实现Kornia 立体视觉评估指南disparity 视差图四大误差指标MAE / RMSE / 坏点率 / KITTI D1的公式、参数与源码实现 本指南围计算机视觉深度学习人工智能图像处理Kornia 立体匹配评估指标迁移指南整型视差图的类型校验与 KITTI D1 误差实现Kornia 立体匹配评估指标迁移指南整型视差图的类型校验与 KITTI D1 误差实现 导读 本文聚焦 Kornia 立体匹配评估 API 的一处 破坏性变计算机视觉人工智能深度学习图像处理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站