尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Kornia nms2d 支持非方形 kernel_size:一次 NMS 邻域核构造修复的源码级解析
计算机视觉深度学习图像处理【免费下载链接】kornia Geometric Computer Vision Library for Spatial AI项目地址https://gitcode.com/GitHub_Trending/ko/kornia点击查看免费下载本篇技术指南围绕 Kornia 中nms2d2D 非极大值抑制修复展开该函数此前仅能接受方形kernel_size如(3, 3)、(5, 5)一旦传入(11, 5)这类非方形窗口就会抛出RuntimeError: shape [1, 1, -1, H, W] is invalid for input of size ...。修复后nms2d可正确接受任意非方形kernel_size。读完本文你将理解该错误的根因邻域核两维度被交换、padding 应用到错误的边、修复后的通用路径实现原理、边界语义约定以及如何用测试用例验证修复的正确性。背景nms2d 在 Kornia 中的角色nms2d是 Kornia 空间几何子包 kornia/geometry/subpix/ 中的核心函数用于把稠密的响应图response map转化为稀疏的局部极大值候选点。它的典型调用方式是把角点/关键点的响应图输入进去仅保留那些在kernel_size窗口内严格大于所有邻居的位置其余位置置零或返回布尔掩码。在 Kornia 的局部特征检测流水线中nms2d被广泛使用例如kornia/feature/disk/detector.py 中对 heatmap 做 NMS 提取关键点kornia/feature/aliked/aliked.py 中对检测分数做 NMSkornia/feature/xfeat.py 中nms2d(x, (kernel_size, kernel_size), mask_onlyTrue) (x threshold)组合掩码与阈值筛选。这些内部调用大多使用方形窗口(window_size, window_size)但 API 层面kernel_size的类型签名是tuple[int, int]并没有强制要求两个维度相等——这正是 bug 的伏笔。问题现象非方形窗口触发view形状错误修复前向nms2d传入非方形kernel_size例如(11, 5)会直接抛错RuntimeError: shape [1, 1, -1, H, W] is invalid for input of size ...这个错误信息中的[1, 1, -1, H, W]揭示了问题本质内部实现把邻域窗口的卷积核 reshape 时两个 spatial 维度被交换即H、W位置上出现了-1这种无法推断的维度同时 padding 被应用到了错误的边对edge pair上导致卷积输出的空间尺寸与后续view期望的尺寸对不上。该问题由 #4240 记录并提出#4242 完成修复。这是 Kornia 变更日志体系changelog.d/migration-082.fixed.md中记录的众多修复之一同类问题还出现在 3D 版本[nms3d曾对除(3, 3, 3)外的所有核尺寸抛错见 #4241相关测试注释记录于 tests/geometry/subpix/test_nms.py。根因分析卷积核两维交换与 padding 错边旧实现基于卷积convolution padding 构造邻域比较。它先创建一个形状为(k_y * k_x, 1, k_y, k_x)的核再对输入做 padding 后卷积。代码层面存在两个叠加的缺陷两个 extents 被交换核的构建过程中把k_y和k_x弄反导致卷积核的宽高与预期相反padding 应用到了错误的边padding 本应按(k_y - 1) // 2上下和(k_x - 1) // 2左右分别施加却被打到了错误的维度组合上。当k_y k_x方形窗口时这两个缺陷恰好相互掩盖、不产生可见影响一旦传入非方形窗口交换后的核尺寸与 padding 后的输入无法匹配卷积输出形状错误随后的view便抛出文章开头那条shape [1, 1, -1, H, W] is invalid的RuntimeError。这条根因线索也直接写进了测试注释中tests/geometry/subpix/test_nms.py 的test_non_square_kernel_size明确说明非方形窗口过去会因卷积核两维交换、padding 应用到错误边而在内部view处抛错#4240。修复后的实现无 padding 的通用路径修复后的实现位于 kornia/geometry/subpix/nms.py彻底抛弃了卷积 padding方案改为分区 max-pooling 累加的通用路径general path从而天然支持任意(k_y, k_x)组合。核心有三块1. 邻域范围拆分_split_windowkornia/geometry/subpix/nms.py#L27-L30 的_split_window把长度为k的窗口沿中心拆成中心前before和中心后after两个范围def _split_window(k: int) - Tuple[int, int]: Return the neighbour extents of a length-k window either side of its centre. before (k - 1) // 2 return before, k - before - 1例如k 5返回(2, 2)k 11返回(5, 5)。它统一了奇数/偶数窗口的中心定义并且不依赖卷积核形状因此对(11, 5)、(5, 11)、(13, 9)等任意组合都成立。2. 邻域最大值计算_neighbourhood_max2dkornia/geometry/subpix/nms.py#L41-L68 的_neighbourhood_max2d计算每个k_y x k_x窗口内、排除中心后的最大值。它把窗口去掉中心后划分为四个矩形区域中心行上方、中心行下方、中心行左/右侧分别用F.max_pool2d归约再通过torch.maximum逐对合并见_reduce_max。由于两个全宽条带共享一次(1, kx)的列向池化每个位置的代价是O(k_y k_x)次访问而不是朴素的k_y * k_x - 1次——即便支持任意核尺寸性能依然可控。3. 边界语义窗口放不下的位置不是极大值通用路径 kornia/geometry/subpix/nms.py#L277-L288 中没有任何 paddingelse: # General path: the same rule as the explicit paths above, for any window size. A # position whose full window does not fit inside the image is not a maximum -- it has # not been compared against the neighbours that would decide it -- so the border strip # stays False and only the interior is computed (#4239). ky, kx self.kernel_size cy, by _split_window(ky) cx, bx _split_window(kx) mask torch.zeros(B, CH, H, W, devicex.device, dtypetorch.bool) if H ky and W kx: centre x[..., cy : H - by, cx : W - bx] mask[..., cy : H - by, cx : W - bx] centre _neighbourhood_max2d(x, ky, kx)这里确立了一条统一的边界约定#4239位于距边界(k - 1) // 2以内的位置永远不是极大值因为它的完整窗口放不进图像、无法与所有邻居比较。(3, 3)、(5, 5)、(7, 7)三条手写快速路径一直遵循此约定修复后通用路径也与之保持一致。函数入口与模块/函数式 API 的一致性nms2d函数式入口定义于 kornia/geometry/subpix/nms.py#L390-L395本质是NonMaximaSuppression2d模块的一行包装def nms2d(input: torch.Tensor, kernel_size: tuple[int, int], mask_only: bool False) - torch.Tensor: rApply non maxima suppression to filter. See :class:~kornia.geometry.subpix.NonMaximaSuppression2d for details. return NonMaximaSuppression2d(kernel_size)(input, mask_only)NonMaximaSuppression2d模块nms.py#L103-L292支持两个参数kernel_size: tuple[int, int]邻域窗口大小构造时校验必须是长度为 2 的 tupleforward(x, mask_onlyFalse)输入形状(B, C, H, W)mask_onlyTrue时返回布尔极大值掩码否则返回非极大值置零后的响应图。此外该模块重写了_load_from_state_dictnms.py#L117-L133把旧卷积实现遗留的kernel持久化 buffer 从 state_dict 中弹出保证旧版本保存的 checkpoint 在strictTrue下仍能加载——这一点由测试test_loads_legacy_kernel_state_dict_strictlytests/geometry/subpix/test_nms.py覆盖。测试验证参考实现与参数化回归修复正确性由一套从定义出发、与实现零共享结构的参考实现兜底。tests/geometry/subpix/test_nms.py#L28-L54 的_reference_nms_mask通过平移整块视图、torch.maximum归约逐定义写出严格大于窗口内其他所有值的规则再与nms2d输出逐元素对比。针对本次修复的关键回归测试是test_non_square_kernel_sizetests/geometry/subpix/test_nms.py#L233-L243pytest.mark.parametrize(kernel_size, [(11, 5), (5, 11), (13, 9)]) def test_non_square_kernel_size(self, device, dtype, kernel_size): # A non-square window used to raise out of an internal view, because the conv kernel was # built with its two extents swapped and the padding was applied to the wrong pair of # edges (#4240). torch.manual_seed(0) inp (torch.rand(1, 2, 29, 31, devicedevice) * 4).to(dtype) self.assert_close( kornia.geometry.subpix.nms2d(inp, kernel_size, mask_onlyTrue).to(dtype), _reference_nms_mask(inp, kernel_size).to(dtype), )它同时覆盖了高度大于宽度(11, 5)、宽度大于高度(5, 11)和非对称奇数(13, 9)三种情况并与参考实现做全量比对。配套的还有一组行为契约测试共同锁定 NMS 语义测试tests/geometry/subpix/test_nms.py验证的行为test_matches_the_reference_ruleL196-L206(3,3)/(5,5)/(7,7)快速路径与通用路径对同一输入结果一致参数化到(4,4)、(15,15)等test_a_plateau_holds_no_strict_maximumL208-L218抑制是严格的相邻等值互相杀死整块平台不产生极大值test_the_border_strip_is_never_a_maximumL220-L231距边界(k-1)//2内的峰值不被报告test_unit_window_suppresses_nothingL245-L256(1, 1)窗口无邻居输入原样返回浮点与整型均验证test_window_larger_than_the_input_finds_no_maximaL258-L260窗口大于输入时不产生任何极大值test_module_and_functional_agreeL262-L266模块式与函数式 API 输出一致test_gradcheck_general_pathL276-L278通用路径(9, 9)可微通过梯度校验实战用法1. 非方形 NMS保留横向/纵向不同的抑制半径在特征检测中如果希望沿水平方向抑制得更宽、沿垂直方向抑制得更窄例如检测拉长的结构现在可以直接传入非方形窗口import torch from kornia.geometry.subpix import nms2d, NonMaximaSuppression2d # 响应图: (B, C, H, W) scores torch.rand(1, 1, 32, 32) # 函数式 API水平半径 5、垂直半径 2 的非方形窗口 mask nms2d(scores, (11, 5), mask_onlyTrue) print(mask.dtype, mask.shape) # torch.bool, torch.Size([1, 1, 32, 32]) # 模块式 API同样的窗口返回抑制后的响应图 nms NonMaximaSuppression2d((11, 5)) suppressed nms(scores) # 非极大值位置被置零2. 与阈值筛选组合XFeat 风格参考 kornia/feature/xfeat.py#L346 的写法把 NMS 掩码与置信度阈值取交集得到最终稀疏关键点位置mask nms2d(scores, (7, 7), mask_onlyTrue) (scores 0.5) ys, xs torch.nonzero(mask, as_tupleFalse).unbind(1) # 注意去掉 batch/channel 维度3. 模型加载兼容性若你保存过旧版本 Kornia 训练的包含NonMaximaSuppression2d的模型如嵌入在ScaleSpaceDetector中见 kornia/feature/scale_space_detector.py#L765升级后无需重新保存_load_from_state_dict会静默接受旧的kernelbufferstrictTrue加载不会报unexpected key。小结本次nms2d修复changelog.d/migration-082.fixed.md#4240/#4242从根上消除了卷积核两维交换 padding 错边这一对仅在非方形窗口下暴露的缺陷用_split_window_neighbourhood_max2d的无 padding 通用路径取代了卷积实现同时把边界条带永不判极值的语义在快速路径与通用路径之间统一#4239。配套的参数化回归测试(11, 5)、(5, 11)、(13, 9)保证了修复与参考定义严格一致。如今nms2d的kernel_size参数名副其实地支持任意二维窗口为检测各向异性结构的关键点提供了更自由的抑制半径选择。相关实现与测试可直接在 kornia/geometry/subpix/nms.py 与 tests/geometry/subpix/test_nms.py 中查阅API 文档见 docs/source/geometry.subpix.rst。赞分享计算机视觉深度学习图像处理【免费下载链接】kornia Geometric Computer Vision Library for Spatial AI项目地址https://gitcode.com/GitHub_Trending/ko/kornia点击查看免费下载相关推荐Kornia nms2d 非正方形窗口支持内核维度错误与 Padding 错位问题的修复详解Kornia nms2d 非正方形窗口支持内核维度错误与 Padding 错位问题的修复详解 导读 本指南围绕 Kornia 变更日志条目 changelog人工智能计算机视觉深度学习图像处理Kornia NMS 边界规则统一nms2d/nms3d 在不同窗口尺寸下的一致性迁移指南Kornia NMS 边界规则统一 nms2d / nms3d 在不同窗口尺寸下的一致性迁移指南 本文是 Kornia 迁移清单 changelog.d/计算机视觉深度学习图像处理Kornia NMS 单元窗口语义修正nms2d(x, (1, 1)) 与 nms3d(x, (1, 1, 1)) 破坏性变更深度解析Kornia NMS 单元窗口语义修正 nms2d x, 1, 1 与 nms3d x, 1, 1, 1 破坏性变更深度解析 本篇技术指南围绕 Kornia计算机视觉深度学习图像处理上一篇PaddleNLP SKEP 模型汇总与实战指南预训练权重、配置详解与下游任务使用下一篇Kornia LAF 补丁提取的 CPU 半精度采样修复float32 回退与批处理 grid_sample 优化解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

