OpenCV + Python +多处理将无法正常工作

时间:2015-08-07 05:45:17

标签: python multithreading opencv

我想我在OpenCV的Python绑定中发现了一个错误,但由于主席和键盘之间总是存在机会问题而不是代码,我想在这里确认而不是立即提交一张票。 / p>

这是一个用于并行处理大量图像的简单脚本:

import cv2
import multiprocessing
import glob
import numpy

def job(path, output):

    image = cv2.imread(path)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    output.put(path)

if __name__ == "__main__":

    main_image = cv2.imread("./image.png")
    main_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    output = multiprocessing.Queue()

    processes = []

    for path in glob.glob("./data/*"):

        process = multiprocessing.Process(
            target=job,
            args=(path, output))

        process.start()
        processes.append(process)

    for process in processes:
        process.join()

    # Collect all results
    results = [output.get() for process in processes]

    print 'Finished'

在此代码results = [output.get() for process in processes]中永远不会完成。 现在真正奇怪的是,如果我注释掉main_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)行,它对并行计算没有任何影响,那么脚本就完成了。

./image.png./data/处的路径都会导致普通图像,总共约20个。 我尝试在内存中创建图像(numpy.ones([100, 100, 3]).astype(numpy.float32))并且没有产生错误。

我有类似的用C ++编写的代码,运行得很好。 我的环境:OS X 10.10,OpenCV 3.0.0,Python 2.7

所以,我是在做一些愚蠢的事情,还是这确实是OpenCV中出现并行计算的错误?

编辑: 我还尝试了使用multiprocessing.Pool.map()的实现,结果是一样的。这是代码

import cv2
import multiprocessing
import glob
import numpy

def job(path):

    image = cv2.imread(path)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    return path

if __name__ == "__main__":

    image = cv2.imread("./image.png")
    image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    paths = glob.glob("./data/*")
    pool = multiprocessing.Pool()
    result = pool.map(job, paths)

    print 'Finished'

    for value in result:
        print value

我能够使用非opencv任务获得正确的结果,所以我坚信问题出在opencv方面。但请随意证明我错了 - 我很乐意,因为这意味着我不必诉诸C ++。

1 个答案:

答案 0 :(得分:1)

get之前不应该join吗?

根据the python docs

  

加入使用队列的进程

     

请记住,将项目放入队列的进程将等待   在终止之前,直到所有缓冲的项目都由   “馈线”螺纹到底层管道。 (子进程可以调用   队列的cancel_join_thread()方法可以避免这种行为。)

     

这意味着无论何时使用队列,您都需要确保这一点   所有已放入队列的项目最终都将被删除   在流程加入之前。否则你不能确定   将项目放入队列的进程将终止。记得   此外,非守护进程将自动加入。

     

将导致死锁的示例如下:

 from multiprocessing import Process, Queue


 def f(q):
     q.put('X' * 1000000)


 if __name__ == '__main__':
     queue = Queue()
     p = Process(target=f, args=(queue,))
     p.start()
     p.join()                    # this deadlocks
     obj = queue.get() 
     

这里的修复方法是交换最后两行(或者只是删除p.join()行。)