快捷通道一:不看背景科普废话,直达本文主题

快捷通道二:不想看正文废话,直达运行主程序


图像质量评估-IQA

图像超分辨率(Image Super Resolution)

超分辨率(Super-Resolution)即通过硬件或软件的方法提高原有图像的分辨率,通过一系列低分辨率的图像来得到一幅高分辨率的图像过程就是超分辨率重建。超分辨率重建的核心思想就是用时间带宽(获取同一场景的多帧图像序列)换取空间分辨率,实现时间分辨率向空间分辨率的转换。

图像超分方法

图像超分就是让模糊图片变清晰的技术,目前主流方法分三类:基于插值、基于重建和基于学习。

图像超分方法 原理 优点 缺点
基于插值的方法 通过数学公式(如双线性、双三次插值)在像素
间 “猜” 新值,放大图像
计算快,适合实时处理 边缘易模糊,细节恢复差,可能存在锯齿、模糊、块状效应
基于重建的方法 利用多张低分辨率图像或先验知识(如 SRCNN 早期非深度学习
方法、稀疏编码、非局部均值)优化重建,解决退化模型问题
细节保留更好,适合医学
影像等专业领域
计算复杂,耗时较长,可能存在过平滑、边缘失真、振铃效应。
基于学习的方法 用深度学习模型(如 CNN、GAN)从大量数据
中学习低分辨率到高分辨率的映射
细节和纹理恢复最自然,效果最好 需大量数据和算力,模型可能过拟合,
可能存在纹理幻觉、结构错位、高频噪声(如 GAN 伪影)

图像质量评方法估分类

图像超分客观评估方法

评估方法分类

评估应用提示

相关工具推荐

IQA-PyTorch 及其应用

官方介绍翻译

IQA-PyTorch 是一个基于纯 Python 和 PyTorch 构建的全面图像质量评估(IQA)工具包。我们重新实现了许多广泛使用的全参考(FR)和无参考(NR)指标,在有官方 MATLAB 脚本的情况下,结果均已针对其进行校准。借助 GPU 加速,我们的实现比其 Matlab 对应版本快得多。

仓库地址

环境准备

无法联网(HuggingFace)的环境

import os
os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"

或:

# Linux/Mac
export HF_ENDPOINT=https://hf-mirror.com

# Windows
set HF_ENDPOINT=https://hf-mirror.com

