本文是对NIQE图像质量评价指标的代码解读,原文解读请看NIQE文章讲解。
本文的代码来源于IQA-Pytorch工程。

1、原文概要

NIQE实现了无参考的图像质量评价指标,可以有效地对图像的感知(Fidelity)质量进行评估。本文提出了一种完全盲目的图像质量评估(IQA)模型 —— 自然图像质量评估器(NIQE),它基于自然场景统计(NSS)模型,通过提取自然图像的统计特征构建多元高斯(MVG)模型,再计算测试图像特征与该模型的距离来评估质量。与需训练的现有模型不同,NIQE 无需依赖失真图像或人类主观评分,在 LIVE IQA 数据库上的性能优于 PSNR、SSIM 等全参考模型,且与当时顶级的无参考模型BRISQUE相当。
评估方法大致可以分为以下4个步骤,用下图表示。
在这里插入图片描述

  1. 提取quality aware的特征,这个特征来源于空间域自然场景统计模型(NSS模型)。
  2. 在图中选取合适的块来进行评估,作者设计了一种方法来选取图像中更能代表图像质量的块,而非全部使用。
  3. 从补丁中提取到的NSS特征使用零均值广义高斯分布(GGD)来进行拟合,拟合的分布参数作者会进一步送给多元高斯模型拟合使用。
  4. 使用步骤3的分布参数特征fit in一个multivariate Gaussian (MVG) model 多元高斯分布。

这样是完成了一次MVG模型的拟合。

为进一步得到NIQE指标,作者会首先选取来自Flickr无版权数据与Berkeley图像分割数据库的125张自然图像,分辨率范围480×320至1280×720,进行一次上述的过程得到一个标准的多元高斯分布。在测试时,只需要对待评估图像重复一次上述的过程并计算两个分布之间的马氏距离即可。马氏距离计算公式如下:
D(ν1,ν2,∑1,∑2)=(ν1−ν2)T(∑1+∑22)−1(ν1−ν2)\begin{aligned} D\left(\nu_{1}, \nu_{2}, \sum_{1}, \sum_{2}\right) &= \sqrt{ \left( \nu_{1} - \nu_{2} \right)^{T} \left( \frac{\sum_{1} + \sum_{2}}{2} \right)^{-1} \left( \nu_{1} - \nu_{2} \right) } \end{aligned}D(ν1,ν2,1,2)=(ν1ν2)T(21+2)1(ν1ν2)其中v1v_1v1v2v_2v2以及协方差矩阵是前面的多元高斯模型的参数。

2、代码结构

代码实现位于pyiqa/archs/niqe_arch.py中
在这里插入图片描述

3 、核心代码模块

NIQE

这个类实现了整体的参数传入与函数调用。

@ARCH_REGISTRY.register()
class NIQE(torch.nn.Module):r"""Args:- channels (int): Number of processed channel.- test_y_channel (bool): whether to use y channel on ycbcr.- crop_border (int): Cropped pixels in each edge of an image. Thesepixels are not involved in the metric calculation.- pretrained_model_path (str): The pretrained model path.References:Mittal, Anish, Rajiv Soundararajan, and Alan C. Bovik."Making a “completely blind” image quality analyzer."IEEE Signal Processing Letters (SPL) 20.3 (2012): 209-212."""def __init__(self,channels: int = 1,test_y_channel: bool = True,color_space: str = 'yiq',crop_border: int = 0,version: str = 'original',pretrained_model_path: str = None,) -> None:super(NIQE, self).__init__()self.channels = channelsself.test_y_channel = test_y_channelself.color_space = color_spaceself.crop_border = crop_borderif pretrained_model_path is not None:pretrained_model_path = pretrained_model_pathelif version == 'original':pretrained_model_path = load_file_from_url(default_model_urls['url'])elif version == 'matlab':pretrained_model_path = load_file_from_url(default_model_urls['niqe_matlab'])# load model parametersparams = scipy.io.loadmat(pretrained_model_path)mu_pris_param = np.ravel(params['mu_prisparam'])cov_pris_param = params['cov_prisparam']self.mu_pris_param = torch.from_numpy(mu_pris_param)self.cov_pris_param = torch.from_numpy(cov_pris_param)def forward(self, x: torch.Tensor) -> torch.Tensor:r"""Computation of NIQE metric.Input:x: An input tensor. Shape :math:`(N, C, H, W)`.Output:score (tensor): results of ilniqe metric, should be a positive real number. Shape :math:`(N, 1)`."""score = calculate_niqe(x,self.crop_border,self.test_y_channel,self.color_space,self.mu_pris_param,self.cov_pris_param,)return score

