Kornia RandomBoxBlur 的normalized参数语义修复从文档误导到关键字传递的实现细节【免费下载链接】kornia Geometric Computer Vision Library for Spatial AI项目地址: https://gitcode.com/GitHub_Trending/ko/kornia导读本文围绕 Kornia 仓库中一条 changelog 修复记录changelog.d/migration-005.fixed.md对应 PR #4433 / #4486展开剖析RandomBoxBlur增强算子中normalized参数的语义问题它曾被文档描述为L1 归一化开关实际却被按位置转发给kornia.filters.box_blur的separable参数。读者读完本文将理解normalized的真实含义是选择可分卷积还是单次 2D 卷积实现为什么两种设置下输出都是窗口均值而非和以及修复后border_type与separable改为关键字传递为何不改变任何输出。一、问题背景一条修复类变更记录Kornia 使用 Towncrier 管理变更日志每个带来用户可见变化的 PR 在 changelog.d/ 目录下添加一个 Markdown 片段文件命名规则为PR.type.md其中fixed类型对应Bug fixes参见 changelog.d/README.md。本文主角migration-005.fixed.md属于迁移期间保留的历史记录它记录的是一个典型的文档与实现不一致 参数按位置错误转发问题RandomBoxBlursnormalizedargument is documented as what it does. It was described as if True, L1 norm of the kernel is set to 1, but it was forwarded positionally intokornia.filters.box_blursseparableparameter... The call now passesborder_typeandseparableby keyword; outputs are unchanged.一句话概括修复内容把normalized的文档改写成它真实的语义选择可分/单趟实现并把border_type、separable改为按关键字传参——这两件事都不改变任何计算结果。二、底层函数kornia.filters.box_blur的真实签名要理解这个 bug先看被调用的底层函数。kornia.filters.box_blur定义在 kornia/filters/blur.pydef box_blur( input: torch.Tensor, kernel_size: tuple[int, int] | int, border_type: str reflect, separable: bool True ) - torch.Tensor:它接受四个参数输入张量(B, C, H, W)、核大小、边界填充方式默认reflect以及separable默认True。关键点在于该函数中并不存在名为normalized的参数也没有任何是否做 L1 归一化的开关。separable的语义在 docstring 中写得很清楚——use two one-dimensional passes (the default), reducing work for larger kernels即选择实现路径而非归一化方式。从实现看kornia/filters/blur.py两条路径分别是if separable: ky, kx _unpack_2d_ks(kernel_size) kernel_y get_box_kernel1d(ky, deviceinput.device, dtypeinput.dtype) kernel_x get_box_kernel1d(kx, deviceinput.device, dtypeinput.dtype) out filter2d_separable(input, kernel_x, kernel_y, border_type) else: kernel get_box_kernel2d(kernel_size, deviceinput.device, dtypeinput.dtype) out filter2d(input, kernel, border_type)separableTrue拆成水平、垂直两次一维卷积filter2d_separableseparableFalse用单个 2D 核做一次卷积filter2d。三、关键证据两条路径都是 L1 归一化的均值为什么说无论normalized取什么值输出都是窗口均值而非和答案在核的构造函数 kornia/filters/kernels.pydef get_box_kernel1d(kernel_size, *, deviceNone, dtypeNone): scale torch.tensor(1.0 / kernel_size, devicedevice, dtypedtype) return scale.expand(1, kernel_size)def get_box_kernel2d(kernel_size, *, deviceNone, dtypeNone): ky, kx _unpack_2d_ks(kernel_size) scale torch.tensor(1.0 / (kx * ky), devicedevice, dtypedtype) return scale.expand(1, ky, kx)一维核的每个元素是1 / kernel_size一维核元素之和恰好为 1二维核的每个元素是1 / (kx * ky)二维核元素之和也恰好为 1。因此separable选择的只是实现路径两条路径使用的核都满足 L1 范数为 1即元素和为 1卷积结果都等于窗口内像素的算术平均。二者唯一可能的差异是浮点舍入误差normalizedFalse走单趟 2D 卷积normalizedTrue走两次 1D 卷积中间多一次舍入。这就是变更记录中 the kernel is L1-normalized either way, sonormalizedFalsereturns window means, not sums 的源码依据。四、Bug 本体RandomBoxBlur的参数按位置转发RandomBoxBlur定义在 kornia/augmentation/_2d/intensity/box_blur.py构造签名L88-L102def __init__( self, kernel_size: Tuple[int, int] (3, 3), border_type: Union[int, str, BorderType] reflect, normalized: bool True, same_on_batch: bool False, p: float 0.5, keepdim: bool False, ) - None:问题出在修复前的apply_transform它把flags[normalized]按位置塞进了box_blur的第三个参数槽。而box_blur的第三个位置参数是border_type、第四个才是separable——更准确地说按旧实现normalized实际上对应到了separable的位置但文档却把它描述为如果为 True则核的 L1 范数设为 1。这种错位带来两个后果语义误导使用者会以为normalizedFalse返回窗口和而实际上无论何种取值都返回窗口均值脆弱的位置传参border_type与separable混在位置参数里一旦底层函数签名调整或调用方想覆盖border_type就极易张冠李戴。修复后的实现kornia/augmentation/_2d/intensity/box_blur.py改为全部关键字传递def apply_transform(self, input, params, flags, transformNone): return box_blur( input, flags[kernel_size], # a per-call border_type override reaches flags unnormalized, so normalize here too border_typeBorderType.get(flags[border_type]).name.lower(), separableflags[normalized], )两处细节值得注意border_type通过BorderType.get(...).name.lower()统一规范化成小写字符串兼容circular、CIRCULAR、整数3、BorderType.CIRCULAR等拼写因为每次调用时覆盖的border_type会以未规范化形式进入flagsnormalized被显式映射为separable关键字参数语义由归一化开关修正为实现路径选择。五、为什么outputs are unchanged数值等价性变更记录特意强调修复不改变输出这有测试直接佐证。在 tests/augmentation/test_augmentation.py 的TestRandomBoxBlur中pytest.mark.parametrize(normalized, [True, False]) def test_normalized_selects_the_separable_path(self, normalized, device, dtype): out RandomBoxBlur((3, 3), normalizednormalized, p1.0)(img.clone()) expected box_blur(img, (3, 3), border_typereflect, separablenormalized) torch.testing.assert_close(out, expected, rtol0.0, atol0.0) pytest.mark.parametrize(normalized, [True, False]) def test_output_is_the_window_mean_for_either_setting(self, normalized, device, dtype): out RandomBoxBlur((3, 3), normalizednormalized, p1.0)(img.clone()) self.assert_close(out[0, 0, 2, 2], img[0, 0, 1:4, 1:4].mean())第一个测试断言RandomBoxBlur(normalizedX)与box_blur(..., separableX)在rtol0, atol0下完全一致——证明normalized就是separable的透传第二个测试断言无论normalized取何值输出像素都等于窗口均值img[0,0,1:4,1:4].mean()——证明返回的是均值而非和。此外还有一组边界测试L5157-L5188验证border_type的各种拼写circular、CIRCULAR、整数3、BorderType.CIRCULAR都能被接受且每次调用时通过forward(**kwargs)覆盖的border_type会被正确执行——这正是关键字传递修复后新覆盖的能力。六、修复后的正确使用方式与参数语义结合修复后的 类文档 与源码RandomBoxBlur各参数的准确语义如下参数默认值准确语义kernel_size(3, 3)核大小(kH, kW)第一项计行、第二项计列偶数尺寸被接受窗口向左上偏移半个像素而不是报错border_typereflect卷积前的填充模式接受大小写不敏感字符串、BorderType成员或其整数值CONSTANT0, REFLECT1, REPLICATE2, CIRCULAR3normalizedTrue选择实现路径而非归一化开关True对应box_blur(..., separableTrue)两次一维卷积False对应单次二维卷积。两者核均为 L1 归一化输出都是窗口均值仅存在浮点舍入差异same_on_batchFalse是否对整批应用相同变换p0.5应用该变换的概率keepdimFalse是否保持输出形状与输入一致实操示例与类文档 doctest 一致见 box_blur.pyimport torch from kornia.augmentation import RandomBoxBlur img torch.ones(1, 1, 24, 24) out RandomBoxBlur((7, 7))(img) out.shape # torch.Size([1, 1, 24, 24]) # 复现同一次变换借助参数状态 input torch.randn(1, 3, 32, 32) aug RandomBoxBlur((7, 7), p1.0) (aug(input) aug(input, paramsaug._params)).all() # tensor(True)两个值得提醒的边界行为来自类文档的 Warning/Convention 块小图上的填充报错默认border_typereflect下若某空间轴长度不超过核在该轴覆盖范围的一半会抛出 torch 原始的RuntimeError关于 padding而非带类名/形状信息的 kornia 错误constant与replicate可正常运行circular在核半径超过该轴时会抛自己的原始 padding 错误跟踪于 #4559输出不做 clamp默认reflect下每个输出值都是输入的加权平均落在输入极值之间constant用零填充会把边界像素向 0 拉正图像低于输入最小值、负图像高于输入最大值。七、同类增强算子的对照为什么只有RandomBoxBlur有此陷阱在 Kornia 的 2D 强度增强家族中RandomGaussianBlurkornia/augmentation/_2d/intensity/gaussian_blur.py与RandomMedianBlurkornia/augmentation/_2d/intensity/median_blur.py都以核大小 边界为主要参数但只有RandomBoxBlur存在normalized这个从box_blur底层半继承过来的历史参数名。它之所以容易引发误解根本原因在于底层函数的参数名是separable描述算法结构而上层增强器的参数名是normalized听起来像数值语义。本次修复的意义正在于消除这层名不副实——文档按真实行为改写调用按关键字显式绑定让RandomBoxBlur与box_blur的参数契约变得清晰、可维护同时通过rtol0, atol0的测试钉死了输出不变的兼容性承诺。八、小结migration-005.fixed.md这条变更记录虽然只有短短几行却浓缩了一个教科书级的 API 修复流程定位文档与实现的不一致normalized被描述为归一化开关、确认底层真实语义box_blur的separable只选实现路径、两条路径都 L1 归一化、用关键字传递消除位置参数隐患、并用零容差测试锁定输出不变。对使用者而言唯一的结论是RandomBoxBlur的normalized从今往后请当作实现路径选择器理解——无论取 True 还是 False得到的都是盒式窗口均值。【免费下载链接】kornia Geometric Computer Vision Library for Spatial AI项目地址: https://gitcode.com/GitHub_Trending/ko/kornia创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
无审查开源模型浪潮:Dolphin Mistral 24B如何重塑企业AI控制权 无审查开源模型浪潮:Dolphin Mistral 24B如何重塑企业AI控制权
导语
当企业还在为ChatGPT的数据隐私和API依赖发愁时,Dolphin Mistral 24B Venice Edition的推出提供了全新选择——这款240亿参数的开源大模型将系统控制权完全交还给企业,标志… · 2026/11/5 10:08:54
Godot Sprite2D 完全指南:纹理显示、精灵图帧动画与图集裁剪 Godot Sprite2D 完全指南:纹理显示、精灵图帧动画与图集裁剪 【免费下载链接】godot-docs Godot Engine official documentation 项目地址: https://gitcode.com/GitHub_Trending/go/godot-docs
Godot 官方文档仓库中 Sprite2D 参考页(classes/cl… · 2026/11/8 11:01:57
nuclei-templates 实战指南:3 步跑通你的第一次漏洞扫描 nuclei-templates 实战指南:3 步跑通你的第一次漏洞扫描 【免费下载链接】nuclei-templates Community curated list of templates for the nuclei engine to find security vulnerabilities. 项目地址: https://gitcode.com/GitHub_Trending/nu/nuclei-templates… · 2026/11/5 8:20:10
电工证怎么考漳州?工地太忙根本没时间复习考试?考前押题帮你搞定 电工证怎么考漳州?工地太忙根本没时间复习考试?考前押题帮你搞定 工地太忙根本没时间复习考试?你不是一个人。漳州地区的电工证考试,是很多建筑工、水利从业者晋升、转岗、合规操作的必备证书。但面对繁重的工作任务,复习时间成了最大的瓶颈。好在有“… · 2026/11/11 11:52:00
叉车工是特种工吗多久拿证别怕考不过白交培训费 叉车工是特种工吗多久拿证别怕考不过白交培训费 怕考不过白交培训费?叉车工是特种工吗?多久拿证?这些问题,很多准备报考特种作业操作证的小伙伴都在问。今天就从一个周口项目现场管理员的角度,带你们全面了解叉车工是否属于特种作业、考试流程、拿证时间… · 2026/11/11 11:52:00
济源公路工程从业者真实经历:电工证仪器仪表是什么,考证避坑全攻略 济源公路工程从业者真实经历:电工证仪器仪表是什么,考证避坑全攻略 你是不是也像我一样,因为要进工地干活,突然被问到“电工证仪器仪表是什么”这个问题?说白了,就是你连电工证都还没拿到,怎么敢说自己懂电?现在工地招人,不看你有没有学历,就看你有… · 2026/11/11 11:52:00
电工证怎么考漳州学历不高怕报不上名内部消息全公开 电工证怎么考漳州学历不高怕报不上名内部消息全公开 你是不是也和我一样,学历不高,但想考个电工证,怕报不上名?别急,这事儿我早就在漳州摸爬滚打过,今天我就把【内部消息】一股脑儿告诉你,看完保你少走弯路。… · 2026/11/11 11:52:00
罗甸电工证培训机构官方报名入口怎么找?证书过期了不知道怎么复审延期 罗甸电工证培训机构官方报名入口怎么找?证书过期了不知道怎么复审延期 证书过期了不知道怎么复审延期,是很多特种作业人员在实际工作中遇到的常见问题。尤其是像低压电工证、高压电工证这类证书,一旦超过有效期,不仅影响日常工作,还可能面临法律风险。现… · 2026/11/11 11:52:00
栾城考电工证在哪里考内部消息曝光,实操考试心里没底怕挂科?看这里 栾城考电工证在哪里考内部消息曝光,实操考试心里没底怕挂科?看这里 实操考试心里没底怕挂科,这几乎是每个准备考电工证的人都会遇到的难题。尤其是在栾城地区,不少人在报考前总担心考试流程、考试内容和考试通过率。如果你正在为“… · 2026/11/11 11:51:00
电工证丢失还能补吗?千万别踩坑,丢了证等于失业 电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/10 2:16:10
电力电缆作业证直播报名入口与办理流程良心建议 电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/10 17:46:39
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/10 17:11:43
_中职电工证最新政策解读 中职电工证在哪考?工地太忙根本没时间复习考试的救星来了 工地太忙根本没时间复习考试,这是很多正在备考 中职电工证 的建筑工友的真实写照。你不是不想考,而是真的没时间。但别担心,这期内容是 新乡初次报考人员… · 2026/11/11 0:00:52
昆明电工证培训价格值不值得考?老电工告诉你真相 昆明电工证培训价格值不值得考?老电工告诉你真相 之前考的证在外省能不能转过来?这个问题是很多在外地打工、换城市生活、或者是想在昆明发展的朋友最关心的。尤其是现在云南发展快,很多企业都在招持证上岗的电工,如果你手头有证但不在本地,那这个证是不… · 2026/11/11 0:00:52
特种电缆张工网上查询全攻略:外省证如何转过来 特种电缆张工网上查询全攻略:外省证如何转过来 之前考的证在外省能不能转过来?这是很多特种作业从业者最关心的问题,尤其是像特种电缆张工这类证书,直接关系到日常工作是否合规、能否顺利晋升。很多小伙伴因为证书归属地的问题,陷入职业发展的瓶颈,甚至… · 2026/11/11 0:00:52
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 20:19:29
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 19:22:45
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 17:00:47