- 计算机视觉
- 人工智能
- 深度学习
- 图像处理
【免费下载链接】kornia
🐍 Geometric Computer Vision Library for Spatial AI
该 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)从源码结构可以看出其设计要点:
- 恒等变换矩阵:
compute_transformation返回恒等矩阵。由于强度变换不移动像素,其变换矩阵恒为单位阵,掩码/框/关键点的处理函数(apply_transform_mask、apply_transform_box、apply_transform_keypoint)全部直接返回输入; - 矩阵惰性构建:
_compute_matrix_lazily = True,变换矩阵直到.transform_matrix被真正读取时才构建,节省了每次前向传播中不必要的矩阵计算开销; - 无
inverse实现:基类不提供逆变换。当AugmentationSequential执行inverse时,会跳过 2D 强度子变换,仅反转支持的几何子变换。
基类约定中特别强调:这些类假定全库统一的[0, 1]浮点图像值范围(详见 get-started/conventions)。超出该范围时,不同类有各自的策略:有的 clamp、有的重缩放、有的执行uint8转换、有的不 clamp,RandomEqualize甚至会对越界图像抛出RuntimeError。
基类参数p、p_batch、same_on_batch、keepdim的语义如下:
| 参数 | 作用 |
|---|---|
p | 逐样本控制增广应用概率(element-wise) |
p_batch | 逐批次控制增广应用概率(batch-wise) |
same_on_batch | 整批应用同一个变换参数 |
keepdim | True时保持输入形状,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 |
RandomRGBShift | RGB 通道随机偏移 | — |
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__中) |
RandomGamma | Gamma 校正 |
RandomInvert | 反色 |
RandomPosterize | 色调分离(posterize) |
RandomSolarize | 曝光过度(solarize) |
注意:
RandomClahe和RandomJPEG未包含在kornia.augmentation.__all__中,需从kornia.augmentation._2d.intensity子模块直接导入。
5. 归一化类(Normalization,确定性)
| 类名 | 功能 |
|---|---|
Denormalize | 反归一化:input * std + mean |
Normalize | 归一化:(input - mean) / std |
三、核心算子的参数详解与源码剖析
3.1ColorJiggle与ColorJitter:颜色抖动的两套实现
这两个类是 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 与实现均明确说明):
- 底层 primitive 不同:
ColorJitter使用kornia.enhance.adjust_brightness_accumulative、adjust_contrast_with_mean_subtraction、adjust_saturation_with_gray_subtraction(对齐 PIL/TorchVision);ColorJiggle使用kornia.enhance.adjust_brightness、adjust_contrast、adjust_saturation(更符合色彩理论,推荐使用);- 二者都调用
adjust_hue。
- brightness 的重新基准:
ColorJitter将抽到的亮度因子直接传给 primitive(不做-1处理),而ColorJiggle与RandomBrightness一样先执行factor - 1。 - 边界检查:
ColorJiggle的 brightness 边界是[0, 2],因此brightness=1.5或(0.0, 3.0)都会在构造时抛出brightness out of bounds. Expected inside (0, 2);ColorJitter则接受任何值。 - 随机性来源:
ColorJiggle在采样设备上抽取order,ColorJitter始终在 CPU 上抽取,因此二者在 GPU 上生成的顺序可能不同。 - 中性因子处理:
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_samplers用UniformDistribution构造四个因子的均匀分布采样器,forward返回brightness_factor、contrast_factor、hue_factor、saturation_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所有样本也共用同一个核大小;angle和direction则逐样本采样(除非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.4Normalize与Denormalize:确定性归一化/反归一化
这两个是确定性算子(无随机参数),对 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 + meanmean/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构造的Denormalize与Normalize互为逆运算(存在浮点舍入误差),这一点在 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,变换仍会对每个样本计算再做选择,因此RandomEqualize、RandomClahe对越界图像即使p=0.0也会抛错;某些变换在跳过样本上可能出现 NaN 梯度(issue#4576)。 - 参数边界检查:多数类在构造时校验显式范围(如
ColorJiggle的 brightness ∈[0,2]、RandomPlanckianJitter的select_from索引、RandomChannelDropout的num_drop_channelsvs 通道数);但RandomGamma的非负性、RandomGaussianBlur的sigma=0、RandomMedianBlur的偶数核、RandomMotionBlur的奇数核下限等检查发生在前向时。 - 依赖与下载:
RandomDissolving需要可选的diffusers包,且在冷缓存下会下载 Stable Diffusion checkpoint;RandomClahe、RandomJPEG有独立的文档页面,且后者不在__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 兼容),结合RandomMotionBlur、RandomGaussianNoise、等离子体光照等算子,即可构建覆盖真实世界退化(光照变化、运动模糊、传感器噪声、压缩伪影)的鲁棒性训练流水线。