Image Processing 【Normlize和DeNormlize】

在深度学习图像处理中,Normalize(归一化)和DeNormalize(反归一化)是最基础但容易混淆的操作。本文通过Toy Example和可视化对比,让你彻底理解它们的数学原理和代码实现。

什么是归一化(Normalize)?

归一化的目的是将图像的像素值从原始范围(如 [0, 255])映射到一个标准范围(如 [-1, 1] 或 [0, 1]),以便神经网络更容易学习。
x normalized = x original − mean std x_{\text{normalized}} = \frac{x_{\text{original}} - \text{mean}}{\text{std}} xnormalized=stdxoriginalmean

其中:

视觉基础模型ViT一般使用ImageNet的mean和std,如CLIP:
	mean:数据集的均值(如 [0.485, 0.456, 0.406] for ImageNet)
	std:数据集的标准差(如 [0.229, 0.224, 0.225] for ImageNet)
	
传统VAE等low leve图像压缩模型,一般使用default的mean和std:
	mean:数据集的均值(如 [0.5, 0.5, 0.5] for default)
	std:数据集的标准差(如 [0.5, 0.5, 0.5] for default)

这个Norm的操作一般在那里使用呢?

  • 训练的时候,在Dataset的transforms
  • 推理的时候,在Transformers的AutoProcessor
  • 需要注意的是:训练和推理的归一化必须一致;如果训练时用了 ImageNet 的 mean=[0.485, 0.456, 0.406],推理时也必须用相同的参数,否则模型性能会大幅下降。
# 训练的时候
from torchvision import transforms
# 定义归一化参数(例如 ImageNet 的 mean/std)
DATA_NORM = {
    "mean": [0.485, 0.456, 0.406],
    "std": [0.229, 0.224, 0.225]
}
# 在 Dataset 的 transforms 中加入 Normalize
train_transform = transforms.Compose([
    transforms.Resize(256),
    transforms.RandomCrop(224),
    transforms.ToTensor(),          # 先转换到 [0,1]
    transforms.Normalize(           # 再归一化到标准分布
        mean=DATA_NORM["mean"], 
        std=DATA_NORM["std"]
    ),
])
dataset = ImageFolder("data/train", transform=train_transform)

# 推理的时候,底层已封装了数据预处理(包括归一化),用户无需关心具体参数。
from transformers import AutoImageProcessor
processor = AutoImageProcessor.from_pretrained("google/vit-base-patch16-224")
inputs = processor(images=image, return_tensors="pt")  # 自动归一化

数据加载过程中,数值范围的变化:

ToTensor 将 [0, 255][0, 1]
Normalize 将 [0, 1] → 标准分布
数据集 →	Mean 和	Std  →	归一化后范围
	mean和std是default(0.5)[0, 1][-1, 1]
	mean和std是imagenet:		[0, 1][-2.1, 2.5]

什么是反归一化(DeNormalize)

反归一化是归一化的逆操作,用于将处理后的数据还原到原始范围(如 [0, 255]),一般用于生成的图像的可视化
x original = x normalized × std + mean x_{\text{original}} = x_{\text{normalized}} \times \text{std} + \text{mean} xoriginal=xnormalized×std+mean

如果输入是经过ToTensor的 [0, 1],想要输出是 [0, 255],则还需乘以 255,才能成功还原到原始像素值!
x original = ( x normalized × std + mean ) × 255 x_{\text{original}} = (x_{\text{normalized}} \times \text{std} + \text{mean}) \times 255 xoriginal=(xnormalized×std+mean)×255

def denormalize(tensor, mean, std):
    # 输入 tensor 是 (C, H, W),反归一化后转 (H, W, C) 并缩放到 [0, 255]
    mean = torch.tensor(mean).view(3, 1, 1)
    std = torch.tensor(std).view(3, 1, 1)
    denorm_img = (tensor * std + mean) * 255.0
    return denorm_img.permute(1, 2, 0).clamp(0, 255).to(torch.uint8)

# 测试反归一化
norm_img = transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])(toy_img)
denorm_img = denormalize(norm_img, mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])

训练VAE可视化图像的数据变化流程

因为SSIM/PSNR一般在 [0,1] 之间计算,rFID一般在[0,255]之间计算:
在这里插入图片描述

常见误区

  1. ToTensor 已经归一化到 [0, 1],Normalize 是进一步变换。

  2. ImageNet 的 mean/std 会使数据超出 [0, 1],可视化时需 clamp

  3. 反归一化必须使用和归一化相同的 mean/std,否则颜色会错误。

# 下面的 denorm 仅适用于 mean=0.5, std=0.5:
samples = torch.clamp(127.5 * samples + 128.0, 0, 255)  # 仅适用于 mean=0.5, std=0.5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yuezero_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值