张芷铭的个人博客

学习感知图像块相似度 (LPIPS):迈向人类视觉感知的图像质量评估

在计算机视觉和图像处理领域,如何准确评估图像质量、衡量图像之间的相似度是一个核心问题。传统指标如PSNR(峰值信噪比)和SSIM(结构相似性指数)虽被广泛使用,但它们往往与人类主观感知存在显著差距。LPIPS (Learned Perceptual Image Patch Similarity) 作为一种基于深度学习的感知相似度度量方法,较好地解决了这一问题,它通过预训练的神经网络提取图像特征,并计算特征空间中的距离来评估图像相似性,其结果更符合人类视觉系统的判断。

LPIPS 的定义与发展

LPIPS,全称为 Learned Perceptual Image Patch Similarity,也称为“感知损失”(perceptual loss)。它来源于CVPR2018的论文《The Unreasonable Effectiveness of Deep Features as a Perceptual Metric》。该度量标准学习生成图像到Ground Truth的反向映射,强制生成器学习从假图像中重构真实图像的反向映射,并优先处理它们之间的感知相似度。

相比于传统度量方法(如L2/PSNR, SSIM, FSIM),LPIPS 的核心优势在于其更符合人类的感知情况。LPIPS的值越低表示两张图像越相似,反之,则差异越大。

LPIPS 的原理与数学推导

LPIPS 的核心思想是利用深度卷积神经网络提取的特征来度量图像间的感知差异。

基本框架

  1. 特征提取:将两张待比较的图像块($x$ 和 $x_0$)输入到一个预训练的深度神经网络(如VGG、AlexNet或SqueezeNet)中。
  2. 特征激活与归一化:提取网络中间各层的输出特征,并对每个层的输出进行激活后归一化处理,记为 $\hat{y}^l$ 和 $\hat{y}_0^l$(其中 $l$ 表示第 $l$ 层)。
  3. 缩放与差异计算:对每一层归一化后的特征差异进行缩放(使用一个权重向量 $w_l$),然后计算 $L_2$ 距离。
  4. 空间平均与求和:对每一层缩放后的差异进行空间平均,并对所有层求和,得到最终的LPIPS距离。

数学表达

LPIPS 的公式可以表示为: $$d(x, x_0) = \sum_{l} \frac{1}{H_l W_l} \sum_{h,w} ||w_l \odot (\hat{y}{hw}^l - \hat{y}{0hw}^l)||_2^2$$ 其中:

  • $\hat{y}^l, \hat{y}_0^l \in \mathbb{R}^{H_l \times W_l \times C_l}$ 是在 $l$ 层提取的激活特征。
  • $w_l$ 是一个用于缩放第 $l$ 层特征通道的权重向量。
  • $\odot$ 表示逐元素相乘。
  • $H_l, W_l$ 是特征图的尺寸。

注意:在实际代码实现中,最终的距离并未进行开方操作(即并非严格意义上的 $L_2$ 范数)。

网络选择与训练模式

LPIPS 支持多种预训练网络 backbone,常用的包括:

  • AlexNet:模型较小 (9.1MB),速度最快,默认推荐用于前向评估。
  • VGG:模型较大 (58.9MB),速度中等,精度较高,更接近传统感知损失。
  • SqueezeNet:模型轻量 (2.8MB),速度快,精度良好,适合资源受限环境。

论文中将 LPIPS 分为三种训练模式:

  • Lin:固定预训练网络,仅学习线性权重 $w_l$。
  • Tune:从预训练模型初始化,并对整个网络进行微调。
  • Scratch:使用高斯分布的权重初始化网络,并对整个网络进行训练。

LPIPS 的安装与使用

安装

LPIPS 可以通过 Python 的 pip 包管理器方便地安装:

1
pip install lpips

安装时,其核心依赖包括 torch(PyTorch深度学习框架)、torchvisionnumpyscipy 等。

