15

我正在寻找使用python的多处理模块来创建一个进程,该进程通过opencv的python接口不断地轮询网络摄像头,将任何结果图像发送到一个队列,其他进程可以从中访问它们。但是,每当我尝试对队列中其他进程检索到的图像执行任何操作时,都会遇到挂起(Ubuntu 12.04 上的 python 2.7)。这是一个最小的例子:

import multiprocessing
import cv

queue_from_cam = multiprocessing.Queue()

def cam_loop(queue_from_cam):
    print 'initializing cam'
    cam = cv.CaptureFromCAM(-1)
    print 'querying frame'
    img = cv.QueryFrame(cam)
    print 'queueing image'
    queue_from_cam.put(img)
    print 'cam_loop done'


cam_process = multiprocessing.Process(target=cam_loop,args=(queue_from_cam,))
cam_process.start()

while queue_from_cam.empty():
    pass

print 'getting image'
from_queue = queue_from_cam.get()
print 'saving image'
cv.SaveImage('temp.png',from_queue)
print 'image saved'

此代码应该运行到“保存图像”的打印输出,然后挂起。有什么想法可以解决这个问题吗?

4

3 回答 3

10

最简单的方法是使用cv2基于 NumPy 数组的较新模块。这样你就不必手动酸洗了。这是修复(我只更改了 4 行代码):

import multiprocessing
import cv2

queue_from_cam = multiprocessing.Queue()

def cam_loop(queue_from_cam):
    print 'initializing cam'
    cap = cv2.VideoCapture(0)
    print 'querying frame'
    hello, img = cap.read()
    print 'queueing image'
    queue_from_cam.put(img)
    print 'cam_loop done'

cam_process = multiprocessing.Process(target=cam_loop,args=(queue_from_cam,))
cam_process.start()

while queue_from_cam.empty():
    pass

print 'getting image'
from_queue = queue_from_cam.get()
print 'saving image'
cv2.imwrite('temp.png', from_queue)
print 'image saved'
于 2013-06-11T22:33:03.027 回答
5

看来解决方案是将opencv iplimage对象转换为字符串,然后在将其添加到队列之前对其进行腌制:

import multiprocessing
import cv
import Image
import pickle
import time

queue_from_cam = multiprocessing.Queue()

def cam_loop(queue_from_cam):
    print 'initializing cam'
    cam = cv.CaptureFromCAM(-1)
    print 'querying frame'
    img = cv.QueryFrame(cam)
    print 'converting image'
    pimg = img.tostring()
    print 'pickling image'
    pimg2 = pickle.dumps(pimg,-1)
    print 'queueing image'
    queue_from_cam.put([pimg2,cv.GetSize(img)])
    print 'cam_loop done'


cam_process = multiprocessing.Process(target=cam_loop,args=(queue_from_cam,))
cam_process.start()

while queue_from_cam.empty():
    pass

print 'getting pickled image'
from_queue = queue_from_cam.get()
print 'unpickling image'
pimg = pickle.loads(from_queue[0])
print 'unconverting image'
cv_im = cv.CreateImageHeader(from_queue[1], cv.IPL_DEPTH_8U, 3)
cv.SetData(cv_im, pimg)
print 'saving image'
cv.SaveImage('temp.png',cv_im)
print 'image saved'
于 2012-06-02T14:27:56.723 回答
0

虽然这个线程很旧,但我想提供一个更新的版本,以防人们也对这个问题感兴趣(我是)。在这里,我们不保存图像,而是显示一个连续的视频。

import multiprocessing
import cv2


def cam_loop(queue_from_cam):
    cap = cv2.VideoCapture(0)
    while True:
        hello, img = cap.read()
        queue_from_cam.put(img)


def main():
    print('initializing cam')
    queue_from_cam = multiprocessing.Queue()
    cam_process = multiprocessing.Process(target=cam_loop, args=(queue_from_cam,))
    cam_process.start()
    while True:
        if queue_from_cam.empty():
            continue
        from_queue = queue_from_cam.get()
        cv2.imshow("from queue", from_queue)
        key = cv2.waitKey(1)
        if key == ord("q"):
            cv2.destroyAllWindows()
            break
    print("Destroying process...")
    cam_process.terminate()
    cam_process.join()


if __name__ == '__main__':
    main()
于 2021-09-20T22:36:49.803 回答