4

我有一些代码对一堆 Python Imaging Library (PIL) Image 对象执行(独立)操作。我想尝试使用并行处理来加快速度,所以我阅读了下面的多处理模块:

http://docs.python.org/library/multiprocessing.html

但是我仍然不太清楚如何使用多处理来解决这个问题。

从概念上讲,我可以使用图像对象的 multiprocessing.Queue 并使用工作人员池。但 Image 对象似乎“不可挑剔”:

UnpickleableError: Cannot pickle <type 'ImagingCore'> objects

有没有更好的方法来并行处理 PIL 图像?

4

3 回答 3

2

如果您从文件中获取图像对象,您只需将文件名发送给工作人员并让他们自己打开图像。

否则,您可以发送图像数据(使用Image.getdata())以及大小和像素格式,并让工作人员使用Image.new()和重建图像Image.putdata()

于 2012-09-16T06:18:27.257 回答
2

只需将文件名放在一个列表中,然后让工作进程处理它们。下面的示例在子进程中使用ImageMagick从晦涩的格式进行一些图像转换。但是同样的原理也可以用于 PIL。只需替换函数的内容。这是我经常使用的程序,用于将 DICOM 文件(医学成像中使用的一种格式,在本例中来自 X 射线机)转换为 PNG 格式。processfile()

"""Convert DICOM files to PNG format, remove blank areas. The blank erea
   removal is based on the image size of a Philips flat detector. The image
   goes from 2048x2048 pixels to 1574x2048 pixels."""

import os
import sys
import subprocess
from multiprocessing import Pool, Lock

globallock = Lock()

def checkfor(args):
    """Make sure that a program necessary for using this script is
    available.

    Arguments:
    args -- string or list of strings containing a command to test
    """
    if isinstance(args, str):
        args = args.split()
    try:
        f = open('/dev/null')
        subprocess.call(args, stderr=subprocess.STDOUT, stdout=f)
        f.close()
    except:
        print "Required program '{}' not found! exiting.".format(args[0])
        sys.exit(1)

def processfile(fname):
    """Use the convert(1) program from the ImageMagick suite to convert the
       image and crop it.

    Arguments:
    fname -- string containing the name of the file to process
    """
    size = '1574x2048'
    args = ['convert', fname, '-units', 'PixelsPerInch', '-density', '300',
            '-crop', size+'+232+0', '-page', size+'+0+0', fname+'.png']
    rv = subprocess.call(args)
    globallock.acquire()
    if rv != 0:
        print "Error '{}' when processing file '{}'.".format(rv, fname)
    else:
        print "File '{}' processed.".format(fname)
    globallock.release()

def main(argv):
    """Main program.

    Arguments:
    argv -- command line arguments
    """
    if len(argv) == 1:
        # If no filenames are given, print a usage message.
        path, binary = os.path.split(argv[0])
        print "Usage: {} [file ...]".format(binary)
        sys.exit(0)
    # Verify that the convert program that we need is available.
    checkfor('convert')
    # Apply the processfile() function to all files in parallel.
    p = Pool()
    p.map(processfile, argv[1:])
    p.close()

if __name__ == '__main__':
    main(sys.argv)
于 2012-09-16T10:28:32.510 回答
1

另一种选择是PIL 图像转换为可腌制的 numpy 数组。

from __future__ import print_function
import numpy
import pickle

my_array = numpy.array([1,2,3])
pickled_array = pickle.dumps(my_array)
print('The pickled version of %s is:\n\n%s.' % (my_array, pickled_array))
于 2014-08-06T17:35:06.810 回答