一、图像高级增强:从基础到实战

大家好,我是老张。今天咱们聊聊图像高级增强。

做图像分类、目标检测的朋友,一定遇到过数据不够的问题。我刚开始做CV项目时,总觉得标注数据越多越好。后来发现,光靠数量堆砌不行,质量才是关键。说白了,你得让模型看到更多「花样」——这就是高级增强要做的事。

核心思想:通过模拟真实世界的各种变化,让模型学会「举一反三」。不是简单翻转、旋转,而是更聪明的玩法。

1.1 Cutout:给图像「挖个洞」

Cutout 的思路很直接——随机遮挡图像的一部分。我最早在 Kaggle 比赛里用到它,效果出奇的好。

为什么有效?模型被迫关注局部特征,而不是依赖某个区域。比如识别猫,如果猫脸被遮住,模型就得看耳朵、尾巴来判断。

import torch
import numpy as np

def cutout(image, mask_size=16):
    """随机遮挡一个正方形区域"""
    h, w, _ = image.shape
    y = np.random.randint(h)
    x = np.random.randint(w)
    
    y1 = max(0, y - mask_size // 2)
    y2 = min(h, y + mask_size // 2)
    x1 = max(0, x - mask_size // 2)
    x2 = min(w, x + mask_size // 2)
    
    image[y1:y2, x1:x2] = 0  # 用黑色填充
    return image

我的经验:mask_size 别太大,一般设为图像短边的 10%-20%。太大反而让模型学不到东西。

1.2 Random Erasing:更灵活的遮挡

Random Erasing 是 Cutout 的升级版。它不一定是正方形,可以是任意矩形,还能用随机颜色填充。

我记得有一次做行人重识别,光照变化很大。用 Random Erasing 后,模型对遮挡的鲁棒性明显提升。

def random_erasing(image, p=0.5, sl=0.02, sh=0.4):
    """随机擦除,面积比例在 sl 到 sh 之间"""
    if np.random.rand() > p:
        return image
    
    h, w, _ = image.shape
    area = h * w
    
    for _ in range(100):
        target_area = np.random.uniform(sl, sh) * area
        aspect_ratio = np.random.uniform(0.3, 3.0)
        
        h_erase = int(round(np.sqrt(target_area * aspect_ratio)))
        w_erase = int(round(np.sqrt(target_area / aspect_ratio)))
        
        if h_erase < h and w_erase < w:
            y = np.random.randint(0, h - h_erase)
            x = np.random.randint(0, w - w_erase)
            # 用随机颜色填充
            color = np.random.randint(0, 255, 3)
            image[y:y+h_erase, x:x+w_erase] = color
            break
    
    return image

注意:Random Erasing 和 Cutout 不要同时用。我踩过这个坑,效果反而下降。

1.3 Mixup:让两张图「谈恋爱」

Mixup 的思路很巧妙——把两张图按比例混合,标签也按同样比例混合。

你想想看,模型看到的不再是「猫」或「狗」,而是「70% 的猫 + 30% 的狗」。这强迫模型学习线性插值关系,泛化能力自然更强。

def mixup(x1, y1, x2, y2, alpha=1.0):
    """混合两张图像及其标签"""
    lam = np.random.beta(alpha, alpha)
    
    x_mixed = lam * x1 + (1 - lam) * x2
    y_mixed = lam * y1 + (1 - lam) * y2
    
    return x_mixed, y_mixed

我在做医学图像分类时用过 Mixup。数据量只有 2000 张,但 Mixup 让准确率从 82% 提到了 89%。

1.4 CutMix:结合 Cutout 和 Mixup 的优点

CutMix 是 Cutout 和 Mixup 的「混血儿」。它把一张图的一块区域切掉,贴上另一张图的对应区域,标签按面积比例混合。

说白了,就是「挖个洞,补上别人的内容」。这样既保留了局部特征,又引入了混合信息。

def cutmix(x1, y1, x2, y2, alpha=1.0):
    """CutMix 增强"""
    lam = np.random.beta(alpha, alpha)
    
    h, w = x1.shape[1:3]
    cut_ratio = np.sqrt(1. - lam)
    cut_h = int(h * cut_ratio)
    cut_w = int(w * cut_ratio)
    
    # 随机选择裁剪区域
    y = np.random.randint(0, h - cut_h)
    x = np.random.randint(0, w - cut_w)
    
    # 交换区域
    x_mixed = x1.clone()
    x_mixed[:, y:y+cut_h, x:x+cut_w] = x2[:, y:y+cut_h, x:x+cut_w]
    
    # 标签按面积比例混合
    lam = 1. - (cut_h * cut_w) / (h * w)
    y_mixed = lam * y1 + (1 - lam) * y2
    
    return x_mixed, y_mixed

实战对比:

方法 适用场景 优点 缺点
Cutout 分类、检测 简单、高效 信息丢失
Random Erasing 行人重识别 更灵活 参数调优
Mixup 小样本分类 泛化强 标签模糊
CutMix 目标检测 保留局部 计算稍大

1.5 AutoAugment:让 AI 自己选策略

AutoAugment 是 Google 提出的方法。它用强化学习搜索最佳增强策略。

嗯,这里要注意——搜索过程很耗时。我试过在 CIFAR-10 上跑一次,用了 4 块 GPU 跑了 3 天。但效果确实好,比手动调参强不少。

搜索出来的策略包含 5 个子策略,每个子策略包含 2 个操作。比如「先旋转 15 度,再剪切 0.2」。这些操作按概率执行,幅度也有范围。

# AutoAugment 的典型策略(CIFAR-10)
policy = [
    [('Invert', 0.1, 7), ('Contrast', 0.2, 6)],
    [('Rotate', 0.7, 2), ('TranslateX', 0.3, 9)],
    [('Sharpness', 0.8, 1), ('ShearY', 0.1, 8)],
    [('ShearX', 0.4, 7), ('TranslateY', 0.6, 3)],
    [('Solarize', 0.6, 5), ('AutoContrast', 0.5, 1)]
]

我的建议:如果你资源有限,直接用别人搜好的策略。PyTorch 官方库里有现成的。

1.6 RandAugment:简化版 AutoAugment

RandAugment 去掉了搜索过程。它只控制两个参数:操作数量 N 和幅度 M。

为什么能简化?因为研究发现,随机选择操作的效果和搜索出来的差不多。你想想看,这省了多少事。

def rand_augment(image, n=2, m=9):
    """随机选择 N 个操作,幅度为 M"""
    operations = [
        'autocontrast', 'equalize', 'rotate', 'solarize',
        'color', 'posterize', 'contrast', 'brightness',
        'sharpness', 'shear_x', 'shear_y', 'translate_x', 'translate_y'
    ]
    
    for _ in range(n):
        op = np.random.choice(operations)
        # 应用操作,幅度映射到 [0, 10]
        image = apply_op(image, op, m)
    
    return image

我曾经在 ImageNet 子集上对比过:AutoAugment 提升 1.8%,RandAugment 提升 1.5%。差距不大,但 RandAugment 训练时间少了 90%。

知识体系总览

下面这张图,帮你理清这些方法的关系:

图像高级增强方法体系 基础遮挡 Cutout(挖洞) Random Erasing(随机擦除) 混合增强 Mixup(图像混合) CutMix(裁剪混合) 自动搜索 AutoAugment(搜索策略) RandAugment(简化版) 核心目标:提升模型泛化能力,防止过拟合 三种思路:遮挡局部 → 混合样本 → 自动搜索最优策略 实战建议:小数据集用 Mixup/CutMix,大数据集用 RandAugment 资源充足时,AutoAugment 仍是天花板

实战建议

说了这么多,到底怎么选?我总结几条经验:

  • 数据量 < 1万张:优先用 Mixup 或 CutMix。它们能有效缓解过拟合。
  • 数据量 1万-10万张:用 RandAugment。效果好,调参简单。
  • 数据量 > 10万张:可以考虑 AutoAugment。但说实话,RandAugment 也够用了。
  • 目标检测任务:CutMix 效果最好。因为它保留了目标的位置信息。

避坑指南:我曾经在同一个项目里同时用了 Cutout、Mixup 和 RandAugment。结果模型训练了 200 个 epoch 还没收敛。记住,增强不是越多越好,选 1-2 个就够了。

好了,这一章的内容就到这里。下一章我们会聊更高级的玩法——生成式增强。到时候见。


专注资料整理