做过图像压缩、超分辨率或者去噪的工程师大概都遇到过这样的场景:算法A的PSNR比算法B高出2dB,但把输出图放在一起看,B反而更讨人眼喜欢。A的图整体平滑干净,细节却被抹掉了;B的图虽然有些噪声残留,纹理和边缘的清晰感明显更好。这种客观指标与主观感受打架的情况并不是偶然,根源在于PSNR这类基于像素误差的指标,只关心每个像素点差了多少,完全不关心人眼是如何看图的。基于人眼感知的图像质量评价(Image Quality Assessment,IQA)正是为了解决这个问题而发展起来的一套方法论,它的核心目标是让机器打出的分数尽可能逼近人类的平均评分。

一、为什么PSNR和SSIM会失灵
要理解感知类IQA的价值,先得弄清楚传统指标为什么不好用。PSNR的计算只依赖均方误差(MSE),它对所有像素一视同仁:一个像素偏了10个灰度值,无论是在平坦区域还是纹理区域,无论偏差出现在图像中央还是角落,对最终分数的贡献完全相同。但人眼显然不是这么工作的。人类视觉系统(Human Visual System,HVS)对亮度的敏感度远高于对色度的敏感度,对低频结构失真的容忍度低于对高频噪声的容忍度,注意力还会优先落在画面主体上。这些特性决定了像素级的均匀度量天生就和主观感受错位。
举个典型例子:一幅自然图像经过轻微的高斯模糊后,MSE可能很小,PSNR很高,但人眼对模糊极其敏感,主观分数会掉得很厉害。反过来,叠加少量高频噪声后MSE变大、PSNR降低,人眼却常常觉得图像“更锐了”,观感不降反升。这种非线性的、带掩蔽效应的感知行为,是任何基于误差线性累加的指标都无法刻画的。SSIM引入了亮度、对比度、结构三个分量的局部比较,比PSSN前进了一步,尤其在结构失真的捕捉上有明显改善,但它本质上仍假设失真是局部独立的,对几何形变、色偏、块效应等复杂失真的评价依然经常偏离主观感受。
二、人类视觉系统的几个关键感知特性
感知类IQA算法的设计基本都围绕HVS的若干经典特性展开,理解这些特性是看懂各类算法的前提。第一个是对比敏感度函数(CSF)。人眼对不同空间频率的敏感度不是平坦的曲线,在中等频率段(大约每度视角2到8个周期)最敏感,频率越高敏感度越低。这意味着同样幅度的误差,落在中频段时人眼更容易察觉,而落在高频段时往往被忽略。早期的PQMT、MSE加权改进方法就尝试把CSF作为加权矩阵叠在误差图上。
第二个特性是掩蔽效应,它包含亮度掩蔽和纹理掩蔽两方面。亮度掩蔽指人眼在亮度较高的区域对误差的敏感度会下降,Werber-Fechner定律描述的对数感知关系就是理论基础。纹理掩蔽则更直观:在纹理复杂的区域,失真会被周围丰富的纹理“藏起来”,人眼很难发现;同样的失真出现在平坦天空或白墙上就格外刺眼。JPEG压缩的块效应在平坦区域最明显,正是纹理掩蔽的直接体现。第三个特性是视觉注意力机制,人眼会聚焦于显著目标、人脸、边缘等区域,这些区域的失真对主观质量的影响权重远大于背景区域。第四个是人眼对结构信息的高度依赖,这也是SSIM家族的出发点,但后续算法进一步发现,人眼感知的“结构”更接近轮廓、相位信息和局部几何,而不仅仅是局部统计量。
三、经典感知IQA算法的核心思路与代码实践
MSSSIM(多尺度SSIM)是对SSIM最直接的改进。它把图像在多个尺度上分别下采样,在每个尺度上计算对比度分量和结构分量的SSIM,再加权融合。多尺度的设计对应了人眼在不同观察距离下的感知行为:远看时只能感知大尺度结构,近看时细节权重上升。实践表明MSSSIM在JPEG压缩、模糊、噪声等混合失真数据集上的相关性明显优于单尺度SSIM。
VIF(Visual Information Fidelity)则换了一个思路:它不再直接度量失真,而是度量参考图像与失真图像各自携带的视觉信息量,用两者的比值作为质量分数。VIF在发送端建模为原始图像经过失真信道到达接收端的过程,借助自然场景统计(NSS)理论,认为人眼熟悉的自然图像统计规律被破坏的程度就是质量下降的程度。VIF在LIVE数据集上的表现长期位居传统算法前列,对噪声类失真尤其鲁棒。FSIM(Feature SIMilarity)进一步引入了相位一致性(Phase Congruency)和梯度幅度两个特征,前者模拟人眼对边缘和轮廓位置的敏感性,后者捕捉对比度信息,两者加权融合后与主观分数的相关性进一步提高。
以Python的scikit-image和pyiqa库为例,实际工程中可以这样组合使用多个指标做交叉验证:
import torch
from pyiqa import create_metric
# 加载多个感知指标,在GPU上批量评估
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
ms_ssim = create_metric('ms_ssim', device=device)
vif = create_metric('vif', device=device)
fsim = create_metric('fsim', device=device)
lpips = create_metric('lpips', device=device, net='alex')
# img_ref与img_dist为归一化到[0,1]的Tensor,形状为[N,3,H,W]
# 分别计算各指标分数并输出,用于交叉比对
print('MS-SSIM:', ms_ssim(img_ref, img_dist).mean().item())
print('VIF :', vif(img_ref, img_dist).mean().item())
print('FSIM :', fsim(img_ref, img_dist).mean().item())
print('LPIPS :', lpips(img_ref, img_dist).mean().item())需要注意的是,这些指标的方向性不一致:MS-SSIM、VIF、FSIM是分数越高质量越好,LPIPS则是距离越小质量越好。做自动化阈值判断时务必先统一方向,否则监控告警的逻辑会完全颠倒。另外全参考指标需要原始图像参与计算,在只有接收端图像的实际业务中无法使用,这时需要转向NR-IQA(无参考质量评价)方向,比如BRISQUE、NIQE这类基于自然场景统计的无参考方法。
四、深度学习时代的感知指标如何选型
进入深度学习时代后,感知指标出现了新的分化。一方面,超分辨率领域提出的Perceptual Loss思路催生了LPIPS:它把两张图送入预训练的AlexNet或VGG网络,提取多个中间层特征,逐层计算特征距离再加权求和。由于卷积网络的特征本身就编码了人眼敏感的边缘、纹理、语义信息,LPIPS与主观评分的一致性在BAPPS等感知打分数据集上大幅超越了传统指标,尤其擅长捕捉传统指标完全无感的纹理扭曲和生成类伪影。另一方面,DISTS针对纹理失真做了专门优化,解决了LPIPS对纹理轻微错位过度惩罚的问题,更适合评价生成式模型的输出。
选型上没有万能答案,建议按失真类型分类处理。评价压缩、传输这类保真型失真,MSSSIM和VIF依然是稳妥的基线;评价超分、去噪这类需要平衡保真与感知的任务,LPIPS配合SSIM做双指标监控是主流做法;评价GAN扩散模型生成结果时,DISTS加人眼抽检的组合更可靠。还有一点工程经验值得强调:任何指标在应用到自己的业务场景前,都应该先收集少量样本做主观打分实验(比如MOS,平均意见分),验证指标分数与人工评分的SROCC相关性,相关性不达标就说明该指标不适合当前场景,盲目相信单一指标分数是很多画质翻车事故的直接原因。把指标当作主观感受的近似工具而不是绝对真理,才是一套靠谱质量评价体系的正确打开方式。