Kornia 颜色空间转换的 TorchScript 兼容性修复:从 PEP 604 联合类型到 `Optional[torch.Tensor]`

Kornia 颜色空间转换的 TorchScript 兼容性修复:从 PEP 604 联合类型到 `Optional[torch.Tensor]`

计算机视觉深度学习图像处理 【免费下载链接】kornia 🐍 Geometric Computer Vision Library for Spatial AI 项目地址: https://gitcode.com/GitHub_Trending/ko/kornia 点击查看 免费下载 本文基于 changelog.d/migration-122.fixed.md 记录的迁移修复…

📅 2026/11/2 11:04:13
PaperOrchestra Outline Agent工作原理:1次LLM调用如何生成驱动全局的outline.json

PaperOrchestra Outline Agent工作原理:1次LLM调用如何生成驱动全局的outline.json

【免费下载链接】PaperOrchestra An automated AI research-paper writer based off Googles PaperOrchestra papers implementation through a skills - benchmark autoraters using any coding agent (Claude Code, Cursor, Antigravity, Cline, Aider). No API keys, no LL…

📅 2026/11/2 10:59:12
【RHCA+】glances命令(监控系统资源)

【RHCA+】glances命令(监控系统资源)

“ 目录:RHCA -> 12 系统监控 -> 8 glances命令(监控系统资源) ”查看CPU、内存、网络、磁盘、进程等监控信息,类似top;语法格式:glances参数作用-w启动网页模式,会同时开启网页和api&…

