即使现在有这么高级的质量评估方法:
https://mp.weixin.qq.com/s/77F6JlbLN6cFaU7vR4N0CA
本文写一些以前用的质量评估方法。
图像上色(Image Colorization)是计算机视觉中的一项重要任务,它将灰度图像转换为彩色图像。评估上色结果的质量是一个复杂问题,因为颜色不仅要逼真,还需要与图像内容语义相符。今天,我们将深入探讨几种常用的图像上色评估指标,从理论公式到代码实现,全面了解如何客观评估上色结果的质量。
评估图像上色质量通常需要多个指标,这些指标可以从不同角度衡量生成图像与真实图像的差异:
接下来,我们将详细介绍每个指标的原理、数学公式以及代码实现。
SSIM是一种衡量两幅图像结构相似度的指标。与MSE和PSNR等仅关注像素差异的指标不同,SSIM考虑了亮度、对比度和结构三个方面,更符合人类视觉感知系统。
SSIM指标通过以下公式计算:
其中:
pythonfrom skimage.metrics import structural_similarity as ssim
def calculate_ssim(img1, img2):
"""计算两幅图像之间的结构相似性指标"""
return ssim(img1, img2, channel_axis=2, data_range=255)
SSIM取值范围为[-1, 1],值越接近1表示两幅图像结构越相似。对于图像上色任务,高SSIM值意味着生成的彩色图像保持了原始图像的结构特征。
PSNR是评估重建图像质量的常用指标,用于测量信号最大值与背景噪声之间的比率,通常以分贝(dB)表示。PSNR值越高,表示重建图像与原始图像越接近。
PSNR基于MSE计算,公式如下:
其中:
pythonfrom skimage.metrics import peak_signal_noise_ratio as psnr
def calculate_psnr(img1, img2):
"""计算两幅图像之间的峰值信噪比"""
return psnr(img1, img2, data_range=255)
通常,PSNR值在20-40dB之间被视为可接受的图像质量。PSNR值越高,表示上色结果与真实彩色图像在像素级别上越接近。
MSE是最基本的图像差异度量方法,计算两幅图像对应像素差值的平方平均值。它直接反映像素差异的大小,但不考虑人类视觉感知。
其中:
pythonfrom skimage.metrics import mean_squared_error as mse
def calculate_mse(img1, img2):
"""计算两幅图像之间的均方误差"""
return mse(img1, img2)
MSE值越小,表示上色结果与真实图像越接近。但需要注意的是,MSE对于视觉感知并不总是可靠的,因为人眼对不同类型的失真有不同的敏感度。
MAE计算两幅图像对应像素差的绝对值平均值,与MSE类似,但对异常值不那么敏感。
pythonimport numpy as np
def calculate_mae(img1, img2):
"""计算两幅图像之间的平均绝对误差"""
return np.mean(np.abs(img1.astype(np.float32) - img2.astype(np.float32)))
与MSE一样,MAE值越小表示上色结果越好。MAE和MSE都是像素级别的度量,但MAE对异常值的惩罚较轻。
对于图像上色任务,在LAB颜色空间中评估颜色准确性更为合适。LAB颜色空间的L通道表示亮度,a和b通道表示颜色信息。颜色误差专注于评估a和b通道的差异,忽略亮度差异。
其中 和 表示两幅图像在LAB颜色空间的a和b通道。
pythonimport cv2
import numpy as np
def rgb2lab(rgb_image):
"""将RGB图像转换为LAB颜色空间"""
lab_image = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2LAB)
return lab_image
def calculate_color_accuracy(img1, img2):
"""计算LAB颜色空间ab通道的颜色准确性"""
lab1 = rgb2lab(img1)
lab2 = rgb2lab(img2)
# 提取a和b通道
ab1 = lab1[:, :, 1:3]
ab2 = lab2[:, :, 1:3]
# 计算颜色通道的平均绝对误差
color_error = np.mean(np.abs(ab1.astype(np.float32) - ab2.astype(np.float32)))
return color_error
颜色误差值越小,表示上色结果的颜色与真实图像越接近。由于这个指标专注于颜色差异,它对上色任务特别有意义。
感知相似度(Learned Perceptual Image Patch Similarity, LPIPS)是基于深度学习的图像质量评估指标,它利用深度神经网络提取的特征来评估图像的感知相似度,更接近人类的视觉感知。
LPIPS通过预训练的卷积神经网络(如AlexNet、VGG等)提取图像特征,然后计算这些特征之间的距离:
其中:
pythonimport torch
import lpips
import torchvision.transforms as transforms
class LPIPS_Metric:
def __init__(self, device='cuda' if torch.cuda.is_available() else 'cpu'):
self.device = device
self.model = lpips.LPIPS(net='alex').to(device)
def calculate_lpips(self, img1, img2):
"""计算两幅图像之间的LPIPS感知距离"""
# 将numpy转换为torch张量
transform = transforms.ToTensor()
img1_tensor = transform(img1).unsqueeze(0).to(self.device)
img2_tensor = transform(img2).unsqueeze(0).to(self.device)
# 归一化到[-1, 1]
img1_tensor = img1_tensor * 2 - 1
img2_tensor = img2_tensor * 2 - 1
with torch.no_grad():
distance = self.model(img1_tensor, img2_tensor)
return distance.item()
LPIPS值越小,表示两幅图像在感知上越相似。LPIPS特别适合评估生成内容的质量,因为它能够抓住人类视觉系统关注的细节。
FID是评估生成图像质量的重要指标,特别适用于GAN等生成模型。它测量真实图像分布和生成图像分布之间的距离,使用预训练的Inception网络提取特征。
假设真实图像和生成图像的特征服从多元高斯分布,FID计算两个分布之间的距离:
其中:
pythonimport torch
import numpy as np
from scipy import linalg
import torchvision.models as models
import torchvision.transforms as transforms
from PIL import Image
from tqdm import tqdm
class FID_Metric:
def __init__(self, device='cuda' if torch.cuda.is_available() else 'cpu'):
self.device = device
self.model = models.inception_v3(pretrained=True).to(device)
self.model.eval()
# 移除分类器部分
self.model.fc = torch.nn.Identity()
# 设置图像变换
self.transform = transforms.Compose([
transforms.Resize((299, 299)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
def get_features(self, images_list):
"""从图像路径列表中提取特征"""
features = []
for img_path in tqdm(images_list, desc="提取特征"):
img = Image.open(img_path).convert('RGB')
img = self.transform(img).unsqueeze(0).to(self.device)
with torch.no_grad():
feat = self.model(img)
features.append(feat.cpu().numpy())
return np.concatenate(features, axis=0)
def calculate_fid(self, real_images, fake_images):
"""计算真实图像和生成图像之间的FID距离"""
real_features = self.get_features(real_images)
fake_features = self.get_features(fake_images)
# 计算均值和协方差
mu1, sigma1 = real_features.mean(axis=0), np.cov(real_features, rowvar=False)
mu2, sigma2 = fake_features.mean(axis=0), np.cov(fake_features, rowvar=False)
# 计算FID
diff = mu1 - mu2
covmean, _ = linalg.sqrtm(sigma1.dot(sigma2), disp=False)
if np.iscomplexobj(covmean):
covmean = covmean.real
fid = diff.dot(diff) + np.trace(sigma1) + np.trace(sigma2) - 2 * np.trace(covmean)
return fid
FID值越小,表示生成图像分布与真实图像分布越接近。FID能够检测出生成内容的多样性和质量,是评估上色模型整体性能的重要指标。
在实际应用中,我们通常需要对大量图像对进行评估。下面的代码展示了如何组织评估流程:
pythondef evaluate_images(image_groups, metrics_to_compute=None, use_lpips=True, use_fid=False):
"""评估模型性能"""
if metrics_to_compute is None:
metrics_to_compute = ['ssim', 'psnr', 'mse', 'mae', 'color_error']
# 初始化指标
metrics = {metric: [] for metric in metrics_to_compute}
if use_lpips:
lpips_metric = LPIPS_Metric()
metrics['lpips'] = []
# 处理每组图像
for name, paths in tqdm(image_groups.items(), desc="评估图像"):
# 加载图像
real_B = cv2.imread(paths['real_B_rgb'])
fake_B = cv2.imread(paths['fake_B_rgb'])
# 转换BGR为RGB
real_B = cv2.cvtColor(real_B, cv2.COLOR_BGR2RGB)
fake_B = cv2.cvtColor(fake_B, cv2.COLOR_BGR2RGB)
# 计算各项指标
if 'ssim' in metrics_to_compute:
metrics['ssim'].append(calculate_ssim(real_B, fake_B))
if 'psnr' in metrics_to_compute:
metrics['psnr'].append(calculate_psnr(real_B, fake_B))
if 'mse' in metrics_to_compute:
metrics['mse'].append(calculate_mse(real_B, fake_B))
if 'mae' in metrics_to_compute:
metrics['mae'].append(calculate_mae(real_B, fake_B))
if 'color_error' in metrics_to_compute:
metrics['color_error'].append(calculate_color_accuracy(real_B, fake_B))
if use_lpips:
metrics['lpips'].append(lpips_metric.calculate_lpips(real_B, fake_B))
# 计算FID(如果需要)
if use_fid:
real_images = [paths['real_B_rgb'] for paths in image_groups.values()]
fake_images = [paths['fake_B_rgb'] for paths in image_groups.values()]
fid_metric = FID_Metric()
fid_score = fid_metric.calculate_fid(real_images, fake_images)
metrics['fid'] = fid_score
return metrics
收集完所有指标后,我们需要进行统计分析和可视化,以便于理解模型性能:
pythondef summarize_metrics(metrics):
"""汇总指标并返回DataFrame"""
summary = {}
# 计算每个指标的统计数据
for metric_name, values in metrics.items():
if metric_name == 'fid': # FID是单一值
if values is not None:
summary[metric_name] = values
else:
if len(values) > 0:
summary[f"{metric_name}_mean"] = np.mean(values)
summary[f"{metric_name}_std"] = np.std(values)
summary[f"{metric_name}_min"] = np.min(values)
summary[f"{metric_name}_max"] = np.max(values)
return pd.DataFrame([summary])
def plot_metrics_distribution(metrics, output_dir):
"""绘制指标分布并保存到输出目录"""
os.makedirs(output_dir, exist_ok=True)
for metric_name, values in metrics.items():
if metric_name == 'fid': # 跳过FID,因为它是单一值
continue
plt.figure(figsize=(10, 6))
plt.hist(values, bins=30, alpha=0.7)
plt.title(f'Distribution of {metric_name.upper()}')
plt.xlabel(metric_name.upper())
plt.ylabel('Count')
plt.grid(True, alpha=0.3)
plt.savefig(os.path.join(output_dir, f'{metric_name}_distribution.png'))
plt.close()
为了全面评估上色结果,我们需要了解各指标的适用场景:
指标 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
SSIM | 考虑结构相似性,符合人类视觉感知 | 对颜色差异不够敏感 | 评估上色结果的结构保持度 |
PSNR | 计算简单,广泛使用 | 仅基于像素差异,不符合视觉感知 | 粗略评估上色质量 |
MSE | 计算简单,直观 | 不符合人类视觉感知 | 像素级差异的基准测量 |
MAE | 对异常值不敏感 | 同样不符合视觉感知 | 像素级差异的稳健测量 |
Color Error | 专注于颜色差异 | 忽略了结构信息 | 评估上色的颜色准确性 |
LPIPS | 接近人类视觉感知 | 计算复杂,依赖预训练模型 | 评估感知质量 |
FID | 评估整体分布相似度 | 需要大量样本,计算成本高 | 评估上色模型的整体性能 |
在实际应用中评估上色模型时,建议采取以下策略:
多指标综合评估:单一指标难以全面反映上色质量,应综合考虑多个指标。
权衡计算成本与精度:LPIPS和FID虽然更准确,但计算成本高,可根据实际需求选择。
考虑颜色准确性:对于上色任务,颜色误差是一个特别重要的指标。
结合主观评估:客观指标无法完全替代人类主观评价,可结合小规模的主观评测。
评估指标组合:
图像上色评估是一个多维度的问题,需要从结构相似性、像素差异、颜色准确性和感知质量等多个角度进行衡量。通过合理选择和组合不同指标,我们可以全面客观地评估上色模型的性能,为模型改进提供有力支持。
本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!