超分辨率指标计算:Python代码用于评估图像质量,PSNR、SSIM、LPIPS和NIQE

本文主要是介绍超分辨率指标计算:Python代码用于评估图像质量,PSNR、SSIM、LPIPS和NIQE,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

整体目标与设计思想

整体目标

这个Python脚本主要用于评估图像质量,它比较了一组高清(HD)图像和对应的生成图像,并计算了四种不同的图像质量指标:PSNR、SSIM、LPIPS和NIQE。

设计思想

  1. 模块化: 代码通过函数进行模块化,每个函数负责一个特定任务,如计算PSNR或SSIM。
  2. 并行化: 使用多进程来加速图像处理,特别是在处理大量图像时。
  3. 可扩展性: 可以容易地添加更多的图像质量指标。
  4. 结果记录: 为每个高清图像生成一个详细的文本文件,记录与之相关的生成图像的所有质量指标。

功能模块解析

初始化LPIPS模型

在代码开始,使用了LPIPS库来初始化一个预训练的VGG网络,这用于后续的LPIPS图像质量评估。

loss_fn = lpips.LPIPS(net='vgg')

图像质量评估函数

calculate_psnr, calculate_ssim

这两个函数分别使用OpenCV和skimage库来计算PSNR和SSIM。这些都是全参考指标,需要原图和生成图进行比较。

calculate_lpips

这个函数使用初始化的LPIPS模型来评估两个图像(原图和生成图)之间的感知差异。

calculate_niqe

这个函数实现了NIQE(无参考图像质量评估),即只需要一个图像即可评估其质量。

主要的图像处理函数:process_image()

这个函数是代码的核心,它执行以下操作:

  1. 读取高清图像和生成图像: 使用OpenCV的cv2.imread方法。
  2. 初始化质量指标: 初始化用于存储最佳质量指标的变量。
  3. 计算并记录指标: 对于每个生成图像,计算所有的质量指标,并记录最佳值。
  4. 结果存储: 将计算的质量指标保存到一个文本文件。

并行处理

使用Python的multiprocessing.Pool来并行处理所有高清图像。这是一种典型的"Map-Reduce"模式,其中process_image函数是map操作。

with Pool(4) as pool:  # Initialize a pool with 4 processespool.starmap(process_image, [(i, main_output_file_path, hd_img_folder, generated_img_root_folder, output_root_folder) for i in range(1, 570)])

性能和优化

  1. IO操作: 由于代码涉及大量的文件读写(图像和文本),IO可能成为性能瓶颈。
  2. 并行优化: 使用多进程可以显著加速处理时间,但要注意不要超过系统的CPU核心数。

最佳实践与改进建议

  1. 配置文件或命令行参数: 硬编码(如路径和进程数)应避免,最好使用配置文件或命令行参数。
  2. 错误处理: 当前代码没有太多的错误处理,建议添加更多的异常捕获和错误检查。

代码

