[英]Multiprocessing multi-layered image merging in Python
我花了几个小时在堆栈和谷歌上搜索这个问题的答案,似乎很接近但从来没有完全得到答案。 我觉得它在create_files
中很简单,但我就是不明白。
我正在尝试提高程序的速度,该程序从编号的文件夹中获取随机图像,并使用 Pillow 将它们以透明度堆叠在一起。 现在,只要您点击 18 个文件夹,每个文件夹包含 20 张左右的图像,在我的 M1 MacBook Pro 上每张图像大约需要 2 秒,这可能会非常慢。 我想过使用多处理来加快速度,但我不知道是不是因为我的代码非常依赖 for 循环迭代器变量,但我似乎无法让 pool.map 为我工作而不会出现不同的错误。 我将发布相关功能的片段。 任何建议都会很棒,我敢肯定这是一个简单的重构,对于 Python 来说可能还是有点太绿了。
一些函数调用的变量要么是文件夹的路径,要么是所有图像路径的数组(image1 将是 [0] image2 将是 [1] 等)。
def save_file(img, counter):
if not os.path.exists(f"{output_folder}"):
os.makedirs(f"{output_folder}")
img.save(f"{output_folder}/file_{counter}.png")
def create_composite(layer_count, img):
image_size = Image.open(image_paths[0][0])
composite_img = Image.new("RGBA", image_size.size)
composite_img = merge_images(layer_count, img, composite_img)
return composite_img
def merge_images(layer_count, img, composite_img):
for i in range(layer_count):
next_img = Image.open(img[i])
composite_img = Image.alpha_composite(composite_img, next_img)
return composite_img
def randomise_layers(layer_count):
# Creates an array with randomised files for each layer and checks for exceptions.
image_stack = []
for i in range(layer_count):
# Checks if there are any image conflicts and adds them to the stack.
image_stack.append(check_exception(i))
return image_stack
def check_exception(index):
# Checks if any of the layers have a known exception with another layer
temp_file_path = file_paths(index)
if is_exception(temp_file_path):
check_exception(index)
else:
return temp_file_path
def is_exception(file_path):
# Gets layer exceptions from file
return False
def create_files(iterations):
for i in range(iterations):
save_file(create_composite(layer_count, randomise_layers(layer_count)), i)
if iterations < 10:
print(f"File {i+1} created.")
if __name__ == "__main__":
iterations = 5
create_files(iterations)
好的! 所以感谢 Albert 的建议,我更多地研究了 ProcessPoolExecutor,并做了一些重构。
我的create_files
函数现在如下:
def create_files(iterations):
with concurrent.futures.ProcessPoolExecutor(os.cpu_count()-2) as exe:
exe.map(save_file, list(range(iterations)))
由于这种重构和使用映射,我不得不将一堆变量移动为全局变量,因为一旦多处理启动,我就无法将它们传递给函数(似乎没有保留任何已在之前的范围相同)。 我将更多地研究将其中一些值传递到线程中,另一种选择是列出这些变量,并执行类似的操作
var1 = [missing_variable] * iterations
使它们可用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.