第三章 图像质量评估:主观评价与客观评价指标
图像处理完了,效果到底怎么样?
这个问题,我每次做完一个去雾或拉伸算法,都得面对。光靠眼睛看,有时候会骗人。你想想看,一张图看起来挺亮,但细节全丢了,这能算好吗?
所以,我们需要一套「尺子」来量。这套尺子分两种:主观评价(人眼看)和客观评价(数学算)。
3.1 主观评价:让眼睛说话
主观评价,说白了就是找人来看图打分。我最早做项目时,总觉得机器算出来的指标才靠谱,后来被现实教育了——用户只看「好不好看」。
核心原则:主观评价是最终标准,客观指标只是辅助工具。
3.1.1 评价方法
- 评价:直接给单张图打分(1-5分,5分最好)。
- 相对评价:把多张图放一起,挑最好的。
- 成对比较:两张图二选一,简单粗暴。
我的习惯:做算法对比时,我会先做一轮成对比较,快速筛掉明显差的,再用评价细看前几名。这样效率高,不容易疲劳。
3.1.2 注意事项
主观评价有个大坑——人眼会疲劳。我曾经连续看了200张图,到后面眼睛都花了,打分完全不准。
避坑指南:每看20-30张图,休息5分钟。最好找3-5个人一起评,取平均值,减少个人偏好影响。
3.2 客观评价指标:用数字说话
主观评价虽然重要,但没法自动化。所以我们需要客观指标,让程序自己算。
我常用的指标有四个:PSNR、SSIM、熵、对比度。下面一个一个说。
3.2.1 PSNR(峰值信噪比)
PSNR 是最经典的指标,衡量两幅图之间的像素差异。说白了,就是算「原图」和「处理后的图」差了多少。
公式长这样:
PSNR = 10 * log10(MAX^2 / MSE)
其中:
MAX = 像素最大值(8位图就是255)
MSE = 均方误差(像素差值的平方平均)
PSNR 越高,说明处理后的图越接近原图。一般超过30dB就算不错,40dB以上人眼几乎看不出区别。
注意:PSNR 只算像素差异,不管视觉感受。有时候 PSNR 很高,但图看起来就是怪怪的。我遇到过这种情况,后来加了 SSIM 才发现问题。
3.2.2 SSIM(结构相似性)
SSIM 比 PSNR 聪明一点。它不光看像素差异,还看亮度、对比度、结构三个维度。
SSIM 的取值范围是 [-1, 1],越接近1说明越像原图。一般0.9以上就算很好了。
| 指标 | PSNR | SSIM |
|---|---|---|
| 关注点 | 像素差异 | 结构相似性 |
| 取值范围 | 0~∞(dB) | [-1, 1] |
| 优点 | 计算简单,物理意义明确 | 更符合人眼视觉 |
| 缺点 | 不敏感于结构变化 | 对平移/旋转敏感 |
| 适用场景 | 去噪、压缩质量评估 | 去雾、增强效果评估 |
我的经验:做去雾时,PSNR 和 SSIM 要一起看。PSNR 高但 SSIM 低,说明图变亮了但结构被破坏了。这种情况,我一般会调参数重新跑。
3.2.3 信息熵
熵衡量图像的信息量。熵越高,说明图像细节越丰富。
公式:
Entropy = -sum(p(i) * log2(p(i)))
其中:
p(i) = 灰度值 i 出现的概率
对于8位图,最大熵是8(所有灰度值均匀分布)。一般自然图像的熵在5-7之间。
注意:熵不是越高越好。噪声也会增加熵。我曾经把一张雾图拉伸过度,熵确实高了,但图全是噪点,根本不能用。
3.2.4 对比度
对比度衡量图像的明暗差异。常用的指标是 RMS 对比度:
Contrast = sqrt( (1/N) * sum( (I(i) - mean(I))^2 ) )
说白了,就是像素值的标准差。标准差越大,对比度越高。
去雾和对比度拉伸,本质上都是在提高对比度。但要注意,过度拉伸会导致细节丢失。
3.3 核心逻辑:指标之间的关系
这四个指标不是孤立的。我画了一张图,帮你理清它们的关系:
3.4 代码实现:Python 计算指标
下面是我常用的计算代码,直接用 skimage 和 numpy:
import numpy as np
from skimage.metrics import peak_signal_noise_ratio, structural_similarity
from skimage.measure import shannon_entropy
def evaluate_image(original, processed):
"""
计算图像质量指标
original: 原图 (H, W, C) 或 (H, W)
processed: 处理后的图
"""
# PSNR
psnr = peak_signal_noise_ratio(original, processed, data_range=255)
# SSIM
ssim = structural_similarity(original, processed, multichannel=True, data_range=255)
# 熵(转灰度计算)
if len(processed.shape) == 3:
gray = np.mean(processed, axis=2).astype(np.uint8)
else:
gray = processed.astype(np.uint8)
entropy = shannon_entropy(gray)
# 对比度(RMS)
contrast = np.std(gray)
return {
'PSNR': round(psnr, 2),
'SSIM': round(ssim, 4),
'Entropy': round(entropy, 2),
'Contrast': round(contrast, 2)
}
# 使用示例
# result = evaluate_image(original_img, dehazed_img)
# print(result)
注意:PSNR 和 SSIM 需要原图作为参考。如果只有处理后的图(比如从网上下载的),就只能算熵和对比度了。
3.5 综合评估流程
我一般按这个流程来评估:
- 先看主观:快速扫一眼,有没有明显问题(过曝、偏色、噪点)。
- 再算客观:跑一遍代码,看 PSNR、SSIM、熵、对比度。
- 对比分析:如果主观好但客观差,或者反过来,要找出原因。
- 最终决策:以主观为主,客观为辅。
避坑指南:我曾经迷信 PSNR,调参调到 PSNR 最高,结果图看起来像塑料一样。后来才明白,指标是工具,不是目的。用户觉得好,才是真的好。