4. 图像基础增强:几何变换、色彩抖动与噪声注入

图像增强,说白了就是给训练数据“化妆”。你想想看,真实世界里的照片,角度会偏、光线会变、摄像头还会有点噪点。如果模型只在“素颜”的干净数据上训练,一到真实场景立马就崩。

我个人习惯把图像增强分成三大类:几何变换、色彩抖动和噪声注入。这三板斧用好了,模型的泛化性至少能提 5-10 个点。下面我一个个拆开讲。

核心观点:图像增强不是“加数据量”,而是“加数据分布”。让模型见过更多样的情况,它才不会在测试集上翻车。
图像基础增强知识体系 图像基础增强 几何变换 色彩抖动 噪声注入 旋转 翻转 裁剪 亮度/对比度 饱和度/色相 HSV 扰动 高斯噪声 椒盐噪声 模糊/遮挡 目标:在不改变语义的前提下,增加数据多样性,提升模型对视角、光照、噪声的鲁棒性

4.1 几何变换:让模型学会“换个角度看世界”

几何变换是最直观的增强手段。你拍一张猫的照片,换个角度它还是猫。模型必须学会这种不变性。

4.1.1 旋转与翻转

旋转一般取 ±10° 到 ±30°。翻转分水平翻转和垂直翻转。水平翻转很常用,垂直翻转在自然图像里要慎用——你想想,谁会倒着看人脸?

我的经验:在车牌识别项目里,我试过旋转 45°,结果模型把“6”认成“9”了。后来我限制在 ±15°,效果才稳定。旋转角度不是越大越好。

4.1.2 随机裁剪与缩放

随机裁剪是“暴力但有效”的方法。从原图上随机抠一块,再缩放到固定尺寸。这相当于让模型看到物体的局部也能识别。

我记得有一次做细粒度分类,鸟类数据集里每张图都拍得很正。模型在测试集上遇到稍微偏一点的图就崩。加了随机裁剪后,准确率直接从 72% 跳到 81%。

import torchvision.transforms as T

# 常用几何变换组合
geo_transform = T.Compose([
    T.RandomResizedCrop(size=224, scale=(0.8, 1.0)),
    T.RandomHorizontalFlip(p=0.5),
    T.RandomRotation(degrees=15),
    T.Resize((224, 224))
])
变换类型 常用参数 适用场景 注意事项
水平翻转 p=0.5 通用(自然图像) 文字、车牌等有方向性任务慎用
旋转 ±10° ~ ±30° 通用 角度过大可能改变语义
随机裁剪 scale=(0.08, 1.0) 分类、检测 裁剪比例不要太小
仿射变换 translate=(0.1, 0.1) 文本、文档图像 保持文字可读性
避坑指南:我曾经在医学影像项目里用了随机裁剪,结果把病灶区域裁掉了,模型学了一堆“正常组织”的特征。对于关键区域敏感的任务,裁剪范围一定要控制好。

4.2 色彩抖动:模拟真实世界的光照变化

同一个物体,早上和傍晚拍出来颜色完全不一样。色彩抖动就是模拟这种变化。

4.2.1 亮度、对比度、饱和度调整

这三个参数是色彩抖动的“三件套”。亮度调暗一点,对比度拉高一点,饱和度降一点,模型就能适应不同光照条件。

我个人习惯用 ColorJitter,参数范围设得比较保守:亮度 ±0.2,对比度 ±0.2,饱和度 ±0.2。太猛了会失真,模型反而学坏。

4.2.2 HSV 空间扰动

在 HSV 空间做扰动比 RGB 更自然。因为 HSV 把色调、饱和度、亮度分开了,你单独调亮度不会影响颜色。

