Kornia 修复 MPS 边界补丁提取暗化问题:`grid_sample` 边框填充的像素中心钳制原理
Kornia 修复 MPS 边界补丁提取暗化问题grid_sample边框填充的像素中心钳制原理【免费下载链接】kornia Geometric Computer Vision Library for Spatial AI项目地址: https://gitcode.com/gh_mirrors/ko/kornia本篇文章围绕 Kornia changelog 条目 changelog.d/migration-126.fixed.mdissue #4063展开详细讲解补丁提取patch extraction在 Apple MPSMetal Performance Shaders后端上遇到图像边界时输出被暗化的根因、修复方案及其对下游描述子descriptor的影响。读完本文你将理解torch.nn.functional.grid_sample在align_cornersFalse下的归一化坐标语义掌握用零填充 钳制网格精确模拟padding_modeborder的通用技巧并能看懂 Kornia 中extract_patches_simple与extract_patches_from_pyramid的底层实现与对应测试。背景LAF 与补丁提取在局部特征local features流程中Kornia 用 LAFLocal Affine Frame形状为(B, N, 2, 3)描述每个关键点的仿射区域并从图像中裁出对应的方形补丁再交给 SIFT、HardNet 等描述子网络。这一环节的两个核心函数都位于 kornia/feature/laf.pyextract_patches_simple不做平滑直接按 LAF 定义的仿射网格在单张图上双线性采样速度快但有混叠extract_patches_from_pyramid先对图像做高斯金字塔下采样按 LAF 的尺度选择合适层级采样抗混叠效果更好也是 get_laf_descriptors 的默认路径。两者的采样核心都是F.affine_grid(..., align_cornersFalse)生成网格后调用F.grid_sample。关键点在于当 LAF 靠近甚至越过图像边界时采样网格会落到图像范围之外此时grid_sample的padding_mode决定界外采样返回什么值。问题根因MPS 缺少padding_modeborderpadding_modeborder的含义是界外采样点被钳制到图像边缘像素的值相当于边缘复制。然而 Apple 的 MPS 后端没有实现padding_modeborder。为了让代码在所有设备上行为一致Kornia 在 MPS 上改用padding_modezeros界外返回 0同时手动把采样网格钳制回图像范围内从而模拟边缘复制。问题出在钳制的目标值上。旧实现使用grid.clamp(-1, 1)在align_cornersFalse的坐标系里归一化坐标±1对应的是边界像素的外边缘即像素索引-0.5而不是该像素的中心。此时双线性采样会把边界像素与界外零填充各取一半进行混合于是凡是触及图像边界的 LAF其补丁边缘像素大约只返回真实值的一半——在[0, 1]区间的图像上表现为明显的暗化darkened patches。修复后的实现位于 kornia/feature/laf.py 的_clamp_grid_to_pixel_centersdef _clamp_grid_to_pixel_centers(grid: torch.Tensor, h: int, w: int) - torch.Tensor: x grid[..., 0].clamp(-1.0 1.0 / float(w), 1.0 - 1.0 / float(w)) y grid[..., 1].clamp(-1.0 1.0 / float(h), 1.0 - 1.0 / float(h)) return torch.stack([x, y], dim-1)核心变化钳制上限从±1改为±(1 - 1/size)size 为对应轴的长度。在align_cornersFalse语义下1 - 1/size恰好是最外侧像素的中心。把网格钳到像素中心零填充模式下的双线性采样就只会取到该像素自身的值从而精确复现padding_modeborder。修复如何落地_grid_sample_patches的设备分流钳制逻辑被封装进统一采样入口 _grid_sample_patchesdef _grid_sample_patches(img: torch.Tensor, grid: torch.Tensor, h: int, w: int) - torch.Tensor: if img.device.type mps: return F.grid_sample(img, _clamp_grid_to_pixel_centers(grid, h, w), padding_modezeros, align_cornersFalse) return F.grid_sample(img, grid, padding_modeborder, align_cornersFalse)也就是说CPU / CUDA 后端继续使用原生padding_modeborder不经过钳制分支MPS 后端走像素中心钳制 零填充的模拟路径。正如 changelog 所述CPU 和 CUDA 路径从未进入该分支其行为与修复前逐字节一致byte-identical因此本修复只影响 MPS 用户不存在回归风险。金字塔路径中的同样修正extract_patches_from_pyramid使用两级策略小图/大图走打包图集atlas路径将各金字塔层级并排放置并做一格replicate边缘保护在 atlas 路径中层级常量同样以最外层像素中心为钳制界kornia/feature/laf.py-1.0 1.0 / float(w_l), # lo: 该层级最外侧像素中心 -1.0 1.0 / float(h_l), 1.0 - 1.0 / float(w_l), # hi 1.0 - 1.0 / float(h_l),这组lo/hi常量随后被应用到网格重映射grid grid.maximum(lo); grid grid.minimum(hi)见 laf.py保证 MPS 上金字塔采样的边界行为与 CPU 一致。此外kornia/feature/sift/pyramid.py 等 SIFT 内部路径也复用了_grid_sample_patches因此同样受益于该修复。影响面所有基于补丁的描述子补丁是描述子的输入。get_laf_descriptors在 kornia/feature/integrated.py 直接调用extract_patches_from_pyramid(timg, lafs, patch_size)因此修复自动传导到所有基于 LAF 补丁的模块get_laf_descriptors 与封装它的 LAFDescriptorSIFTFeature 等 LocalFeature 组合模块KeyNetAffNetHardNet以及 affine_shape.py、orientation.py 中所有以extract_patches_from_pyramid提取补丁的环节。一句话概括凡是靠近图像边界的关键点其补丁值此前在 MPS 上偏暗描述子随之失真修复后这些补丁与 CPU/CUDA 结果一致。量化验证与测试保障changelog 给出的量化结果针对一张[0, 1]区间图像、补丁跨越图像角落的场景与 CPU 结果的最大偏差从0.395降至2.5e-6后者已接近浮点精度极限修复前有64.7% 的补丁像素偏差超过1e-3修复后全部回到1e-3以内。这些结论有对应测试钉住防止回归见 tests/feature/test_laf.py 的TestClampGridToPixelCenterstest_matches_border_padding将钳制到像素中心 零填充与 CPU 上原生padding_modeborder的结果做assert_close对比test_naive_clamp_is_not_equivalent显式断言旧的grid.clamp(-1, 1)与 border 参考结果偏差大于1e-3——这正是本 bug 的回归护栏test_extractors_match_cpu_at_the_border参数化覆盖extract_patches_simple与extract_patches_from_pyramid用跨越图像角落的 LAF 验证补丁不依赖设备。测试文件还通过_corner_border_laf构造旋转 LAF让补丁同时越出两个边确保测试真正命中边界分支见 test_laf.py。经验总结本次修复对使用 Kornia 的 MPS 开发者是一个重要提醒padding_modeborder并非所有后端都支持跨设备代码需要显式模拟align_cornersFalse下±1不是像素中心而是边界像素外边缘任何手工钳制网格的代码都应钳到±(1 - 1/size)补丁提取是特征流程的地基边界上的像素级偏差会通过描述子放大影响匹配质量本修复让 MPS 上的局部特征流程与 CPU/CUDA 严格对齐。如果你正在 MPS 上使用extract_patches_simple、extract_patches_from_pyramid、LAFDescriptor、SIFTFeature或KeyNetAffNetHardNet升级到包含本次修复issue #4063的版本即可消除边界补丁暗化问题无需改动任何调用代码。【免费下载链接】kornia Geometric Computer Vision Library for Spatial AI项目地址: https://gitcode.com/gh_mirrors/ko/kornia创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考