无参考图像的清晰度评价方法

无参考图像的清晰度评价方法

Tenengrad 梯度函数

Tenengrad 梯度函数采用Sobel算子分别提取水平和垂直方向的梯度值,基与Tenengrad 梯度函数的图像清晰度定义如下:
D ( f ) = ∑ y ∑ x ∣ G ( x , y ) ∣ ( G ( x , y ) > T ) \mathrm{D(f)=\sum_y\sum_x|G(x,y)|\quad(G(x,y)>T)} D(f)=yx∣G(x,y)(G(x,y)>T)
G(x,y) 的形式如下:
G ( x , y ) = G x 2 ( x , y ) + G y 2 ( x , y ) \mathrm{G(x,y)=\sqrt{G_x^2(x,y)+ G_y^2(x,y)}} G(x,y)=Gx2(x,y)+Gy2(x,y)

其中:T是给定的边缘检测阈值,Gx和Gy分别是像素点(x,y)处Sobel水平和垂直方向边缘检测算子的卷积,建议使用Sobel算子模板来检测边缘。

代码如下:


import math
from functools import partial
import pandas as pd
import os
import cv2
import numpy as np
from tqdm import tqdm


def load_and_process_image(image_path):
    image = cv2.imread(image_path)
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    return gray_image


def tenengrad_gradient(image, ksize=3):
    gradient_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=ksize)
    gradient_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=ksize)
    tenengrad = gradient_x ** 2 + gradient_y ** 2
    tenengrad_sum = np.sum(tenengrad)
    tenengrad_value = math.sqrt(tenengrad_sum)
    # Normalize by image area
    image_area = image.size
    tenengrad_normalized = tenengrad_value / image_area
    return tenengrad_normalized


def process_image(image_path):
    image = load_and_process_image(image_path)
    tenengrad_value = tenengrad_gradient(image)
    image_name = os.path.basename(image_path)
    return (image_name, tenengrad_value)



from multiprocessing import Pool



def process_image_in_folder(folder_path):
    files = os.listdir(folder_path)
    # 构建完整的文件路径
    file_paths = [os.path.join(folder_path, file) for file in files]
    # 使用 functools.partial 包装函数,以便在进程间传递
    pool = Pool()#这里使用了进程池加速运算
    process_func = partial(process_image)
    results = list(tqdm(pool.imap(process_func, file_paths), total=len(file_paths)))
    return results


def save_results_to_excel(results, excel_path):
    columns = ["filename", "tenengrad"]
    df = pd.DataFrame(data=results, columns=columns)
    df.to_csv(excel_path, index=False)
    print(f"数据已经写入到了文件{excel_path}中")

# Example usage:
if __name__ == '__main__':
    results = process_image_in_folder(r'E:\Desktop\data\sourceimages')
    save_results_to_excel(results, "./jieguo.csv")

partial函数

from multiprocessing import Pool
from functools import partial

def process_image(image_path, resize_width):
    # 假设这里是处理图像的函数,将图像调整到指定宽度
    # 在这个例子中,假设我们只输出一些信息
    print(f"Processing image {image_path} with width {resize_width}")

if __name__ == '__main__':
    pool = Pool()
    file_paths = ['image1.jpg', 'image2.jpg', 'image3.jpg']
    
    # 使用 functools.partial 固定 resize_width 参数为 800
    process_func = partial(process_image, resize_width=800)
    
    # 使用进程池并行处理
    results = list(pool.imap(process_func, file_paths)) #这里的函数process_func不可以加括号,加了括号表示调用

  1. 使用 functools.partial
    • 在上面的例子中,我们使用 partial(process_image, resize_width=800) 创建了一个新的函数 process_func。这个新函数 process_func 实际上就是 process_image 函数的一个版本,其中的 resize_width 参数被固定为 800。
  2. 进程池并行处理
    • pool.imap(process_func, file_paths) 中,我们将 process_func 作为要在进程池中并行处理的函数传递进去。pool.imap() 会依次将 file_paths 中的每个图像路径作为 process_func 的第一个参数(即 image_path),并将固定的 resize_width=800 作为第二个参数传递给 process_func
  3. 避免重复传递参数
    • 如果直接使用 pool.imap(process_image, file_paths),那么 process_image 函数必须接收两个参数:image_pathresize_width。每次调用时,我们都需要手动传递 resize_width,这样会显得冗余,并且不符合进程池的要求。

通过使用 functools.partial,我们可以在创建 process_func 的时候,预先设定 resize_width 参数为固定的值(比如 800),然后在并行处理过程中,每次调用 process_func 时只需传递 image_path 这一个特定参数即可,避免了重复传递和提高了代码的可读性和灵活性。

multiprocessing

multiprocessing 是 Python 中用于支持多进程处理的标准库模块。它允许开发者创建和管理进程,可以在多核系统中并行执行任务,从而加速程序的执行速度。

使用 multiprocessing 模块可以轻松地创建新的进程,将任务分配给不同的进程并行执行,处理大量数据或者需要大量计算的任务时特别有用。与单线程程序相比,多进程可以显著提高程序的性能,因为它们可以同时利用多个 CPU 核心。

总结来说,multiprocessing 提供了一种利用多核 CPU 的方法,允许 Python 程序同时执行多个任务,从而提高程序的效率和性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值