做如上设置后,仍然存在类似相关报错(安全起见,建议开始就使用这种方法,全部使用本地部署的方式,哪怕能够连上 HF): (MaxRetryError("HTTPSConnectionPool(host='hf-mirror.com' Max retries exceeded with url: **/model.safetensors,那么按照下面三个步骤操作:

HF 模型下载 网页中选择目标 pth 文件下载到本地,如果无法访问,自行查找科学上网方法或请人帮忙下载

修改源文件: %USERPROFILE%\AppData\Local\Programs\Python\Python310\Lib\site-packages\pyiqa\archs\hypernet_arch.py

self.base_model = timm.create_model(
    # 修改 pretrained=True 为 pretrained=False
    base_model_name, pretrained=True, features_only=True
)

步骤一中下载的权重文件可以直接保存到 %USERPROFILE%\\.cache\torch\hub\pyiqa下,这样程序中可以不用指定路径使用默认的权重文件进行加载。也可以下载到固定的目录,加载时自行指定路径:

metric = pyiqa.create_metric('qualichlip', pretrained=False)
metric.load_weights('your_path/QualiCLIP.pth')

metric = pyiqa.create_metric('qualichlip', pretrained_model_path='your_path/QualiCLIP.pth')

解决 load_state_dict 报错问题

运行主程序获取结果

指标使用说明

使用提示和个人见解

自定义模型训练与数据集使用

IQA-PyTorch 项目为 CLIPIQA、CNNIQA、DBCNN、HyperNet、NIMA、QualiCLIP、TOPIQ、WaDIQaM 这几个深度学习类神经网络模型提供了可自定义训练的默认数据集配置,在项目 options/train 目录下,以 QualiCLIP 的 KonIQ-10k 数据集为例,配置为 options/train/QualiCLIP/train_QualiCLIP_koniq10k.yml 文件。

训练配置通常包含 学习率及其调度策略、批量大小、训练周期数、优化器选择、损失函数配置,用户可以根据自己的硬件条件和数据集特性调整这些参数,以获得最佳的训练效果。clone 完项目,下载好对应的数据集,修改好训练配置后就可以开始自行训练:

# 在项目根目录下
python ./pyiqa/train.py --opt options/train/train_QualiCLIP_koniq10k.yml

全部可自定义训练的配置:

模型名称 数据集(需用户指定) 配置文件名(示例)
CLIPIQA KonIQ-10k train_CLIPIQA_koniq10k.yml
CNNIQA KonIQ-10k train_CNNIQA.yml
DBCNN LIVEC
KonIQ-10k
TID2008
train_DBCNN.yml
train_DBCNN_koniq10k.yml
train_DBCNN_tid.yml
HyperNet KonIQ-10k train_HyperNet.yml
NIMA AVA
KonIQ-10k
SPAQ
train_NIMA.yml
train_NIMA_inception_ava.yml
train_NIMA_inception_koniq.yml
train_NIMA_inception_spaq.yml
QualiCLIP live
KonIQ-10k
SPAQ
train_QualiCLIP_clive.yml
train_QualiCLIP_flive.yml
train_QualiCLIP_koniq10k.yml
train_QualiCLIP_spaq.yml
TOPIQ resnet50_ava
CGFIQA
GFIQA
KonIQ-10k
Swin_ava
Swin_CGFIQA
train_TOPIQ_res50_ava.yml
train_TOPIQ_res50_cgfiqa.yml
train_TOPIQ_res50_gfiqa.yml
train_TOPIQ_res50_koniq.yml
train_TOPIQ_swin_ava.yml
train_TOPIQ_swin_cgfiqa.yml
WaDIQaM general_iqa_dataset
KonIQ-10k
train_WaDIQaM_FR_kadid.yml
train_WaDIQaM_NR_koniq.yml

图像评分主计算程序

import pyiqa
import torch
import os
import time
import glob
import shutil
import os.path as osp
import logging
import piexif
import metric_conf as mc
from PIL import Image
from pillow_heif import register_heif_opener

# 配置日志
logging.basicConfig(level=logging.INFO, format='[%(asctime)s] [%(levelname)s] %(message)s')
logger = logging.getLogger(__name__)

# 如非调试, 关闭大部分日志, 修改源文件, 删除一些不必要的 print
pyiqa_logger = logging.getLogger('pyiqa')
pyiqa_logger.setLevel(logging.ERROR)


def ts_from_file_name(file_name, begin_index = 0):
    name_arr = file_name.rsplit(".", 1)[0].split("_")
    index1, index2, index3 = begin_index, begin_index + 1, begin_index + 2
    cut_time = name_arr[index2] if len(name_arr[index2]) == 6 else name_arr[index2][0:6]
    timestamp = f"{name_arr[index1]}_{cut_time}"
    if len(name_arr) > index3 and name_arr[index3].isdigit() and len(name_arr[index3]) == 1:
        timestamp += f"_{name_arr[index3]}"
    return timestamp


def convert_heif_to_rgb(heic_path, delete_heic=False):
    """
    heic 格式转换到 jpg 格式, 画质会大幅损失, 哪怕quality设置为95%
    """
    register_heif_opener()
    heif_name = osp.basename(heic_path)
    image_name = osp.splitext(heif_name)[0]
    jpg_path = osp.join(osp.dirname(heic_path), f'{image_name}.jpg')

    with Image.open(heic_path) as image:
        rgb_image = image.convert('RGB')
        exif_bytes = image.info.get('exif')
        save_kwargs = {'quality': 95, 'subsampling': 1}

        if exif_bytes:
            try:
                exif_dict = piexif.load(exif_bytes)
                save_kwargs['exif'] = piexif.dump(exif_dict)
            except Exception as e:
                logger.error(f"error while handling exif info: {e}")

        if osp.exists(jpg_path):
            os.remove(jpg_path)
        rgb_image.save(jpg_path, **save_kwargs)
        logger.warning(f'image {heif_name} converted to jpg, quality will be reduced a lot')

    if delete_heic:
        os.remove(heic_path)
        logger.info(f'heif image {heic_path} removed')

    return jpg_path


def get_timestamp_list(lr_dir, ts_begin_index = 0):
    time_set = []
    for ff in os.listdir(lr_dir):
        fp = osp.join(lr_dir, ff)
        if osp.isdir(fp):
            continue
        ts = ts_from_file_name(ff, ts_begin_index)
        if ts not in time_set:
            time_set.append(ts)

    return time_set


def metric_score_align(score, max_value, lower_better):
    if not isinstance(score, (int, float)):
        logger.error(f"Score parameter: {score} is not a number!")
        raise TypeError("Score must be a number")

    if score == 0:
        return score

    # 基于当前AI的水平, 限制0除外的评估结果的上下限, 下限为最大值的10%, 上限为最大值的80%, 这样可以控制评估结果浮动的区间
    reduced_score = max(score, max_value * 0.1) if score < max_value * 0.1 else min(score, max_value * 0.8)
    if max_value <= 1:
        # 最大50, 最小5
        return reduced_score * 50 if not lower_better else 5 / reduced_score
    if max_value <= 10:
        # 最大50, 最小5
        return reduced_score * 5 if not lower_better else 50 / reduced_score
    if max_value <= 100:
        # 最大50, 最小: 5 if lower_better else 6.25
        return reduced_score * 0.625 if not lower_better else 400 / reduced_score
    return reduced_score


def iqa_score_calc(lr_dir, hr_dir, ts_list, metric_conf):
    """
    通用图像质量评估分数计算函数

    参数:
        lr_dir: 输入图片目录
        hr_dir: 输出图片目录
        ts_list: 时间戳列表
        metric_conf: 评估指标配置

    返回:
        包含各时间戳分数的字典
    """
    metric_class = metric_conf['metric_class'].upper()
    metric_name = metric_conf['metric_name']
    if metric_conf['evaluate_object'] == 'folder':
        return dir_score_calc(lr_dir, hr_dir, ts_list, metric_conf)

    has_weights = 'weights_path' in metric_conf and metric_conf['weights_path']
    device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
    metric = pyiqa.create_metric(metric_name, device=device, pretrained=not has_weights)
    # 如果用户配置和指定了权重文件就加载
    if has_weights:
        metric.load_weights(metric_conf['weights_path'], weight_keys='params')
    scores = dict()
    image_count = len(ts_list)

    for index, ts in enumerate(ts_list):
        lr_files = glob.glob(osp.join(lr_dir, f"{ts}_iso*.jpg"))
        hr_files = glob.glob(osp.join(hr_dir, f"{ts}_iso*.heic"))
        hr_files += glob.glob(osp.join(hr_dir, f"{ts}_iso*.jpg"))

        if (metric_class == 'FR' and len(lr_files) == 0) or len(hr_files) == 0:
            logger.warning(f"no image found by timestamp {ts}")
            continue

        lr_file = lr_files[0] if metric_class == 'FR' else None
        hr_file = hr_files[0]
        index_text = f"{'' if index >= 9 or image_count < 10 else '0'}{index + 1} / {image_count}"

        try:
            scores[ts] = dict()
            if hr_file.endswith(".heic"):
                hr_file = convert_heif_to_rgb(hr_file)

            score = metric(hr_file).item() if metric_class == 'NR' else metric(hr_file, lr_file).item()
            scores[ts][metric_name] = score
            logger.info(f"[{index_text}]: [{ts}] {metric_name}_score: {score:.2f}")
        except Exception as e:
            logger.error(f"[{index_text}]: [{ts}] error while calculating {metric_name} score: {e}")
            scores[ts][metric_name] = 0.0

    return scores


def dir_score_calc(lr_dir, hr_dir, ts_list, metric_conf):
    """
    按照文件夹进行图像质量评估分数计算

    参数:
        lr_dir: 输入图片目录
        hr_dir: 输出图片目录
        ts_list: 时间戳列表
        metric_conf: 评估指标配置

    返回:
        包含各时间戳分数的字典
    """
    metric_name = metric_conf['metric_name']
    has_weights = 'weights_path' in metric_conf and metric_conf['weights_path']
    device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
    metric = pyiqa.create_metric(metric_name, device=device, pretrained=not has_weights)
    # 如果用户配置和指定了权重文件就加载
    if has_weights:
        metric.load_weights(metric_conf['weights_path'], weight_keys='params')
    scores = dict()
    image_count = len(ts_list)

    for index, ts in enumerate(ts_list):
        lr_files = glob.glob(osp.join(lr_dir, f"{ts}_iso*.jpg"))
        hr_files = glob.glob(osp.join(hr_dir, f"{ts}_iso*.heic"))
        hr_files += glob.glob(osp.join(hr_dir, f"{ts}_iso*.jpg"))
        index_text = f"{'' if index >= 9 or image_count < 10 else '0'}{index + 1} / {image_count}"
        if len(lr_files) == 0 or len(hr_files) == 0:
            logger.warning(f"no image found by timestamp {ts}")
            continue

        lr_file = lr_files[0]
        hr_file = hr_files[0]

        try:
            scores[ts] = dict()
            if hr_file.endswith(".heic"):
                hr_file = convert_heif_to_rgb(hr_file)

            temp_hr_dir = osp.join(hr_dir, osp.basename(hr_file))
            temp_hr_dir = osp.splitext(temp_hr_dir)[0]
            if osp.exists(temp_hr_dir):
                shutil.rmtree(temp_hr_dir)
            os.makedirs(temp_hr_dir, exist_ok=True)
            # 最少 2 张才能正常运行
            shutil.copy(hr_file, osp.join(temp_hr_dir, '1.jpg'))
            shutil.copy(hr_file, osp.join(temp_hr_dir, '2.jpg'))

            temp_lr_dir = osp.join(lr_dir, osp.basename(lr_file))
            temp_lr_dir = osp.splitext(temp_lr_dir)[0]
            if osp.exists(temp_lr_dir):
                shutil.rmtree(temp_lr_dir)
            os.makedirs(temp_lr_dir, exist_ok=True)
            # 最少 2 张才能正常运行
            shutil.copy(lr_file, osp.join(temp_lr_dir, '1.jpg'))
            shutil.copy(lr_file, osp.join(temp_lr_dir, '2.jpg'))

            score = metric(temp_hr_dir, temp_lr_dir).item()
            scores[ts][metric_name] = 0.0 if score < 0.1 else score
            logger.info(f"[{index_text}]: [{ts}] {metric_name}_score: {score:.2f}")
            shutil.rmtree(temp_hr_dir)
            shutil.rmtree(temp_lr_dir)
        except Exception as e:
            logger.error(f"[{index_text}]: [{ts}] error while calculating {metric_name} score: {e}")
            scores[ts][metric_name] = 0.0

    return scores


def evaluate_with_conf(lr_dir, hr_dir, ts_begin_index=0):
    """
    图像综合质量评估分数计算过程

    参数:
        lr_dir: 输入图片目录
        hr_dir: 输出图片目录
        ts_begin_index: 时间戳在文件中出现的位置, 所有文件名格式必须统一, 例如: 20251021_142422_iso100_20.0X_IP17Pro_HR.jpg
    """
    ts_list = get_timestamp_list(lr_dir, ts_begin_index)
    # 计算函数里, scores 在字典各个深度上一定要给个初始默认值, 否则后续需要做额外判断
    composite_scores, enabled_count = dict(), 0

    for metric in mc.metrics:
        if not metric['current_enabled']:
            continue

        scores = dict()
        enabled_count += 1
        metric_class = metric['metric_class'].upper()
        metric_name = metric['metric_name']
        better_mark = '低分更优' if metric['lower_better'] else '高分更优'

        logger.info(f"======================= 开始使用 {metric_class} 指标 [{metric_name.upper()} ({better_mark})] 评估图像 =======================")
        if metric_class in ['NR', 'FR']:
            scores = {**iqa_score_calc(lr_dir, hr_dir, ts_list, metric), **scores}
        else:
            logger.error(f"unsupported metric class [{metric_class}] of metric [{metric_name}]")
            continue

        for ts in ts_list:
            if ts not in scores:
                scores[ts] = dict()
            if ts not in composite_scores:
                composite_scores[ts] = dict()
            if metric_name not in scores[ts]:
                scores[ts][metric_name] = 0.0

            composite_scores[ts] = {**composite_scores[ts], **scores[ts]}

    if enabled_count == 0:
        logger.info(f"**************** 没有配置任何计算指标, 请检查 metric.conf 中的 current_enabled 配置 ****************")
        return

    for ts in ts_list:
        if ts not in composite_scores:
            continue
        composite_score, file_error, aigc_fail = 0.0, False, False
        for metric_name, score in composite_scores[ts].items():
            metric = [m for m in mc.metrics if m['metric_name'] == metric_name][0]
            if score == 0.0:
                if metric['metric_class'] == 'folder':
                    aigc_fail = True
                else:
                    file_error = True
                break
            composite_score += metric_score_align(score, metric['value_range'][1], metric['lower_better'])

        # 每个指标最大50分, 将结果控制到100分内
        composite_score = 2 * composite_score / enabled_count

        if file_error:
            logger.info(f"**************** [{ts}] 文件错误, 比如无权限或输入输出被不合法的旋转造成shape不一致等 ****************")
            continue
        if aigc_fail:
            logger.info(f"**************** [{ts}] AIGC疑似未生效, 输入和输出图像非常接近 ****************")
            continue
        logger.info(f"**************** [{ts}] 综合得分: {composite_score:.2f} ****************")


if __name__ == '__main__':
    """
    验证过的指标请参考 README.md, 启用哪些指标来评估, 通过 metric_conf.py 的 current_enabled 来配置
    推荐 NR-无参考 指标: 
        'qualiclip'     准确性好, 一张4k图使用CPU约需要8~10s, NR首选
    推荐 FR-全参考 指标: 
        'sfid'          对 AI-SR 生成效果评估能力较好, 速度一般, 非AIGC不准
        'lpips+'        准确性较好, 一张4k图使用CPU约需要2~3s, FR首选
    """

    lr_dir = r'D:\images\temp\test_LR'
    hr_dir = r'D:\images\temp\test_HR'

    # ts_begin_index: 时间戳在文件中出现的位置, 所有文件名格式必须统一, 例如: 20251021_142422_iso100_20.0X_IP17Pro_HR.jpg
    evaluate_with_conf(lr_dir=lr_dir, hr_dir=hr_dir, ts_begin_index=0)

附一: 经过实测的部分指标(一知半解,出错或不适用勿怪)

全部指标参见官方文档 METRICS

全参考指标名 提出时间 值的大小说明 评估结果说明 结果值范围
sfid 2024 低分代表高质量 准确性较好,主要用于生成模型(如 GAN)的评估,其核心是‌统计学方法 0~100
fid 2024 低分代表高质量 准确性较好,主要用于生成模型(如 GAN)的评估,其核心是‌统计学方法 0~100
lpips 2018 低分代表高质量 神经网络类指标,一张 4k 图使用 CPU 约需要 3s 0~1
lpips+ 2020 低分代表高质量 神经网络类指标,准确性远胜 lpips,一张 4k 图使用 CPU 约需要 3s,FR 首选 0~1
stlpips 2020 低分代表高质量 神经网络类指标,准确性较好,一张 4k 图使用 CPU 约需要 10~15s 0~1
lpips-vgg 2018 低分代表高质量 神经网络类指标,32G 内存的 Windows11 PC 无法支撑其内存需求 0~1
lpips-vgg+ 2023 低分代表高质量 神经网络类指标,32G 内存的 Windows11 PC 无法支撑其内存需求 0~1
stlpips-vgg 2020 低分代表高质量 神经网络类指标,32G 内存的 Windows11 PC 无法支撑其内存需求 0~1
nlpd 2006 低分代表高质量 一张 4k 图使用 CPU 约需要 2s 0~1
gmsd 2014 低分代表高质量 梯度幅度相似性偏差 0~1
dists 2020 低分代表高质量 神经网络类指标,图像深度相似性,计算所需的空闲内存至少 20GB 0~1
psnr 2002 高分代表高质量 传统峰值信噪比指标,准确性可信但对于 AIGC 来说参考意义不大 0~100
ssim 2004 高分代表高质量 结构相似性,计算所需的空闲内存至少 20GB 0~1
ms_ssim 2003 高分代表高质量 多尺度结构相似性,计算所需的空闲内存至少 12GB 0~1
cw_ssim 2010 高分代表高质量 带权重的结构相似性,计算所需的空闲内存至少 20GB 0~1
fsim 2011 高分代表高质量 特征相似性,一张 4k 图使用 CPU 约需要 2~5s,准确性一般,对于 AIGC 来说参考意义不大 0~1
ahiq 2014 高分代表高质量 神经网络类指标,一张 4k 图使用 CPU 约需要 110~120s 0~1
wadiqam_fr 2018 高分代表高质量 神经网络类指标,加权平均深度图像质量度量,现有模型评估结果为负数,暂不采用 -1~1
无参考指标名 提出时间 值的大小说明 评估结果说明 结果值范围
qualiclip 2025 高分代表高质量 神经网络类指标,清晰度评估相对准确,一张 4k 图使用 CPU 约需要 8~10s,NR 首选 0~1
dbcnn 2019 高分代表高质量 神经网络类指标,清晰度评估相对准确,一张 4k 图使用 CPU 约需要 15~30s 0~1
niqe 2012 低分代表高质量 清晰度评估相对准确,matlab 模型,一张 4k 图使用 CPU 约需要 5s 0~10+
niqe_matlab 2012 低分代表高质量 清晰度评估相对准确,matlab 模型,一张 4k 图使用 CPU 约需要 5s 0~10+
cnniqa 2014 高分代表高质量 神经网络类指标,清晰度评估相对准确,一张 4k 图使用 CPU 约需要 3s 0~1
musiq 2021 高分代表高质量 神经网络类指标,清晰度评估相对准确,一张 4k 图使用 CPU 约需要 70~90s 0~1
ilniqe 2015 低分代表高质量 matlab 模型,准确性一般 0~20
hyperiqa 2020 高分代表高质量 神经网络类指标,现有模型区分度一般,在‌预测准确性‌上领先,适合高精度评估,计算开销大 0~100
nima 2018 高分代表高质量 神经网络类指标,现有模型区分度一般,在‌美学感知‌上最贴近人类偏好,但对技术失真不敏感 0~10
piqe 2015 低分代表高质量 现有模型区分度较差 0~100
arniqa 2023 高分代表高质量 神经网络类指标,现有模型区分度较差 0~1
brisque 2012 低分代表高质量 神经网络类指标,现有模型区分度较差 0~100
pi 2018 低分代表高质量 不可用 0~100
maniqa 2022 高分代表高质量 神经网络类指标,不可用 0~100
nrqm 2016 高分代表高质量 matlab 模型,不可用,没有任何输出 0~1
clipiqa 2023 高分代表高质量 神经网络类指标,准确性尚可,但区分度不高,一张 4k 图使用 CPU 约需要 8s 0~1
maclip 2024 高分代表高质量 神经网络类指标,截至 pyiqa-0.1.14.1,尚未实现 0~1
liqe 2023 高分代表高质量 准确性尚可,一张 4k 图使用 CPU 约需要 1s 0~1
paq2piq 2020 高分代表高质量 神经网络类指标,偏向人类主观感知质量,对真实世界复杂失真(如手机拍摄)具有强泛化能力 0~1
topiq_nr 2023 高分代表高质量 神经网络类指标,偏向衡量图像质量对下游视觉任务性能的影响,不适用 0~1
tres 2023 高分代表高质量 旨在衡量图像质量对下游视觉任务性能的影响,而非人类主观感知,不适用 0~1

附二: metric_conf.py

# coding=utf-8
# 这些个指标的配置内容太长了,无法保存发布,只好删掉样例中没启用的
"""
    'metric_name': 指标名称
    'metric_class': 分为FR-全参考评估、NR-无参考评估
    'current_enabled': 当前项目质量评估是否启用, 其实可以将metrics拆分成启用和未启用的两个, 更方便调试
    'weights_path': 用户自己指定或者训练的权重文件, 不指定会按照官方默认的文件加载
    'evaluate_object': 评估对象, 分为指定文件 (绝大多数指标), 或者指定目录 (如fid、sfid等)
    'can_be_used': 该指标是否经过验证可用, 有些指标实现上有问题, 有些网络环境不支持, 有些准确性太差
    'lower_better': 是否低分代表高质量
    'value_range': 取值范围, 闭区间
    'created_at': 指标提出/创建年份
    'description': 该指标的一些描述, 建议补全其作用和测试验证的效果信息
"""

metrics = [
    {
        'metric_name': 'sfid',
        'metric_class': 'fr',
        'current_enabled': True,
        'weights_path': '',
        'evaluate_object': 'folder',
        'can_be_used': True,
        'lower_better': True,
        'value_range': [0, 100],
        'created_at': 2024,
        'description': '准确性较好, 主要用于生成模型 (如GAN) 的评估,衡量生成图像与真实图像在‌特征空间分布‌上的相似性,其核心是‌统计学方法'
    },
    {
        'metric_name': 'qualiclip',
        'metric_class': 'nr',
        'current_enabled': True,
        'weights_path': '',
        'evaluate_object': 'file',
        'can_be_used': True,
        'lower_better': False,
        'value_range': [0, 1],
        'created_at': 2025,
        'description': '神经网络类指标, 准确性好, 一张4k图使用CPU约需要8~10s, NR首选'
    },
    {
        'metric_name': 'lpips+',
        'metric_class': 'fr',
        'current_enabled': True,
        'weights_path': '',
        'evaluate_object': 'file',
        'can_be_used': True,
        'lower_better': True,
        'value_range': [0, 1],
        'created_at': 2020,
        'description': '神经网络类指标, 准确性较好, 一张4k图使用CPU约需要2~3s, FR首选'
    }
]


↙↙↙阅读原文可查看相关链接,并与作者交流