# 色彩抖动示例
color_transform = T.Compose([
    T.ColorJitter(
        brightness=0.2,
        contrast=0.2,
        saturation=0.2,
        hue=0.1
    ),
    T.ToTensor(),
    T.Normalize(mean=[0.485, 0.456, 0.406],
                std=[0.229, 0.224, 0.225])
])
小技巧:做多模态任务时,图像增强的参数最好和文本描述对齐。比如你调暗了图像,文本里就不要写“明亮的房间”,否则模态之间会打架。

4.3 噪声注入:让模型学会“抗干扰”

真实摄像头拍出来的图,多少都有噪声。模型如果没见过噪声,遇到一点噪点就崩了。

4.3.1 高斯噪声与椒盐噪声

高斯噪声是加性噪声,每个像素加一个高斯分布的值。椒盐噪声是随机把像素变成纯白或纯黑。

我记得在安防场景的项目里,摄像头在低光照下全是噪点。一开始模型在白天数据上跑得很好,晚上直接废了。加了高斯噪声训练后,夜间准确率从 55% 提到了 78%。

4.3.2 模糊与遮挡

模糊模拟运动或失焦,遮挡模拟物体被挡住一部分。这两种增强对检测和分割任务特别有用。

import random
import torch

def add_gaussian_noise(img, mean=0., std=0.05):
    noise = torch.randn_like(img) * std + mean
    return torch.clamp(img + noise, 0., 1.)

def random_erasing(img, p=0.5, scale=(0.02, 0.1)):
    if random.random() < p:
        # 随机遮挡一块区域
        h, w = img.shape[1:]
        eh = int(random.uniform(*scale) * h)
        ew = int(random.uniform(*scale) * w)
        x = random.randint(0, w - ew)
        y = random.randint(0, h - eh)
        img[:, y:y+eh, x:x+ew] = 0
    return img
噪声类型 强度范围 适用场景 副作用
高斯噪声 std=0.01~0.1 低光照、传感器噪声 过强会掩盖细节
椒盐噪声 prob=0.01~0.05 传输丢包、老旧摄像头 密度过高破坏结构
高斯模糊 kernel=3~7 运动模糊、失焦 过度模糊丢失纹理
随机遮挡 scale=0.02~0.3 遮挡检测、鲁棒性训练 遮挡比例过大导致语义丢失
避坑指南:我曾经在 OCR 项目里加了椒盐噪声,结果模型把“—”认成了“一”。噪声强度一定要根据任务调,文字识别任务噪声强度要比通用分类低一个数量级。

4.4 增强策略组合:别一股脑全上

很多人以为增强越多越好,其实不是。增强组合不当,反而会降低模型性能。

我一般遵循三个原则:

  1. 先几何后色彩:先做旋转裁剪,再做颜色调整。顺序反了会导致颜色信息被几何变换插值破坏。
  2. 噪声放最后:噪声注入放在所有变换之后,避免噪声被后续的缩放或裁剪放大。
  3. 强度递进:训练初期用弱增强,后期逐渐加强。让模型先学干净特征,再学抗干扰。
# 推荐的增强组合顺序
full_transform = T.Compose([
    # 1. 几何变换
    T.RandomResizedCrop(224, scale=(0.8, 1.0)),
    T.RandomHorizontalFlip(p=0.5),
    T.RandomRotation(degrees=10),
    # 2. 色彩抖动
    T.ColorJitter(brightness=0.2, contrast=0.2,
                  saturation=0.2, hue=0.05),
    # 3. 噪声注入(自定义函数)
    T.Lambda(lambda x: add_gaussian_noise(x, std=0.02)),
    # 4. 归一化
    T.ToTensor(),
    T.Normalize(mean=[0.485, 0.456, 0.406],
                std=[0.229, 0.224, 0.225])
])
总结一下:图像基础增强是数据增强的“基本功”。几何变换解决视角问题,色彩抖动解决光照问题,噪声注入解决传感器问题。这三者组合使用,能让多模态模型在真实场景下更稳定。但记住——增强不是越多越好,要根据任务和数据特点来调。