无参考图像的清晰度评价方法
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)=y∑x∑∣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不可以加括号,加了括号表示调用
- 使用
functools.partial
:- 在上面的例子中,我们使用
partial(process_image, resize_width=800)
创建了一个新的函数process_func
。这个新函数process_func
实际上就是process_image
函数的一个版本,其中的resize_width
参数被固定为 800。
- 在上面的例子中,我们使用
- 进程池并行处理:
- 在
pool.imap(process_func, file_paths)
中,我们将process_func
作为要在进程池中并行处理的函数传递进去。pool.imap()
会依次将file_paths
中的每个图像路径作为process_func
的第一个参数(即image_path
),并将固定的resize_width=800
作为第二个参数传递给process_func
。
- 在
- 避免重复传递参数:
- 如果直接使用
pool.imap(process_image, file_paths)
,那么process_image
函数必须接收两个参数:image_path
和resize_width
。每次调用时,我们都需要手动传递resize_width
,这样会显得冗余,并且不符合进程池的要求。
- 如果直接使用
通过使用 functools.partial
,我们可以在创建 process_func
的时候,预先设定 resize_width
参数为固定的值(比如 800),然后在并行处理过程中,每次调用 process_func
时只需传递 image_path
这一个特定参数即可,避免了重复传递和提高了代码的可读性和灵活性。
multiprocessing
multiprocessing
是 Python 中用于支持多进程处理的标准库模块。它允许开发者创建和管理进程,可以在多核系统中并行执行任务,从而加速程序的执行速度。
使用 multiprocessing
模块可以轻松地创建新的进程,将任务分配给不同的进程并行执行,处理大量数据或者需要大量计算的任务时特别有用。与单线程程序相比,多进程可以显著提高程序的性能,因为它们可以同时利用多个 CPU 核心。
总结来说,multiprocessing
提供了一种利用多核 CPU 的方法,允许 Python 程序同时执行多个任务,从而提高程序的效率和性能。