📅 2026/11/2 10:59:12
MORE NEWS

更多资讯

📰

AWS云安全五层自动化地图:从最小权限到自动响应的实战复习指南

简介:面向云上架构师、运维与安全工程师的AWS安全实践参考文档,围绕身份与访问管理、数据保护、网络安全、基础设施安全、日志监控五大维度展开,帮助读者在真实项目中落地最小权限、纵深防御与零信任思路。包内为1个PDF文件,约15.…

📰

C++逆向工程核心技术解析与实战应用

1. 项目概述"重楼C逆向四期"是一个专注于C逆向工程技术的进阶培训项目。作为系列课程的第四期,它延续了前三期的核心技术体系,同时针对当前行业需求新增了多项实用内容。逆向工程在安全研究、漏洞分析、软件调试等领域具有不可替代的价值&…

📰

OpenCV透视变换实战:从原理到避坑,文档矫正与车牌识别预处理

图像透视变换这个主题,我在实际项目里踩过的坑比想象中多得多。很多人第一次接触它,以为调个getPerspectiveTransform加warpPerspective就完事了,结果跑出来要么图像扭曲得不成样子,要么边缘全是黑边,要么四个角点顺序…

📰

IL与C#底层差异及实用分析技巧

1. IL与C#的底层探索视角差异 当我们谈论IL(Intermediate Language,中间语言)时,实际上是在讨论.NET平台代码编译后的底层表示形式。作为在.NET生态深耕多年的开发者,我发现很多同行对IL存在两种极端认知:要…

📰

数独验证算法:一次遍历实现高效合规检查

1. 项目概述:手搓有效的数独验证器 这道力扣原题《有效的数独游戏》是算法练习中的经典题型,编号为36题。题目要求我们验证一个9x9的数独棋盘是否符合规则,而不需要关心它是否有解。作为力扣热题100中的一员,它经常出现在算法面试…

📰

API与SDK的区别:从概念到实践,彻底搞懂接口与工具包

身边不少刚入行的朋友,甚至一些做了两三年业务开发的同学,聊起 API 和 SDK 这两个词,表情都挺微妙——说不知道吧,天天在用;说知道吧,让他用一句话讲清楚区别,往往就开始"就是那个……接口…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