图像质量评估数据集主观评分解析实战指南
1. 图像质量评估数据集概述
图像质量评估(IQA)是计算机视觉领域的重要研究方向,其核心在于量化人类对图像质量的主观感知。主流IQA数据集通常包含三类数据:原始参考图像、经过不同失真类型和程度处理的失真图像,以及对应的人类主观评分(MOS/DMOS)。这些数据集为开发客观质量评估算法提供了基准测试平台。
目前学术界广泛使用的数据集包括:
LIVE数据集:德克萨斯大学奥斯汀分校于2006年发布,包含29幅原始图像和779幅失真图像,涵盖5种失真类型:
- JPEG压缩(175幅)
- JPEG2000压缩(169幅)
- 白噪声(145幅)
- 高斯模糊(145幅)
- 快速衰落(145幅)
TID2013数据集:包含25幅原始图像和3000幅失真图像,提供24种失真类型和5个失真级别,是目前失真类型最全面的数据集之一。
CSIQ数据集:奥克拉荷马州立大学发布,包含30幅原始图像和866幅失真图像,涵盖6种失真类型。
关键提示:DMOS(差异平均意见得分)值越小表示图像质量越好,而MOS(平均意见得分)值越大表示质量越好,不同数据集的评分范围需要特别注意。
2. 主观评分文件解析技术
2.1 LIVE数据集DMOS解析
LIVE数据集的主观评分存储在dmos.mat文件中,使用Python解析的完整代码如下:
import scipy.io import pandas as pd def parse_live_dmos(dataset_path): # 加载MAT文件 mat_data = scipy.io.loadmat(f'{dataset_path}/dmos.mat') # 提取关键数据 orgs = mat_data['orgs'][0] dmos = mat_data['dmos'][0] img_names = [name[0] for name in mat_data['dist_img'][0]] # 构建DataFrame df = pd.DataFrame({ 'image_name': img_names, 'dmos': dmos, 'is_reference': [name.startswith('refimgs') for name in img_names] }) # 过滤参考图像(DMOS为0) return df[~df['is_reference']].reset_index(drop=True)该函数返回包含图像文件名和对应DMOS值的DataFrame,参考图像已被自动过滤。
2.2 TID2013数据集MOS解析
TID2013的评分存储在Excel文件中,解析时需要处理多观察者评分:
import pandas as pd def parse_tid2013_mos(dataset_path): # 读取MOS数据 mos_data = pd.read_excel(f'{dataset_path}/mos_with_names.xlsx') # 计算平均MOS并标准化到0-9范围 observer_columns = [col for col in mos_data.columns if col.startswith('observer')] mos_data['MOS'] = mos_data[observer_columns].mean(axis=1) mos_data['MOS'] = mos_data['MOS'] * 9 / mos_data['MOS'].max() return mos_data[['image_name', 'MOS']]2.3 CSIQ数据集DMOS解析
CSIQ采用独特的DMOS计算方式,需要从原始评分文件重建:
import json import numpy as np def parse_csiq_dmos(dataset_path): with open(f'{dataset_path}/scores.json') as f: scores = json.load(f) # 按图像分组计算 image_scores = {} for score in scores: name = score['image'] if name not in image_scores: image_scores[name] = [] image_scores[name].append(score['rating']) # 计算DMOS(0-1范围) results = [] for name, ratings in image_scores.items(): dmos = np.mean(ratings) results.append({'image_name': name, 'dmos': dmos}) return pd.DataFrame(results)3. 多数据集统一处理框架
3.1 数据标准化处理
不同数据集的评分范围和分布存在差异,需要进行标准化:
def normalize_scores(df, dataset_name): if dataset_name == 'LIVE': df['score'] = df['dmos'] / 100 # LIVE的DMOS范围0-100 elif dataset_name == 'TID2013': df['score'] = df['MOS'] / 9 # TID2013的MOS范围0-9 elif dataset_name == 'CSIQ': df['score'] = df['dmos'] # CSIQ的DMOS已经是0-1 return df3.2 元数据整合
构建包含完整元数据的统一数据结构:
def build_metadata(df, dataset_name): # 提取失真类型和级别 df['distortion'] = df['image_name'].apply(lambda x: x.split('_')[1]) df['level'] = df['image_name'].apply(lambda x: int(x.split('_')[2])) # 添加数据集标识 df['dataset'] = dataset_name return df[['dataset', 'image_name', 'distortion', 'level', 'score']]3.3 完整处理流程
def process_all_datasets(base_path): datasets = { 'LIVE': parse_live_dmos, 'TID2013': parse_tid2013_mos, 'CSIQ': parse_csiq_dmos } all_data = [] for name, parser in datasets.items(): df = parser(f'{base_path}/{name}') df = normalize_scores(df, name) df = build_metadata(df, name) all_data.append(df) return pd.concat(all_data, ignore_index=True)4. 质量评分可视化与分析
4.1 失真类型影响分析
import seaborn as sns import matplotlib.pyplot as plt def plot_distortion_impact(df): plt.figure(figsize=(12, 6)) sns.boxplot(x='distortion', y='score', data=df) plt.title('Quality Score Distribution by Distortion Type') plt.xticks(rotation=45) plt.show()4.2 失真级别趋势分析
def plot_level_trend(df, distortion_type): subset = df[df['distortion'] == distortion_type] plt.figure(figsize=(8, 5)) sns.lineplot(x='level', y='score', data=subset, estimator='median', errorbar=None) plt.title(f'Quality Trend for {distortion_type}') plt.show()4.3 数据集间评分分布对比
def plot_dataset_comparison(df): plt.figure(figsize=(10, 6)) sns.violinplot(x='dataset', y='score', data=df) plt.title('Score Distribution Across Datasets') plt.show()5. 实战应用案例
5.1 构建IQA模型训练集
def prepare_training_data(df, test_ratio=0.2): from sklearn.model_selection import train_test_split # 按参考图像划分保证数据平衡 ref_images = df['image_name'].str.extract(r'(img\d+)')[0].unique() train_ref, test_ref = train_test_split(ref_images, test_size=test_ratio) train_mask = df['image_name'].str.contains('|'.join(train_ref)) return df[train_mask], df[~train_mask]5.2 评分一致性验证
def evaluate_consistency(df): # 计算同一失真类型/级别下的评分标准差 consistency = df.groupby(['distortion', 'level'])['score'].std() print(f'Average consistency: {consistency.mean():.4f}') # 可视化最不一致的案例 least_consistent = consistency.sort_values(ascending=False).head(5) least_consistent.plot(kind='bar', title='Top 5 Inconsistent Conditions')5.3 跨数据集验证策略
def cross_dataset_validation(models, df): from sklearn.metrics import mean_squared_error results = {} datasets = df['dataset'].unique() for train_ds in datasets: train = df[df['dataset'] == train_ds] for test_ds in datasets: if test_ds == train_ds: continue test = df[df['dataset'] == test_ds] model = models[train_ds] pred = model.predict(test[features]) mse = mean_squared_error(test['score'], pred) results[f'{train_ds}->{test_ds}'] = mse return pd.DataFrame.from_dict(results, orient='index', columns=['MSE'])6. 高级技巧与最佳实践
6.1 处理评分偏差
不同数据集可能存在的评分偏差校正方法:
def correct_bias(df, reference_scores): """ 使用参考图像评分校正数据集间偏差 reference_scores: 各数据集参考图像应得的理论评分 """ for dataset in df['dataset'].unique(): ref_score = reference_scores[dataset] current_ref = df[(df['dataset']==dataset) & (df['image_name'].str.contains('ref'))]['score'].mean() delta = ref_score - current_ref df.loc[df['dataset']==dataset, 'score'] += delta return df6.2 评分置信度估计
def estimate_confidence(df, min_ratings=5): """ 基于观察者数量估计评分置信度 """ if 'observer_count' not in df.columns: raise ValueError("DataFrame需要包含observer_count列") df['confidence'] = np.minimum(1, df['observer_count'] / min_ratings) return df6.3 高效数据加载器实现
class IQADataset(torch.utils.data.Dataset): def __init__(self, df, image_dir, transform=None): self.df = df self.image_dir = image_dir self.transform = transform def __len__(self): return len(self.df) def __getitem__(self, idx): row = self.df.iloc[idx] img_path = f"{self.image_dir}/{row['image_name']}" image = Image.open(img_path).convert('RGB') if self.transform: image = self.transform(image) return { 'image': image, 'score': torch.tensor(row['score'], dtype=torch.float32), 'distortion': row['distortion'], 'level': row['level'] }7. 常见问题解决方案
7.1 缺失评分处理
def handle_missing_scores(df): # 按失真类型和级别的中位数填充 fill_values = df.groupby(['distortion', 'level'])['score'].median() df['score'] = df.apply( lambda x: fill_values[x['distortion'], x['level']] if pd.isna(x['score']) else x['score'], axis=1 ) return df7.2 评分尺度不一致
def align_rating_scales(df, target_range=(0, 1)): min_target, max_target = target_range for dataset in df['dataset'].unique(): subset = df[df['dataset'] == dataset] min_score = subset['score'].min() max_score = subset['score'].max() df.loc[df['dataset'] == dataset, 'score'] = ( (subset['score'] - min_score) / (max_score - min_score) ) * (max_target - min_target) + min_target return df7.3 大规模数据集处理
def process_large_dataset(dataset_path, chunk_size=10000): full_df = pd.DataFrame() for chunk in pd.read_csv(f'{dataset_path}/scores.csv', chunksize=chunk_size): processed = preprocess_chunk(chunk) # 自定义预处理函数 full_df = pd.concat([full_df, processed]) return full_df