调用calculate_niqe函数得到结果。这里初始化会直接导入预训练的权重,即我们前面讲到的使用标准图像拟合的分布,保存在mu_pris和conv_pris中。

calculate_niqe 函数

实际计算的代码。

def calculate_niqe(img: torch.Tensor,crop_border: int = 0,test_y_channel: bool = True,color_space: str = 'yiq',mu_pris_param: torch.Tensor = None,cov_pris_param: torch.Tensor = None,**kwargs,
) -> torch.Tensor:"""Calculate NIQE (Natural Image Quality Evaluator) metric.Args:img (Tensor): Input image whose quality needs to be computed.crop_border (int): Cropped pixels in each edge of an image. Thesepixels are not involved in the metric calculation.test_y_channel (Bool): Whether converted to 'y' (of MATLAB YCbCr) or 'gray'.pretrained_model_path (str): The pretrained model path.Returns:Tensor: NIQE result."""# NIQE only support gray imageif img.shape[1] == 3:img = to_y_channel(img, 255, color_space)elif img.shape[1] == 1:img = img * 255img = diff_round(img)img = img.to(torch.float64)mu_pris_param = mu_pris_param.to(img).repeat(img.size(0), 1)cov_pris_param = cov_pris_param.to(img).repeat(img.size(0), 1, 1)if crop_border != 0:img = img[..., crop_border:-crop_border, crop_border:-crop_border]niqe_result = niqe(img, mu_pris_param, cov_pris_param)return niqe_result

又封装了一层,实际在niqe中发生。

niqe 函数

实际计算的代码。

def niqe(img: torch.Tensor,mu_pris_param: torch.Tensor,cov_pris_param: torch.Tensor,block_size_h: int = 96,block_size_w: int = 96,
) -> torch.Tensor:assert img.ndim == 4, ('Input image must be a gray or Y (of YCbCr) image with shape (b, c, h, w).')# crop imageb, c, h, w = img.shapenum_block_h = math.floor(h / block_size_h)num_block_w = math.floor(w / block_size_w)img = img[..., 0 : num_block_h * block_size_h, 0 : num_block_w * block_size_w]distparam = []  # dist param is actually the multiscale featuresfor scale in (1, 2):  # perform on two scales (1, 2)img_normalized = normalize_img_with_gauss(img, padding='replicate')distparam.append(blockproc(img_normalized,[block_size_h // scale, block_size_w // scale],fun=compute_feature,))if scale == 1:img = imresize(img / 255.0, scale=0.5, antialiasing=True)img = img * 255.0distparam = torch.cat(distparam, -1)# fit a MVG (multivariate Gaussian) model to distorted patch featuresmu_distparam = nanmean(distparam, dim=1)cov_distparam = nancov(distparam)# compute niqe quality, Eq. 10 in the paperinvcov_param = torch.linalg.pinv((cov_pris_param + cov_distparam) / 2)diff = (mu_pris_param - mu_distparam).unsqueeze(1)quality = torch.bmm(torch.bmm(diff, invcov_param), diff.transpose(1, 2)).squeeze()quality = torch.sqrt(quality)return quality

分为以下几步:

  1. 图像裁剪:
b, c, h, w = img.shape
num_block_h = math.floor(h / block_size_h)
num_block_w = math.floor(w / block_size_w)
img = img[..., 0 : num_block_h * block_size_h, 0 : num_block_w * block_size_w]

将输入图像裁剪为能被 block_size 整除的尺寸,避免边缘无法形成完整图像块的问题。

  1. 多尺度特征提取:
distparam = []  # 存储多尺度特征
for scale in (1, 2):  # 在两个尺度(1x和0.5x)上提取特征# 步骤1:高斯归一化预处理img_normalized = normalize_img_with_gauss(img, padding='replicate')# 步骤2:分块计算特征distparam.append(blockproc(img_normalized,[block_size_h // scale, block_size_w // scale],  # 尺度缩放时块大小同步缩小fun=compute_feature,  # 计算每个块的统计特征))# 步骤3:下采样到0.5x尺度(仅在第一个尺度后执行)if scale == 1:img = imresize(img / 255.0, scale=0.5, antialiasing=True)  # 下采样img = img * 255.0  # 恢复像素值范围