import os
from multiprocessing import Poolimport cv2
import lpips
import numpy as np
import torch
from scipy.ndimage import filters
from scipy.special import gammaln
from scipy.stats import genpareto
from skimage import img_as_float
from skimage.metrics import structural_similarity as compare_ssim
from tqdm import tqdm# Initialize LPIPS
loss_fn = lpips.LPIPS(net='vgg')def calculate_psnr(img1, img2):return cv2.PSNR(img1, img2)def calculate_ssim(img1, img2):return compare_ssim(img1, img2, multichannel=True)def calculate_lpips(img1, img2):img1 = torch.Tensor(img1).permute(2, 0, 1).unsqueeze(0)img2 = torch.Tensor(img2).permute(2, 0, 1).unsqueeze(0)return loss_fn(img1, img2).item()def calculate_niqe(image):image = img_as_float(image)h, w = image.shape[:2]block_size = 96strides = 32features = []for i in range(0, h - block_size + 1, strides):for j in range(0, w - block_size + 1, strides):block = image[i:i + block_size, j:j + block_size]mu = np.mean(block)sigma = np.std(block)filtered_block = filters.gaussian_filter(block, sigma)shape, _, scale = genpareto.fit(filtered_block.ravel(), floc=0)feature = [mu, sigma, shape, scale, gammaln(1 / shape)]features.append(feature)features = np.array(features)model_mean = np.zeros(features.shape[1])model_cov_inv = np.eye(features.shape[1])quality_scores = []for feature in features:score = (feature - model_mean) @ model_cov_inv @ (feature - model_mean).Tquality_scores.append(score)return np.mean(quality_scores)def process_image(i, main_output_file_path, hd_img_folder, generated_img_root_folder, output_root_folder):hd_img_name = f"{i}.png"hd_img_path = os.path.join(hd_img_folder, hd_img_name)hd_img = cv2.imread(hd_img_path)corresponding_generated_folder = os.path.join(generated_img_root_folder, str(i))if not os.path.exists(corresponding_generated_folder):print(f"Folder for {hd_img_name} does not exist. Skipping.")returnoutput_file_path = os.path.join(output_root_folder, f"{i}_output.txt")generated_img_names = os.listdir(corresponding_generated_folder)generated_img_names.sort(key=lambda x: int(x.split('.')[0]))total_images = len(generated_img_names)best_psnr = 0best_ssim = 0best_lpips = float('inf')best_niqe = float('inf')best_metrics_record = {}with open(output_file_path, 'w') as f:f.write(f"Results for HD Image: {hd_img_name}\n")f.write("-------------------------------------\n")for generated_img_name in tqdm(generated_img_names, total=total_images, desc=f"Processing for {hd_img_name}",leave=False):generated_img_path = os.path.join(corresponding_generated_folder, generated_img_name)generated_img = cv2.imread(generated_img_path)psnr = calculate_psnr(hd_img, generated_img)ssim = calculate_ssim(hd_img, generated_img)lpips_value = calculate_lpips(hd_img, generated_img)niqe = calculate_niqe(generated_img)result_line = f"{generated_img_name} PSNR: {psnr} SSIM: {ssim} LPIPS: {lpips_value} NIQE: {niqe}\n"f.write(result_line)if psnr > best_psnr:best_psnr = psnrbest_metrics_record['Best PSNR'] = (generated_img_name, best_psnr)if ssim > best_ssim:best_ssim = ssimbest_metrics_record['Best SSIM'] = (generated_img_name, best_ssim)if lpips_value < best_lpips:best_lpips = lpips_valuebest_metrics_record['Best LPIPS'] = (generated_img_name, best_lpips)if niqe < best_niqe:best_niqe = niqebest_metrics_record['Best NIQE'] = (generated_img_name, best_niqe)with open(main_output_file_path, 'a') as main_f:main_f.write(f"Best Metrics for {hd_img_name}\n")main_f.write("-------------------------------------\n")for metric, (img_name, value) in best_metrics_record.items():main_f.write(f"{metric}: {img_name}, Value: {value}\n")main_f.write("\n")print(f"Best Metrics for {hd_img_name} are saved in {main_output_file_path}")if __name__ == "__main__":hd_img_folder = 'xxxxxxx'generated_img_root_folder = 'xxxxxxx'output_root_folder = 'xxxxxxx'main_output_file_path = os.path.join(output_root_folder, "all_results.txt")with open(main_output_file_path, 'w') as main_f:main_f.write("Detailed Results for Each High-Definition Image\n")main_f.write("==============================================\n")with Pool(4) as pool:  # Initialize a pool with 8 processespool.starmap(process_image,[(i, main_output_file_path, hd_img_folder, generated_img_root_folder, output_root_folder) for i inrange(1, 570)])  # Parallel processing

这篇关于超分辨率指标计算:Python代码用于评估图像质量,PSNR、SSIM、LPIPS和NIQE的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/381

相关文章

基于Python编写一个git自动上传的脚本(打包成exe)

