在python中异步读取和处理图像

时间:2012-09-18 09:31:38

标签: python image-processing asynchronous numpy scipy

上下文

我经常发现自己处于以下情况:

  • 我有一个我需要处理的图像文件名列表
  • 我使用例如scipy.misc.imread
  • 顺序读取每个图像
  • 然后我对每张图片进行某种处理并返回结果
  • 我将结果沿图像文件名保存到Shelf

问题在于,简单地阅读图像所花费的时间可以忽略不计,有时甚至比图像处理更长。

问题

所以我认为理想情况下我可以在处理图像n时读取图像n + 1。或者甚至以自动确定的最佳方式一次更好地处理和读取多个图像?

我已经阅读过有关多处理,线程,扭曲,gevent等的内容,但我无法弄清楚使用哪一个以及如何实现这个想法。有没有人能解决这类问题?

最小例子

# generate a list of images
scipy.misc.imsave("lena.png", scipy.misc.lena())
files = ['lena.png'] * 100

# a simple image processing task
def process_image(im, threshold=128):
    label, n = scipy.ndimage.label(im > threshold)
    return n

# my current main loop
for f in files:
    im = scipy.misc.imread(f)
    print process_image(im)

1 个答案:

答案 0 :(得分:11)

Philip's answer很好,但只会创建几个进程(一个阅读,一个计算),这几乎不会超出现代的> 2核心系统。这是使用multiprocessing.Pool(特别是其映射方法)的替代方法,它创建了同时执行读取和计算方面的过程,但应该更好地利用您可用的所有核心(假设文件多于核心)

#!/usr/bin/env python

import multiprocessing
import scipy
import scipy.misc
import scipy.ndimage

class Processor:
    def __init__(self,threshold):
        self._threshold=threshold

    def __call__(self,filename):
        im = scipy.misc.imread(filename)
        label,n = scipy.ndimage.label(im > self._threshold)
        return n

def main():
    scipy.misc.imsave("lena.png", scipy.misc.lena())
    files = ['lena.png'] * 100

    proc=Processor(128)
    pool=multiprocessing.Pool()
    results=pool.map(proc,files)

    print results

if __name__ == "__main__":
    main()

如果我将图片数量增加到500,并使用processes=N参数Pool,那么我

Processes   Runtime
   1         6.2s
   2         3.2s
   4         1.8s
   8         1.5s

在我的四核超线程i7上。

如果您进入更实际的用例(即实际的不同图像),您的进程可能会花费更多时间等待图像数据从存储加载(在我的测试中,它们几乎是从缓存磁盘瞬间加载)然后可能值得明确创建更多的进程而不是核心,以获得更多的计算和负载重叠。只有你自己在现实负载和硬件上的可扩展性测试才能告诉你实际上最适合你的东西。