在两个尺度(原始尺度和 0.5 倍下采样尺度)上提取特征,模拟人类视觉系统的多尺度感知特性。normalize_img_with_gauss:对图像进行高斯滤波归一化(去除局部均值和对比度),这对应于NSS模型;blockproc:将图像分块,对每个块调用 compute_feature 提取统计特征(如广义高斯分布 GGD、非对称广义高斯分布 AGGD 的参数),对应论文中的分块特征提取部分。

  1. 特征拼接与 MVG 模型拟合:
# 拼接两个尺度的特征
distparam = torch.cat(distparam, -1)# 拟合失真图像的多元高斯(MVG)模型
mu_distparam = nanmean(distparam, dim=1)  # 特征均值向量
cov_distparam = nancov(distparam)        # 特征协方差矩阵

将多尺度特征拼接为一个特征向量,然后计算失真图像特征的均值和协方差,拟合 MVG 模型(nanmean 和 nancov 用于处理可能的 NaN 值(避免异常值影响统计特性))。

  1. 计算 NIQE 质量分数:
# 计算NIQE分数(论文公式10)
invcov_param = torch.linalg.pinv((cov_pris_param + cov_distparam) / 2)  # 平均协方差的伪逆
diff = (mu_pris_param - mu_distparam).unsqueeze(1)  # 均值差向量(扩展维度用于矩阵乘法)
# 马氏距离计算:sqrt[(μ1-μ2)^T * Σ_avg^{-1} * (μ1-μ2)]
quality = torch.bmm(torch.bmm(diff, invcov_param), diff.transpose(1, 2)).squeeze()
quality = torch.sqrt(quality)
return quality

利用概要中提到的niqe公式计算马氏距离。

3、总结

代码实现核心的部分讲解完毕,NIQE作为一个传统的无参考IQA指标,使用比较广泛。


感谢阅读,欢迎留言或私信,一起探讨和交流。
如果对你有帮助的话,也希望可以给博主点一个关注,感谢。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/95522.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/95522.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/95522.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

配置时钟分频与倍频

在STM32微控制器中,“配置时钟分频与倍频”是一个关键步骤,它允许开发者根据应用需求调整系统时钟的频率。以下是对这一概念的详细解释:时钟源与基础频率时钟源:STM32微控制器通常支持多种时钟源,如高速外部时钟&#…

【深度学习新浪潮】视觉大模型在预训练方面有哪些关键进展?

近年来,视觉大模型在预训练领域取得了多项突破性进展,涵盖架构设计、多模态融合、数据利用效率及训练策略等多个维度。以下结合2024-2025年最新研究成果,从技术创新和应用突破两方面展开分析: 一、架构创新:突破分辨率与模态限制 超高分辨率预训练 伯克利与英伟达提出的P…

Elasticsearch原理篇

Elasticsearch原理篇写在前面:用之于手,先明于心一、传统数据库的瓶颈:当数据量成为负担1. 千万级数据下的性能衰减2. 分页查询的“深水陷阱”3. 关联查询的扩展难题4. 全文检索能力薄弱二、Elasticsearch 的优势:为搜索而生的分布…

《我是如何用C语言写工控系统的漏洞和Bug》连载(1)内容大纲

第一部分:导论与基础 第1章 引言 1.1 工控系统的独特性和重要性 实时性、可靠性、长生命周期的要求与IT系统的差异:后果不再是信息泄露,而是物理世界的中断与破坏 1.2 为什么C语言依然是工控领域的主流? 性能、底层硬件操作、历史…

.Net程序员就业现状以及学习路线图(三)

一、.Net程序员就业现状分析 1. 市场需求与薪资水平 ‌市场需求两极分化‌:2025年数据显示,.Net开发岗位全国占比约0.009%,主要集中在深圳、上海等一线城市 2 3。高端岗位(云原生/AI集成方向)年薪可达36-60万&#xff…

云计算学习100天-第40天 -普罗米修斯1

目录 Prometheus 概述—— 安装prometheus 案例 环境说明 实验步骤 一、prometheus服务器配置时间同步 二、安装Prometheus服务器 配置文件说明 三、编写服务启动文件并启动服务 四、访问web页面 Prometheus 概述—— Prometheus是一个开源系统监控和警报工具包&a…

高效文本处理:cut、sort、uniq 和 tr 命令详解与实战

前言 🔪 一、cut —— 按列或字符截取 常用选项: 示例: 🔄 二、sort —— 排序(默认按行首字符升序) 常用选项: 示例: 🧼 三、uniq —— 去除连续重复行 常用选项…

时序数据库选型指南:Apache IoTDB为何成为工业物联网首选?

