繁体   English   中英

Python中的多处理多层图像合并

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM