Kornia 2D 强度变换(Intensity Transforms)完全指南:像素级增强算子、参数与源码解析
2026/9/24 15:34:27 网站建设 项目流程
  • 计算机视觉
  • 人工智能
  • 深度学习
  • 图像处理

【免费下载链接】kornia

🐍 Geometric Computer Vision Library for Spatial AI

项目地址:https://gitcode.com/gh_mirrors/ko/kornia
点击查看免费下载
本指南聚焦于 Kornia 计算机视觉库中的 **2D 强度变换(2D intensity transforms)**——这是数据增强流水线的核心组成部分。强度变换只改变图像像素值,不改变像素的空间位置,因此掩码(mask)、边界框(box)与关键点(keypoint)可以原样透传。你将了解完整算子清单、参数语义、底层实现原理与实战用法。

该 API 页面位于 docs/source/augmentation.intensity.rst,对应的全部实现位于 kornia/augmentation/_2d/intensity/ 目录。


一、什么是 2D 强度变换?

Kornia 的强度变换(intensity transforms)是一类只改变像素值不移动任何像素位置的增广算子。与之相对的是几何变换(geometric transforms,如旋转、缩放、仿射变换),后者会改变像素的空间坐标。

强度变换的关键特性:

  • 像素位置不变:输入图像的每个像素都留在原地,只有数值被修改;
  • 元数据透传:由于不移动像素,掩码(mask)、边界框(box)和关键点(keypoint)等标注数据可以直接“原样穿过”而不需要任何重投影或插值处理;
  • 可批量可随机:所有随机强度变换都支持p(应用概率)、same_on_batch(整批相同)、keepdim(输出维度保持)等通用参数。

这一特性使强度变换非常适合与几何变换混合使用:先做几何变换(同步更新 box/keypoint),再做强度变换(标注无需变动),从而构成完整的增广流水线。

统一的基类:IntensityAugmentationBase2D

所有 2D 强度变换都继承自IntensityAugmentationBase2D,该类定义在 kornia/augmentation/_2d/intensity/base.py:

class IntensityAugmentationBase2D(RigidAffineAugmentationBase2D): _compute_matrix_lazily = True @_input_metadata_only def compute_transformation(self, input, params, flags): return self.identity_matrix(input)

从源码结构可以看出其设计要点:

  1. 恒等变换矩阵compute_transformation返回恒等矩阵。由于强度变换不移动像素,其变换矩阵恒为单位阵,掩码/框/关键点的处理函数(apply_transform_maskapply_transform_boxapply_transform_keypoint)全部直接返回输入;
  2. 矩阵惰性构建_compute_matrix_lazily = True,变换矩阵直到.transform_matrix被真正读取时才构建,节省了每次前向传播中不必要的矩阵计算开销;
  3. inverse实现:基类不提供逆变换。当AugmentationSequential执行inverse时,会跳过 2D 强度子变换,仅反转支持的几何子变换。

基类约定中特别强调:这些类假定全库统一的[0, 1]浮点图像值范围(详见 get-started/conventions)。超出该范围时,不同类有各自的策略:有的 clamp、有的重缩放、有的执行uint8转换、有的不 clamp,RandomEqualize甚至会对越界图像抛出RuntimeError

基类参数pp_batchsame_on_batchkeepdim的语义如下:

参数作用
p逐样本控制增广应用概率(element-wise)
p_batch逐批次控制增广应用概率(batch-wise)
same_on_batch整批应用同一个变换参数
keepdimTrue时保持输入形状,False时广播为批形式(B, C, H, W)

注意:基类并未在入口对[0,1]范围做校验,这是一个前置条件而非强制契约。此外,在p < 1时变换仍会对每个样本计算,再通过门控选择,因此一个越界输入即使被跳过,也可能在计算阶段触发报错。


二、完整算子清单

Kornia 2D 强度变换模块共提供36 个随机/确定性算子,全部从 kornia/augmentation/_2d/intensity/init.py 导出。按功能类别划分如下:

