063、超分评价指标详解:PSNR、SSIM、LPIPS 与 NIQE 的计算与对比
063、超分评价指标详解PSNR、SSIM、LPIPS 与 NIQE 的计算与对比上个月调一个视频超分模型在公开测试集上PSNR刷到了38.2dB心里美滋滋准备发论文。结果审稿人一句话把我打回原形“请补充感知质量指标PSNR高不代表视觉好。” 当时真想顺着网线过去理论——后来自己盯着输出帧看了半小时确实高频细节是多了但纹理全是假的像油画笔刷抹上去的。从那以后我养成了一个习惯跑完模型先算四个指标PSNR、SSIM、LPIPS、NIQE一个都不能少。PSNR最古老也最坑的指标PSNR的全称是Peak Signal-to-Noise Ratio峰值信噪比。公式很简单PSNR 10 * log10(MAX^2 / MSE)MAX是像素最大值8位图就是255。MSE是均方误差逐像素算差然后平均。这里踩过坑很多人直接用skimage.metrics.peak_signal_noise_ratio但默认参数是data_range255。如果你处理的是归一化到[0,1]的tensor别这样写——算出来PSNR会虚高。正确做法是# 别这样写psnr peak_signal_noise_ratio(hr, sr)# 应该指定data_rangepsnrpeak_signal_noise_ratio(hr,sr,data_range255)PSNR最大的问题是什么它完全不在乎图像结构。你把一张清晰人脸整体向右平移一个像素PSNR可能掉到20dB以下但人眼看不出区别。反过来你给图像加一层高斯噪声PSNR可能只掉0.5dB但视觉上已经糊成一片了。实战经验PSNR适合作为模型训练的loss监督信号但不适合作为最终评价标准。我见过太多论文靠PSNR刷榜实际效果一塌糊涂。如果你发现两个模型PSNR差0.1dB以内基本可以认为它们在这个指标上没有显著差异——别为了这0.1dB折腾三天调参。SSIM结构相似性比PSNR靠谱一点SSIMStructural Similarity Index从亮度、对比度、结构三个维度比较图像。公式长这样SSIM(x,y) (2μxμy C1)(2σxy C2) / (μx^2 μy^2 C1)(σx^2 σy^2 C2)μ是均值σ是方差C1、C2是防止除零的小常数。别这样写直接用skimage.metrics.structural_similarity不指定win_size默认是7x7窗口。对于超分任务尤其是4倍、8倍超分7x7窗口太小了算出来的SSIM对纹理细节不敏感。我习惯用win_size11或者15。# 推荐写法ssim_valstructural_similarity(hr,sr,win_size11,data_range255,channel_axis-1)SSIM比PSNR好的地方在于它对图像结构变化更敏感。比如超分结果出现了振铃效应边缘附近的伪影SSIM会明显下降而PSNR可能只掉零点几分贝。但SSIM也有坑它对模糊不敏感。你把一张高清图稍微模糊一下SSIM可能还有0.95以上但人眼已经能看出区别了。这就是为什么后来有了MS-SSIM多尺度SSIM对模糊更敏感。LPIPS终于开始像人了LPIPSLearned Perceptual Image Patch Similarity是2018年提出的核心思想是用预训练好的CNN比如AlexNet、VGG提取特征在特征空间里算距离。原理一句话人眼看图像不是逐像素看的而是看纹理、边缘、语义内容。LPIPS让网络替我们做这件事。# 使用lpips库注意输入要归一化到[-1,1]importlpips loss_fnlpips.LPIPS(netalex)# 推荐用alexvgg太慢# 别这样写loss_fn lpips.LPIPS(netvgg, verboseTrue) # verboseTrue会打印一堆信息distloss_fn(hr_tensor,sr_tensor)# 输出是0-1之间的距离越小越好踩坑记录LPIPS的输入必须是归一化到[-1,1]的tensor而且要有batch和channel维度。如果你直接传numpy数组会报错。另外LPIPS对图像尺寸有要求至少224x224太小了特征提取不准。LPIPS最大的价值在于它能捕捉到PSNR和SSIM完全看不出的差异。比如超分结果出现了纹理粘连两个不同物体的纹理混在一起LPIPS会给出很高的距离而PSNR可能还很高。这也是为什么现在顶会论文几乎必报LPIPS。实战建议LPIPS的数值范围是0到1但实际中0.1以下就算很好了。如果你的模型LPIPS能到0.05以下视觉上基本看不出和原图的区别。NIQE无参考指标救急用的前面三个指标都需要高清参考图HR但实际应用中你拿到的低清图可能根本没有对应的HR。这时候NIQENatural Image Quality Evaluator就派上用场了。NIQE的原理从大量自然图像中提取统计特征主要是空间域和频域的统计量建立一个“自然图像”的分布模型。然后计算待测图像的特征与这个模型的偏离程度。# 使用piq库计算NIQEfrompiqimportniqe# 别这样写score niqe(sr) # 默认参数可能不适合超分scoreniqe(sr,data_range255,reductionnone)# 返回每个图像的分数注意NIQE没有参考图所以它只能告诉你图像“像不像自然图像”不能告诉你超分结果是否忠实于原图。比如你把一张人脸超分成了猫脸如果猫脸纹理自然NIQE可能还很高——这就尴尬了。个人经验NIQE适合做模型筛选的辅助指标。比如你有10个候选模型PSNR和SSIM都差不多这时候看NIQE选最低的那个。但别把NIQE当唯一标准它和主观评分的相关性只有0.6左右远不如LPIPS0.8以上。四个指标怎么用我的血泪经验训练阶段用PSNR做loss监督同时每100个iteration算一次LPIPS如果LPIPS不降反升说明模型开始过拟合了——赶紧加正则化或者早停。模型对比先看PSNR和SSIM如果两个模型差距在0.1dB/0.01以内再算LPIPS。LPIPS差距超过0.02基本可以判断哪个模型更好。论文投稿四个指标全报但要在正文里说明每个指标的意义。审稿人看到你报了LPIPS和NIQE会觉得你懂行。实际应用如果用户反馈“超分结果太假”先看LPIPS如果LPIPS很高说明模型产生了伪影。这时候别调PSNR了调LPIPS相关的loss比如Perceptual Loss更有效。最后说一句指标只是工具别被指标绑架。我见过最离谱的事有人为了刷PSNR把超分结果直接往HR上靠结果纹理全没了——这叫降噪不叫超分。真正好的超分是在保持纹理自然的前提下提升分辨率这需要你同时盯着四个指标更要盯着自己的眼睛。