3.1 典型评价尺度

PSNR范围(dB)图像质量评价
>40极好(肉眼不可辨差异)
30-40良好(可接受质量)
20-30较差(明显失真)
<20严重失真(不可接受)
 1import numpy as np
 2import cv2
 3import matplotlib.pyplot as plt
 4
 5
 6"""计算两幅RGB图像的PSNR值
 7参数:
 8    img1: 原始图像(numpy数组)
 9    img2: 待评估图像(numpy数组)
10返回:
11    PSNR值(dB)
12"""
13def rgb_psnr(img1, img2):
14    # 确保输入是numpy数组
15    img1 = np.array(img1, dtype=np.float64)
16    img2 = np.array(img2, dtype=np.float64)
17    # 计算各通道MSE
18    mse_r = np.mean((img1[:, :, 0] - img2[:, :, 0]) ** 2)
19    mse_g = np.mean((img1[:, :, 1] - img2[:, :, 1]) ** 2)
20    mse_b = np.mean((img1[:, :, 2] - img2[:, :, 2]) ** 2)
21    # 计算平均MSE
22    mse = (mse_r + mse_g + mse_b) / 3
23    # 处理完全相同的图像
24    if mse == 0:
25        return float('inf')
26    return 20 * np.log10(255 / np.sqrt(mse))
27
28
29def psnr(img1, img2):
30    img1 = img1.astype(np.float64)
31    img2 = img2.astype(np.float64)
32
33    mse = np.mean((img1 - img2) ** 2)
34    if mse == 0:
35        return float('inf')
36
37    if img1.max() > 1:
38        max_pixel = 255.0
39    else:
40        max_pixel = 1.0
41
42    return 20 * np.log10(max_pixel / np.sqrt(mse))
43
44
45if __name__ == "__main__":
46    # 1. 读取原始图像
47    original = cv2.imread('../../mario.png')  # BGR格式
48    original = cv2.cvtColor(original, cv2.COLOR_BGR2RGB)  # 转换为RGB
49
50    # 2. 创建测试图像(添加高斯噪声)
51    noisy = original + np.random.normal(0, 25, original.shape)
52    noisy = np.clip(noisy, 0, 255).astype(np.uint8)
53
54    # 3. 计算PSNR
55    # psnr_value = rgb_psnr(original, noisy)
56    psnr_value = psnr(original, noisy)
57    print(f"PSNR between original and noisy image: {psnr_value:.2f} dB")
58
59    # 4. 可视化比较
60    plt.figure(figsize=(12, 6))
61
62    plt.subplot(1, 2, 1)
63    plt.imshow(original)
64    plt.title('Original Image')
65    plt.axis('off')
66
67    plt.subplot(1, 2, 2)
68    plt.imshow(noisy)
69    plt.title(f'Noisy Image (PSNR={psnr_value:.2f}dB)')
70    plt.axis('off')
71
72    plt.tight_layout()
73    plt.show()

Pasted image 20251002145829