1. 颜色调整类(Color Adjustment)

类名功能默认参数
ColorJiggle亮度/对比度/饱和度/色相联合抖动(推荐)四个因子默认0.0
ColorJitter同上,但实现对 PIL/TorchVision 对齐(兼容用)四个因子默认0.0
RandomBrightness随机亮度调整brightness=0.0
RandomContrast随机对比度调整contrast=0.0
RandomSaturation随机饱和度调整saturation=0.0
RandomHue随机色相调整hue=0.0
RandomGrayscale随机转灰度概率p
RandomRGBShiftRGB 通道随机偏移
RandomChannelShuffle通道随机重排
RandomChannelDropout随机丢弃通道num_drop_channels

2. 噪声与退化类(Noise & Degradation)

类名功能
RandomGaussianNoise添加高斯噪声(mean/std
RandomSaltAndPepperNoise椒盐噪声(amount/salt_vs_pepper
RandomBoxBlur盒式模糊
RandomGaussianBlur高斯模糊
RandomMedianBlur中值模糊
RandomMotionBlur运动模糊(核大小/角度/方向)
RandomJPEG模拟 JPEG 压缩伪影(可选依赖)
RandomDissolving溶解效果(需要diffusers,且冷启动会下载 Stable Diffusion checkpoint)
RandomSharpness锐化
RandomRain雨天效果
RandomSnow雪天效果

3. 光照类(Illumination)

类名功能
RandomGaussianIllumination高斯光照扰动
RandomLinearIllumination线性光照
RandomLinearCornerIllumination角落线性光照
RandomPlanckianJitter基于普朗克(黑体辐射)曲线的色温抖动
RandomPlasmaBrightness等离子体亮度场
RandomPlasmaContrast等离子体对比度场
RandomPlasmaShadow等离子体阴影场

4. 色调映射与后处理类(Tone & Post-processing)

类名功能
RandomAutoContrast自动对比度
RandomEqualize直方图均衡化
RandomClahe自适应直方图均衡(CLAHE,不在__all__中)
RandomGammaGamma 校正
RandomInvert反色
RandomPosterize色调分离(posterize)
RandomSolarize曝光过度(solarize)

注意:RandomClaheRandomJPEG未包含在kornia.augmentation.__all__中,需从kornia.augmentation._2d.intensity子模块直接导入。

5. 归一化类(Normalization,确定性)

类名功能
Denormalize反归一化:input * std + mean
Normalize归一化:(input - mean) / std

三、核心算子的参数详解与源码剖析

3.1ColorJiggleColorJitter:颜色抖动的两套实现

这两个类是 2D 强度变换中最常用的颜色增强算子,均继承自IntensityAugmentationBase2D。它们的构造签名完全一致:

ColorJiggle( brightness=0.0, contrast=0.0, saturation=0.0, hue=0.0, same_on_batch=False, p=1.0, keepdim=False, order=None, # 固定应用顺序:0=亮度, 1=对比度, 2=饱和度, 3=色相 )
  • brightness/contrast/saturation:可传入标量(表示以 1.0 为中心的偏移量[1 - x, 1 + x])或(min, max)元组;
  • hue:色相因子,范围限制在(-0.5, 0.5)之间(见 color_jitter.py 中_range_bound(self.hue, "hue", bounds=(-0.5, 0.5)));
  • order:默认None表示每次调用随机抽取应用顺序(torch.randperm(4));传入固定顺序(如[0, 1, 2, 3][1, 3]子集)则按固定顺序执行,并使得变换在torch.compile下可进行 fullgraph 编译。

两类的核心区别(源码 docstring 与实现均明确说明):

  1. 底层 primitive 不同
    • ColorJitter使用kornia.enhance.adjust_brightness_accumulativeadjust_contrast_with_mean_subtractionadjust_saturation_with_gray_subtraction(对齐 PIL/TorchVision);
    • ColorJiggle使用kornia.enhance.adjust_brightnessadjust_contrastadjust_saturation(更符合色彩理论,推荐使用);
    • 二者都调用adjust_hue
  2. brightness 的重新基准ColorJitter将抽到的亮度因子直接传给 primitive(不做-1处理),而ColorJiggleRandomBrightness一样先执行factor - 1
  3. 边界检查ColorJiggle的 brightness 边界是[0, 2],因此brightness=1.5(0.0, 3.0)都会在构造时抛出brightness out of bounds. Expected inside (0, 2)ColorJitter则接受任何值。
  4. 随机性来源ColorJiggle在采样设备上抽取orderColorJitter始终在 CPU 上抽取,因此二者在 GPU 上生成的顺序可能不同。
  5. 中性因子处理ColorJiggle对中性因子(如contrast == 1)直接跳过该步骤,不计算;ColorJitter则在torch.where下计算后选择,因此ColorJiggle(0,0,0,0)是恒等变换且接受任意通道数(包括 1 通道和 4 通道),而ColorJitter的饱和度/色相步骤要求 3 通道。

参数生成器:二者分别使用ColorJiggleGenerator(color_jiggle.py)和ColorJitterGenerator(color_jitter.py)。以ColorJitterGenerator为例,其make_samplersUniformDistribution构造四个因子的均匀分布采样器,forward返回brightness_factorcontrast_factorhue_factorsaturation_factor(形状(B,))以及order(形状(4,)的随机排列,0=亮度、1=对比度、2=饱和度、3=色相)。

使用示例(来自源码 docstring,可复现):

import torch from kornia.augmentation import ColorJiggle rng = torch.manual_seed(0) inputs = torch.ones(1, 3, 3, 3) aug = ColorJiggle(0.1, 0.1, 0.1, 0.1, p=1.0) aug(inputs) # tensor([[[[0.9993, 0.9993, ...]]]]) —— 全部通道被轻微扰动

精确重放(replay):Kornia 的强度变换支持参数状态重放,即用上一次调用保存的_params精确复现同样的变换:

input = torch.randn(1, 3, 32, 32) aug = ColorJiggle(0.1, 0.1, 0.1, 0.1, p=1.0) (aug(input) == aug(input, params=aug._params)).all() # tensor(True)

这一机制在测试与可复现实验(如对比同一次随机增广下不同模型的行为)中非常有用。

3.2RandomGaussianNoise:高斯噪声

源码位于 gaussian_noise.py:

RandomGaussianNoise(mean=0.0, std=1.0, same_on_batch=False, p=0.5, keepdim=False)
  • 噪声是加性的:输出 = 输入 +_params["gaussian_noise"],噪声张量形状与输入(B, C, H, W)一致,mean直接偏移图像;
  • 不进行任何 clamp,因此原本在[0,1]内的输入可能在任一方向越界;
  • same_on_batch=True时,噪声张量以(1, C, H, W)存储,在应用时expand_as(input)扩展到整个批次。

3.3RandomMotionBlur:运动模糊

源码位于 motion_blur.py,是参数最丰富的算子之一:

RandomMotionBlur( kernel_size, # int 固定核大小,或 (min, max) 随机取范围内奇数(闭区间等概率) angle, # 运动方向角度(度,逆时针);float 表示从 (-angle, angle) 采样 direction, # 前后方向;-1.0 向后、+1.0 向前、0.0 均匀;float 表示从 (-direction, direction) 采样 border_type=BorderType.CONSTANT.name, # CONSTANT=0, REFLECT=1, REPLICATE=2, CIRCULAR=3 resample=Resample.NEAREST.name, # 插值方式 same_on_batch=False, p=0.5, keepdim=False, )

关键实现细节:

  • 核大小整批共享kernel_size为元组时,每次调用只抽一个奇数并重复到_params["ksize_factor"](形状(B,)),即使same_on_batch=False所有样本也共用同一个核大小;angledirection则逐样本采样(除非same_on_batch=True)。
  • 范围行为(3, 5)等概率抽取 3 和 5;(4, 4)因范围内无奇数会被向上取整抽到 5;(20, 3)这种倒置范围在构造时直接报错。
  • 方向语义direction=0沿模糊线均匀分布权重,-1/+1将权重堆到两端;旋转使用resample重采样,"nearest"可能丢/重复抽头,"bilinear"/"bicubic"会把权重扩散到线外。
  • 越界行为:默认border_type="constant"时填充为 0,边界像素会被拉向 0;"reflect"时结果保持在输入极值之间(bicubic旋转可能过冲);默认resample="nearest"
  • 可微性:如需更有意义的梯度,建议设置resample="bilinear"

底层调用kornia.filters.motion_blur,输入需为 float 且归一化到[0,1]以获得最佳可微性支持;该函数还接受额外的(B, 3, 3)变换张量并与之合并返回。

3.4NormalizeDenormalize:确定性归一化/反归一化

这两个是确定性算子(无随机参数),对 2D 和 3D 张量形状无关(shape-agnostic)。源码位于 normalize.py 与 denormalize.py:

Normalize(mean, std, p=1.0, keepdim=False) # (input - mean) / std Denormalize(mean, std, p=1.0, keepdim=False) # input * std + mean
  • mean/std可接受:单个 float、逐通道序列/张量、或逐样本(B, C)张量;长度既不是 1 也不是通道数时会报错;
  • p整批为单位门控(构造函数硬编码same_on_batch=True,不提供same_on_batch参数);
  • 统计量存放在flags而非 buffer 中,因此state_dict()为空、Module.to(...)不会改变其 device 和 dtype(便于 ONNX 导出时按需 reshape);
  • 结果不做 clamp:将图像移出[0,1]正是归一化的目的;
  • 用相同的mean/std构造的DenormalizeNormalize互为逆运算(存在浮点舍入误差),这一点在 Normalize 的 docstring 中有明确说明。例如:
from kornia.augmentation import Normalize, Denormalize import torch norm = Normalize(mean=torch.zeros(4), std=torch.ones(4)) x = torch.rand(1, 4, 3, 3) out = norm(x) # torch.Size([1, 4, 3, 3]) denorm = Denormalize(mean=torch.zeros(1, 4), std=torch.ones(1, 4)) denorm(out) # 恢复 x(浮点舍入内)

四、实战用法:构建强度变换增广流水线

4.1 单独使用

每个强度变换都可以当作一个独立的nn.Module使用:

import torch from kornia.augmentation import ( RandomGaussianNoise, RandomMotionBlur, RandomGrayscale, RandomPosterize, RandomGamma, ) x = torch.randn(2, 3, 64, 64) # (B, C, H, W) # 依次施加多个强度变换 x = RandomGaussianNoise(mean=0.0, std=0.05, p=0.8)(x) x = RandomMotionBlur(kernel_size=(3, 7), angle=(0.0, 360.0), direction=0.0, p=0.5)(x) x = RandomGrayscale(p=0.2)(x) x = RandomPosterize(bits=3, p=0.3)(x) x = RandomGamma(gamma=(0.5, 1.5), gain=(0.8, 1.2), p=0.5)(x)

4.2 与几何变换、标注数据混合使用

强度变换不移动像素的特性,使得它可以安全地与几何变换、mask/box/keypoint 标注共存——无需重新投影标注:

from kornia.augmentation import ( RandomAffine, RandomHorizontalFlip, RandomGaussianNoise, ColorJiggle, ) from kornia.augmentation.container import AugmentationSequential augment = AugmentationSequential( RandomAffine(degrees=15, p=0.5), # 几何变换:会同步更新 box/keypoint RandomHorizontalFlip(p=0.5), # 几何变换 ColorJiggle(0.1, 0.1, 0.1, 0.05, p=0.5), # 强度变换:标注透传 RandomGaussianNoise(mean=0.0, std=0.03, p=0.5), # 强度变换:标注透传 )

AugmentationSequential执行inverse()时,2D 强度子变换会被跳过(基类不提供逆变换),仅反转几何子变换。

4.3 精确重放与可复现性

Kornia 的强度变换都支持参数重放:

aug = RandomMotionBlur(3, 35.0, 0.5, p=1.0) out1 = aug(input) out2 = aug(input, params=aug._params) # 与 out1 完全一致

这在需要“同一增广两次不同前向”或需要保存增广参数以便推理时复现的场景中很有价值。

4.4 注意事项与边界行为

阅读 base.py 的 Convention 块可以总结出以下实战要点:

  • 全负值输入风险:基类明确警告,多个强度变换对“全负值”输入可能返回全零图像且无警告(已跟踪 issue#4430)。例如Denormalize(mean=0.5, std=0.5)会将-1映射到恰好 0;RandomAutoContrast对任意常数图像返回零。若训练数据包含负值,请谨慎。
  • p 门控的副作用:即使p=0.0,变换仍会对每个样本计算再做选择,因此RandomEqualizeRandomClahe对越界图像即使p=0.0也会抛错;某些变换在跳过样本上可能出现 NaN 梯度(issue#4576)。
  • 参数边界检查:多数类在构造时校验显式范围(如ColorJiggle的 brightness ∈[0,2]RandomPlanckianJitterselect_from索引、RandomChannelDropoutnum_drop_channelsvs 通道数);但RandomGamma的非负性、RandomGaussianBlursigma=0RandomMedianBlur的偶数核、RandomMotionBlur的奇数核下限等检查发生在前向时。
  • 依赖与下载RandomDissolving需要可选的diffusers包,且在冷缓存下会下载 Stable Diffusion checkpoint;RandomClaheRandomJPEG有独立的文档页面,且后者不在__all__中。

五、源码级验证与测试

Kornia 为强度变换提供了详尽的测试与约定校验:

  • tests/augmentation/test_conventions_intensity_ops.py:验证强度变换的操作约定(恒等矩阵、mask/box/keypoint 透传等);
  • tests/augmentation/test_conventions_intensity_values.py:验证各类变换对[0,1]内外输入的值域行为;
  • tests/augmentation/test_motionblur.py:专项测试RandomMotionBlur的核大小/角度/方向行为;
  • tests/augmentation/test_backward.py 与 test_onnx_export.py:验证变换的可微性与 ONNX 导出支持;
  • tests/augmentation/test_param_validation.py:参数边界校验测试。

如果你在 docs/source/augmentation.auto.rst 中看到“Convention”段落,那是强度变换与几何变换共享的完整约定文档;每个具体类的 docstring 中也包含自身的 Convention 块,是理解边界行为的第一手资料。


六、总结

Kornia 的 2D 强度变换模块提供了从颜色抖动、噪声注入、光照模拟到色调映射的 36 个算子,全部基于统一的IntensityAugmentationBase2D基类,保证:

  • 像素位置不变 → 掩码/边界框/关键点自动透传;
  • 统一的p/same_on_batch/keepdim参数约定;
  • 参数状态可保存、可精确重放;
  • 与几何变换、AugmentationSequential容器无缝组合;
  • 全部算子可微,支持梯度回传与 ONNX 导出。

选择ColorJiggle而非ColorJitter作为默认颜色增强(后者仅用于 TorchVision 兼容),结合RandomMotionBlurRandomGaussianNoise、等离子体光照等算子,即可构建覆盖真实世界退化(光照变化、运动模糊、传感器噪声、压缩伪影)的鲁棒性训练流水线。

相关阅读:[2D 几何变换](https://link.gitcode.com/i/1a9dfd22d45cfd5aec37ff1a39b1d862) · [3D 变换](https://link.gitcode.com/i/08a604b23eb0ce2cca82d4041fb3006d) · [增广容器 AugmentationSequential](https://link.gitcode.com/i/4b2253b413c1b858d774ca5dbb2becdd) · [随机参数生成器](https://link.gitcode.com/i/3b517bbc55c663c4576723f3dfe626cb) · [增强 API 总览](https://link.gitcode.com/i/0e1d18d413014d8175972b0e9c1e6b15)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询