Python:使用多处理进行并行化图像读取和预处理

时间:2015-11-18 10:55:19

标签: python multithreading machine-learning computer-vision multiprocessing

对于机器学习应用程序,我试图在python中编写一个读取图像的图像读取器类,对它们进行预处理并将它们分批传递给应用程序。

读取和预处理需要与机器学习培训/测试并行进行,这很容易使用线程和队列来实现。然而,由于预处理在计算上是昂贵的,我想进一步并行化,以便在不同的过程中并行地读取和预处理各个图像。我试图通过以下方式实现这一点(请注意,该示例将删除与问题无关的所有内容,例如读取标签)

import numpy as np
import cv2
import csv
from multiprocessing import Queue, Pool

def load_image(fname):
    return cv2.imread(fname)[:,:,[2,1,0]].astype(np.float32)

class ImageReader(object):

    def __init__(self, path_to_csv, batchsize, transform=None):

        self.path_to_csv = path_to_csv
        self.batchsize = batchsize
        self.transform = transform

        self.fnames = []
        csvfile = open(path_to_csv, 'rb')
        reader = csv.reader(csvfile)
        for row in reader:
            self.fnames.append(row[0])

        self.num_samples = len(self.fnames)

    def __iter__(self):

        q = Queue(maxsize=3*self.batchsize)
        def producer(fname):
            if self.transform is None:
                q.put(load_image(fname))
            else:
                q.put(self.transform(load_image(fname)))
        p = Pool()
        p.map(producer, self.fnames)

        for i in range(self.num_samples//self.batchsize):
            Xlst = []
            for j in range(self.batchsize):
                Xlst.append(q.get())
            yield np.array(Xlst)

if __name__ == '__main__':
    r = ImageReader('some_path', 128, transform=None)
    for Xb in r:
        print Xb.shape

重要的部分是

    q = Queue(maxsize=3*self.batchsize)
    def producer(fname):
        if self.transform is None:
            q.put(load_image(fname))
        else:
            q.put(self.transform(load_image(fname)))
    p = Pool()
    p.map(producer, self.fnames)

我想让一个工作池并行处理图像(在文件名列表中指定)并将它们放入稍后访问的队列中。

由于producer在类中定义,因此无法进行pickle,因此失败。 stackoverflow中有一些变通方法可以使函数成为可选择的,但是在我的特殊情况下它们似乎都不起作用,其中producer将项放入队列中。有没有人对我的具体情况有所了解?

另外:除了拾取性问题之外,我还有正确的方法吗?我不太确定,因为这是我第一次使用多处理。

1 个答案:

答案 0 :(得分:0)

你考虑过使用joblib吗? e.g。

from scipy.misc import imread, imsave
from sklearn.externals.joblib import Parallel, delayed

def read_images(image_paths_list):
    images = Parallel(n_jobs=4, verbose=5)(
        delayed(imread)(f) for f in image_paths_list
    )
    return images

那可以并行读取一批图像,然后可以使用类似的模式对它们进行后期处理?