基本使用方法

以下是一个使用 LPIPS 计算两张图像相似度的基本 Python 示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import lpips
import torch
from PIL import Image
import torchvision.transforms as transforms

# 初始化 LPIPS 模型
loss_fn = lpips.LPIPS(net='alex')  # 可选 'alex', 'vgg', 'squeeze'
# loss_fn = lpips.LPIPS(net='vgg')    # 更接近传统感知损失
# loss_fn = lpips.LPIPS(net='squeeze') # 轻量级版本

# 图像预处理函数(非常重要!)
def preprocess_image(image_path):
    transform = transforms.Compose([
        transforms.ToTensor(),           # 将图像转换为Tensor
        transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]) # 归一化到[-1, 1]
    ])
    image = Image.open(image_path).convert('RGB')
    return transform(image).unsqueeze(0)  # 添加批次维度

# 加载并预处理图像
img0 = preprocess_image('path/to/image0.jpg')
img1 = preprocess_image('path/to/image1.jpg')

# 如果使用GPU,将数据和模型移至GPU
if torch.cuda.is_available():
    img0 = img0.cuda()
    img1 = img1.cuda()
    loss_fn = loss_fn.cuda()

# 计算感知相似度距离
distance = loss_fn(img0, img1)
print(f"LPIPS 距离: {distance.item():.4f}")

关键注意事项

  1. 图像预处理:输入图像必须是 RGB格式,并归一化到 [-1, 1] 范围。不正确的归一化会严重影响计算结果。
  2. 图像尺寸:模型对输入图像的尺寸没有固定要求,但比较的两张图像需要具有相同的空间尺寸。
  3. 结果解读LPIPS 值越小,表示图像越相似,感知质量越高。值为0表示完全相同。与传统指标(如PSNR越大越好)不同。

LPIPS 的适用场景与最佳实践

LPIPS 在多个计算机视觉任务中发挥着重要作用:

应用场景

  • 图像质量评估:评估超分辨率重建、图像去噪、图像压缩等任务的处理效果,比传统指标更贴合人眼感受。
  • 生成模型训练:作为 GAN(生成对抗网络)训练中的感知损失(Perceptual Loss),引导生成器产生视觉上更逼真的图像。
  • 图像风格迁移:衡量风格化后的图像与内容图像在感知内容上的保持程度。
  • 图像修复与编辑:评估图像修复、补全或编辑后区域与周围环境的自然融合程度。
  • 学术研究:用于计算机视觉算法的公平对比、人类视觉感知研究等。

最佳实践与经验

  • 网络选择
    • 默认推荐使用 net='alex',它在速度和精度之间取得了良好平衡。
    • 若追求更高精度且计算资源充足,可考虑 net='vgg'
    • 在移动端或资源受限环境下,net='squeeze' 是更好的选择。
  • 批量处理:对大量图像进行批量计算可以显著提高效率。
  • 结合其他指标:虽然 LPIPS 更符合感知,但不应完全抛弃传统指标(如 PSNR、SSIM)。结合多种指标可以从不同角度(像素精度、结构相似性、感知相似性)全面评估模型性能。例如,在 NeRF 模型的评估中,通常会同时汇报 PSNR、SSIM 和 LPIPS。
  • 理解局限性:LPIPS 基于 ImageNet 预训练模型,其感知判断可能带有该数据集的偏差。对于某些特定领域(如医疗影像、遥感图像),其有效性可能需要重新验证。

LPIPS 的最新进展与扩展

LPIPS 的思想已经被广泛应用和扩展。例如,在 NeRF(神经辐射场) 社区,LPIPS 被用于评估 novel view synthesis 的结果质量,衡量生成视图与真实视图之间的感知差异。尽管一些 NeRF 框架(如 nerfstudio)最初并未直接内置 LPIPS,但可以通过扩展其评估管道(如修改 get_image_metrics_and_images 方法)来集成 LPIPS 评估。