《基于Python编写一个git自动上传的脚本(打包成exe)》这篇文章主要为大家详细介绍了如何基于Python编写一个git自动上传的脚本并打包成exe,文中的示例代码讲解详细,感兴趣的小伙伴可以跟... 目录前言效果如下源码实现利用pyinstaller打包成exe利用ResourceHacker修改e

Python在二进制文件中进行数据搜索的实战指南

《Python在二进制文件中进行数据搜索的实战指南》在二进制文件中搜索特定数据是编程中常见的任务,尤其在日志分析、程序调试和二进制数据处理中尤为重要,下面我们就来看看如何使用Python实现这一功能吧... 目录简介1. 二进制文件搜索概述2. python二进制模式文件读取(rb)2.1 二进制模式与文本

Python中Tkinter GUI编程详细教程

《Python中TkinterGUI编程详细教程》Tkinter作为Python编程语言中构建GUI的一个重要组件,其教程对于任何希望将Python应用到实际编程中的开发者来说都是宝贵的资源,这篇文... 目录前言1. Tkinter 简介2. 第一个 Tkinter 程序3. 窗口和基础组件3.1 创建窗

利用c++判断水仙花数并输出示例代码

《利用c++判断水仙花数并输出示例代码》水仙花数是指一个三位数,其各位数字的立方和恰好等于该数本身,:本文主要介绍利用c++判断水仙花数并输出的相关资料,文中通过代码介绍的非常详细,需要的朋友可以... 以下是使用C++实现的相同逻辑代码:#include <IOStream>#include <vec

Django调用外部Python程序的完整项目实战

《Django调用外部Python程序的完整项目实战》Django是一个强大的PythonWeb框架,它的设计理念简洁优雅,:本文主要介绍Django调用外部Python程序的完整项目实战,文中通... 目录一、为什么 Django 需要调用外部 python 程序二、三种常见的调用方式方式 1:直接 im

Python字符串处理方法超全攻略

《Python字符串处理方法超全攻略》字符串可以看作多个字符的按照先后顺序组合,相当于就是序列结构,意味着可以对它进行遍历、切片,:本文主要介绍Python字符串处理方法的相关资料,文中通过代码介... 目录一、基础知识:字符串的“不可变”特性与创建方式二、常用操作:80%场景的“万能工具箱”三、格式化方法

Java 接口定义变量的示例代码

《Java接口定义变量的示例代码》文章介绍了Java接口中的变量和方法,接口中的变量必须是publicstaticfinal的,用于定义常量,而方法默认是publicabstract的,必须由实现类... 在 Java 中,接口是一种抽象类型,用于定义类必须实现的方法。接口可以包含常量和方法,但不能包含实例

浅析python如何去掉字符串中最后一个字符

《浅析python如何去掉字符串中最后一个字符》在Python中,字符串是不可变对象,因此无法直接修改原字符串,但可以通过生成新字符串的方式去掉最后一个字符,本文整理了三种高效方法,希望对大家有所帮助... 目录方法1:切片操作(最推荐)方法2:长度计算索引方法3:拼接剩余字符(不推荐,仅作演示)关键注意事

python版本切换工具pyenv的安装及用法

《python版本切换工具pyenv的安装及用法》Pyenv是管理Python版本的最佳工具之一,特别适合开发者和需要切换多个Python版本的用户,:本文主要介绍python版本切换工具pyen... 目录Pyenv 是什么?安装 Pyenv(MACOS)使用 Homebrew:配置 shell(zsh

使用Redis实现会话管理的示例代码

《使用Redis实现会话管理的示例代码》文章介绍了如何使用Redis实现会话管理,包括会话的创建、读取、更新和删除操作,通过设置会话超时时间并重置,可以确保会话在用户持续活动期间不会过期,此外,展示了... 目录1. 会话管理的基本概念2. 使用Redis实现会话管理2.1 引入依赖2.2 会话管理基本操作