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) 別のフレームを読み取る前に、マスター プロセスで少し一時停止します。これは、生成されたプロセスで X を呼び出しているため、キューがオーバーランしないようにするためimshow()に必要です。システムによっては、この値を (秒単位で) 増やす必要がある場合があります。

3) 生成されたプロセスは、waitKey()すべての後に実行する必要がありますimshow()

4) マスター プロセスは、完了時に特別なNoneイメージをキューに入れます。

于 2013-06-11T21:55:10.680 に答える