2

我是 Python 中多处理的初学者。我正在为 OpenCV 开发一个多处理脚本,因为我的计算机无法实时处理 OpenCV 帧。我的目标是在主进程中加载​​和处理帧,并使用子进程显示它们。我的问题是我不明白如何从排队的帧构建显示循环。有人可以帮忙吗?

我的代码:

#!/usr/bin/env python
from multiprocessing import Process, Queue
from Queue import Empty
from PIL import Image
import cv2
import cv2.cv as cv
import numpy as np

def image_display(taskqueue):
   cv2.namedWindow ('image_display', cv2.CV_WINDOW_AUTOSIZE)
   while True:
      if taskqueue.get()==None:
         continue
      else:
         image = taskqueue.get()
         im = Image.fromstring(image['mode'], image['size'], image['pixels'])
         num_im = np.asarray(im)
         cv2.imshow ('image_display', num_im)


if __name__ == '__main__':
   taskqueue = Queue()
   vidFile = cv2.VideoCapture('doppler.wmv')
   p = Process(target=image_display, args=(taskqueue,))
   p.start()
   while True:
      flag, image=vidFile.read()
      if flag == 0:
         break
      im = Image.fromarray(image)
      im_dict = {
      'pixels': im.tostring(),
      'size': im.size,
      'mode': im.mode,
      }
      taskqueue.put(im_dict)

p.join()
cv.DestroyAllWindows()

编辑

感谢答案,我能够找到问题所在。下面是一个修改后的脚本,我在其中故意放慢了循环速度添加了一个用于调试的队列。看来,虽然捕获的帧 vidFile.read()确实作为 numpy 数组通过队列传递,然后未经修改作为参数传递给cv2.imshow()cv2.imshow()但由于未知原因拒绝显示图像。任何解决该问题的帮助将不胜感激!

修改后的代码:

#!/usr/bin/env python
from multiprocessing import Process, Queue
from Queue import Empty
import cv2
import cv2.cv as cv
import numpy as np
import time

def image_display(taskqueue, outqueue):
   cv2.namedWindow ('image_display', cv2.CV_WINDOW_AUTOSIZE)
   while True:
      try:
         outqueue.put('trying')
         time.sleep(1)
         image = taskqueue.get()
         outqueue.put(image)
         cv2.imshow('image_display', image)
      except:
         continue



if __name__ == '__main__':
   taskqueue = Queue()
   outqueue = Queue()
   vidFile = cv2.VideoCapture('doppler.wmv')
   p = Process(target=image_display, args=(taskqueue, outqueue))
   p.start()
   while True:
      print outqueue.get()
      flag, image=vidFile.read()
      if flag == 0:
         break
      taskqueue.put(image)
      time.sleep(0.010)

p.join()
cv.DestroyAllWindows()
4

1 回答 1

2

这应该有效(以下更改说明):

#!/usr/bin/env python
from multiprocessing import Process, Queue
from Queue import Empty
from PIL import Image
import cv2
import cv2.cv as cv
import numpy as np

def image_display(taskqueue):
   cv2.namedWindow ('image_display', cv2.CV_WINDOW_AUTOSIZE)
   while True:

      image = taskqueue.get()              # Added
      if image is None:  break             # Added
      cv2.imshow ('image_display', image)  # Added
      cv2.waitKey(10)                      # Added
      continue                             # Added

      if taskqueue.get()==None:
         continue
      else:
         image = taskqueue.get()
         im = Image.fromstring(image['mode'], image['size'], image['pixels'])
         num_im = np.asarray(im)
         cv2.imshow ('image_display', num_im)


if __name__ == '__main__':
   taskqueue = Queue()
   vidFile = cv2.VideoCapture('doppler.wmv')
   p = Process(target=image_display, args=(taskqueue,))
   p.start()
   while True:
      flag, image=vidFile.read()

      taskqueue.put(image)  # Added
      import time           # Added
      time.sleep(0.010)     # Added
      continue              # Added

      if flag == 0:
         break
      im = Image.fromarray(image)
      im_dict = {
      'pixels': im.tostring(),
      'size': im.size,
      'mode': im.mode,
      }
      taskqueue.put(im_dict)

taskqueue.put(None)
p.join()
cv.DestroyAllWindows()

我试图通过添加行(包含注释的行# Added)对您的代码进行最小的更改:

1)只需将图像本身(原始 NumPy 数组)放在队列中。

2)在读取另一帧之前在主进程中暂停一点。您需要这样做以免超出队列,因为imshow()在生成的进程中可能需要更长的时间,因为它正在调用 X。您可能需要根据您的系统增加此值(以秒为单位)。

3) 生成的进程必须waitKey()在每个imshow().

4) 主进程None完成后将特殊图像放入队列中。

于 2013-06-11T21:55:10.680 回答