研究者们也在不断探索更好的感知相似度度量方法,但 LPIPS 因其简单有效,至今仍是许多研究和应用中首选的感知度量指标。

代码示例与扩展

批量计算目录图像 LPIPS

以下示例展示了如何计算两个目录中对应图像对的平均 LPIPS 距离。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import lpips
import os
from PIL import Image
import torchvision.transforms as transforms

loss_fn = lpips.LPIPS(net='alex')
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])

dir0 = 'path/to/directory/with/images0'
dir1 = 'path/to/directory/with/images1'

files = os.listdir(dir0)
total_lpips = 0.0

for file in files:
    if file in os.listdir(dir1): # 确保两个目录都有该文件
        img0_path = os.path.join(dir0, file)
        img1_path = os.path.join(dir1, file)
        
        img0 = transform(Image.open(img0_path).convert('RGB')).unsqueeze(0)
        img1 = transform(Image.open(img1_path).convert('RGB')).unsqueeze(0)
        
        with torch.no_grad():
            dist = loss_fn(img0, img1)
            total_lpips += dist.item()
            print(f'{file}: {dist.item():.4f}')

average_lpips = total_lpips / len(files)
print(f"平均 LPIPS 距离: {average_lpips:.4f}")

*code adapted from *

在自定义模型训练中作为损失函数

LPIPS 可以作为损失函数集成到 PyTorch 等深度学习框架中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import torch
import lpips

class MyCustomModel(torch.nn.Module):
    def __init__(self):
        super(MyCustomModel, self).__init__()
        # ... 你的模型结构 ...
        self.perceptual_loss = lpips.LPIPS(net='vgg')

    def forward(self, x):
        # ... 前向传播 ...
        return reconstructed_image

    def compute_loss(self, output, target):
        mse_loss = torch.nn.MSELoss()(output, target)
        lpips_loss = self.perceptual_loss(output, target).mean()
        total_loss = mse_loss + 0.01 * lpips_loss # 组合损失,权重需调试
        return total_loss, mse_loss, lpips_loss

总结与学习资源推荐

LPIPS 通过学习深度特征之间的差异,成功地提供了一种比传统指标更符合人类视觉感知的图像相似度度量方法。它在图像生成、处理和质量评估等领域已成为一个重要的工具和基准。

核心要点回顾

  • 定义:LPIPS 是一种基于深度学习感知相似度度量工具,用于评估图像块之间的相似度。
  • 原理:利用预训练CNN(如AlexNet、VGG)提取特征,并在特征空间计算加权L2距离。
  • 安装pip install lpips
  • 使用:输入图像需为RGB张量,并归一化到[-1, 1]
  • 解读:值越小越相似。
  • 应用:图像质量评估、GAN训练、超分辨率、图像修复等。

推荐学习资源

  1. 官方资源
    • 论文:《The Unreasonable Effectiveness of Deep Features as a Perceptual Metric》。
    • GitHub 项目:https://github.com/richzhang/PerceptualSimilarity - 包含官方实现、预训练模型和演示代码。
  2. 扩展阅读
    • 多了解 PSNRSSIM 等传统指标,理解它们的优缺点以及与 LPIPS 的差异。
    • 探索如何将 LPIPS 与其他视觉任务(如风格迁移图像编辑)结合。
  3. 实践建议
    • 亲自动手运行代码,在不同类型的图像上(如人脸、风景、纹理)计算 LPIPS,直观感受其度量效果。
    • 尝试在你自己图像生成或处理项目中使用 LPIPS 作为评估指标或损失函数。

LPIPS 的出现标志着图像质量评估从简单的像素对比迈向了更高级的感知理解阶段。随着深度学习技术的不断发展,未来必然会出现更强大、更高效的感知度量方法,但 LPIPS 作为这一领域的重要里程碑,其思想和实现无疑将继续影响深远。

💬 评论