首页 > 解决方案 > 使用并发期货通过多处理运行多个视频

问题描述

我正在尝试使用 concurrent.futres.ProcessPoolExecuter 运行代码,但在运行视频时遇到下面提到的while true错误class get_frames

concurrent.futures.process.BrokenProcessPool: A process in the process pool was terminated abruptly while the future was running or pending.

下面提到的是我的实际代码:

import cv2
import numpy as np
import imutils
import os
import threading
import concurrent.futures
import time

start = time.perf_counter()

class VideoCapture:

    def __init__(self, name):
        self.cap = cv2.VideoCapture(name)
        self.q = queue.Queue()
        t = threading.Thread(target=self._reader)
        # t.get_ident()
        t.start()
        t.daemon = True

    # read frames as soon as they are available, keeping only most recent one
    def _reader(self):
        while True:
            ret, frame = self.cap.read()
            if not ret:
                break
            if not self.q.empty():
                try:
                    self.q.get_nowait()  # discard previous (unprocessed) frame
                except Queue.Empty:
                    pass
            self.q.put(frame)

    @classmethod
    def read(cls):
        return cls(self.q.get())


names = ['test.mp4', 'test1.mp4']

frames = [None] * len(names);
#frame_in = [None] * len(names);
ret = [None] * len(names);

cap_list = [cv2.VideoCapture(k) for k in names]


# print(cap_list)

class get_frames:

    def __init__(self, cap, name):
        self.cap = cap
        self.name = name
        # print(self.cap)

    def display_frames(self):
        while True:
            ret, frames = self.cap.read()
            if ret is True:
                count += 1
                print(self.name)


with concurrent.futures.ProcessPoolExecutor(max_workers=3) as executor:
    for i, cap in enumerate(cap_list):
        g_f = get_frames(cap, i)
    results = executor.map(g_f.display_frames, cap_list)
    print(results)

对此的任何建议都会有很大帮助

标签: pythonpython-3.xopencvmultiprocessingprocess-pool

解决方案


您可以坚持使用ProcessPoolExecutor Example

示例如下:

def main():
    with concurrent.futures.ProcessPoolExecutor() as executor:
        for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
            print('%d is prime: %s' % (number, prime))

if __name__ == '__main__':
    main()
  • 您必须使用if __name__ == '__main__':语法。按照方法
    放置准备代码。 没有它,整个脚本会被执行多次,并且会卡住。 cap_list = [cv2.VideoCapture(k) for k in names]main()
  • 该示例使用方法,而不是对象。
    我想你可以映射对象方法,但我不能让它工作。
  • 使用 Python 3.6 时,出现错误:"TypeError: can't pickle cv2.VideoCapture objects".
    我将文件名传递给display_frames,并在方法cv2.VideoCapture的开头执行display_frames
  • 您发布的代码未使用class VideoCapture.

用于检测:

  • 我的示例生成合成视频文件(为了使示例“自包含”)。
  • 该示例显示了用于测试的视频帧。

这是代码:

import cv2
import numpy as np
import concurrent.futures

def display_frames(name):
    cap = cv2.VideoCapture(name)

    while True:
        ret, frames = cap.read()

        if ret is False:
            break

        # Show frames for testing:
        cv2.imshow(str(cap), frames)
        cv2.waitKey(100)

    cap.release()

    return name


def main():
    names = ['test2.mp4', 'test3.mp4']

    # Generate two synthetic video files to be used as input:
    ###############################################################################
    width, height, n_frames = 640, 480, 30  # 30 frames, resolution 640x480

    intput_filename1 = names[0]
    intput_filename2 = names[1]

    # Use MPEG4 codec (for testing)
    synthetic_out = cv2.VideoWriter(intput_filename1, cv2.VideoWriter_fourcc(*'mp4v'), 25, (width, height))

    for i in range(n_frames):
        img = np.full((height, width, 3), 60, np.uint8)
        cv2.putText(img, str(i+1), (width//2-100*len(str(i+1)), height//2+100), cv2.FONT_HERSHEY_DUPLEX, 10, (30, 255, 30), 20)  # Green number
        synthetic_out.write(img)

    synthetic_out.release()

    width, height, n_frames = 320, 240, 20 # 20 frames, resolution 320x240
    synthetic_out = cv2.VideoWriter(intput_filename2, cv2.VideoWriter_fourcc(*'mp4v'), 25, (width, height))

    for i in range(n_frames):
        img = np.full((height, width, 3), 60, np.uint8)
        cv2.putText(img, str(i+1), (width//2-50*len(str(i+1)), height//2+50), cv2.FONT_HERSHEY_DUPLEX, 5, (255, 30, 30), 10)  # Blue number
        synthetic_out.write(img)

    synthetic_out.release()
    ###############################################################################


    with concurrent.futures.ProcessPoolExecutor(max_workers=3) as executor:
        for name in executor.map(display_frames, names):
            print(name)

    cv2.destroyAllWindows() # For testing


# Using Python 3.6 there is an error: "TypeError: can't pickle cv2.VideoCapture objects"
if __name__ == '__main__':
    main()

我真的不知道它是否回答了您的问题,因为您的原始代码所剩无几。
我希望它有帮助...


推荐阅读