引言:时序数据管理的时代挑战 随着工业4.0和物联网技术的快速发展,全球时序数据呈现爆炸式增长。据IDC预测,到2025年,全球物联网设备产生的数据量将达到79.4ZB,其中超过60%为时序数据。这类数据具有显著特征&#xff…

Ubuntu查看开机以来修改的文件

获取本次开机时间 uptime -s获取开机时间之后修改的文件 find /home -type f -newermt "2025-09-03 18:10:12"解读:-type f意为只查找类型为“普通文件”(file),不包括目录、链接等。newermt 代表“修改时间比指定时间新…

差分隐私在运营指标:ABP 的 DP 计数器与噪声预算

🚦 差分隐私在运营指标:ABP 的 DP 计数器与噪声预算 📚 目录🚦 差分隐私在运营指标:ABP 的 DP 计数器与噪声预算0. TL;DR 🚀📈 一图看懂(写入→发布→预算→加噪)1. 背景…

洛谷 P1077 [NOIP 2012 普及组] 摆花-普及-

P1077 [NOIP 2012 普及组] 摆花 题目描述 小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共 mmm 盆。通过调查顾客的喜好,小明列出了顾客最喜欢的 nnn 种花,从 111 到 nnn 标号。为了在门口展出更多种花&…

时序数据库选型指南:为何Apache IoTDB成为工业物联网首选

引言:时序数据管理的挑战与机遇 在工业4.0与物联网技术深度融合的今天,全球设备产生的时序数据量正以指数级增长。据IDC预测,到2025年物联网设备产生的数据将达79.4ZB,其中60%为时序数据。这类数据具有高频采集(毫秒级…

【C++】C++入门—(中)

前言:上一篇文章我们介绍了C入门的一些基础的语法,将了命名空间,缺省参数等。这篇文章我们就来介绍剩余的语法。 文章目录一,函数重载二,引用2.1引用的概念和定义2.2引用的特性2.3引用的引用场景2.3.1做函数形参&#…

嵌入式Linux驱动开发:i.MX6ULL按键中断驱动(非阻塞IO)

嵌入式Linux驱动开发:i.MX6ULL按键中断驱动(非阻塞IO) 概述 本文档详细介绍了在i.MX6ULL开发板上实现按键中断驱动的完整过程。该驱动程序实现了非阻塞IO操作,允许用户空间应用程序通过poll系统调用高效地监控按键状态变化&…

从 @Schedule 到 XXL-JOB:分布式定时任务的演进与实践

从Schedule到XXL-JOB:分布式定时任务的演进与实践 在分布式系统中,定时任务是常见需求(如数据备份、报表生成、缓存刷新等)。Spring框架的Schedule注解虽简单易用,但在集群环境下存在明显局限;而XXL-JOB作为…

阿里云营业执照OCR接口的PHP实现与技术解析:从签名机制到企业级应用

一、阿里云营业执照OCR接口的核心技术架构 阿里云OCR服务基于深度学习模型和大规模数据训练,针对中国营业执照的版式特征(如统一社会信用代码位置、企业名称排版、经营范围换行规则等)进行了专项优化,识别准确率可达98%以上。其接口调用遵循RESTful API设计规范,采用HMAC…

AI人工智能大模型应用如何落地

AI人工智能大模型应用落地需要经过以下步骤: 明确应用场景和目标:首先需要明确AI大模型在哪个领域、解决什么问题。例如,在智能客服领域,AI大模型可以用于提高客户服务的效率和质量;在医学领域,AI大模型可以…

手写Muduo网络库核心代码2--Poller、EPollPoller详细讲解

Poller抽象层代码Muduo 网络库中的 Poller 抽象层是其事件驱动模型的核心组件之一,负责统一封装不同 I/O 复用机制(如 epoll、poll),实现事件监听与分发。Poller 抽象层的作用统一 I/O 复用接口Poller 作为抽象基类,定…

基于MCP架构的OpenWeather API服务端设计与实现

随着微服务和模块化架构的发展,越来越多的系统倾向于采用可插拔、高内聚的设计模式。MCP(Modular, Collaborative,Pluggable)架构正是这样一种强调模块化、协作性和扩展性的设计思想。它允许开发者以“组件”方式组合功能,提升系统的灵活性与可维护性。 …

从“叠加”到“重叠”:Overlay 与 Overlap 双引擎驱动技术性能优化

在技术领域,“Overlay”和“Overlap”常因拼写相似被混淆,但二者实则代表两种截然不同的优化逻辑:Overlay 是“主动构建分层结构”,通过资源复用与隔离提升效率;Overlap 是“让耗时环节时间交叉”,通过并行…