【问题标题】:How to use multithreading with and cv2.VideoCapture()?如何使用多线程和 cv2.VideoCapture()?
【发布时间】:2021-05-20 13:51:47
【问题描述】:

我想显示两个或多个单独的视频,并使用 cv2 应用轻微的图像处理。

如果我不使用threading/multiprocessing,那么仅使用cv2.waitKey(timeThatCouldBeSpentFetchingAFrameForAnotherVideo) 显示帧就会浪费很多时间。

我尝试使用threading,但它不能正常工作。我收到此警告:WARNING: nextEventMatchingMask should only be called from the Main Thread! This will throw an exception in the future.。这通常会导致简单的崩溃。

所以,我决定尝试实现multiprocessing,理论上它应该比threading 更快,图像处理更复杂(对吧??)。 I used this as an example. 但是,在这种情况下,我遇到了另一个问题,这种方法只能让我获得视频的第一帧。另外,我尝试将 cv2.VideoCapture() 放在 Process 之外,但结果是:TypeError: cannot pickle 'cv2.VideoCapture' object

这是我的代码:

class CamManager:
    def __init__(self):
        self.saving = Saving()
        self.cams = self.createCamObjList()
        self.buffers = [Buffer(cam.FPS*BUFFER_SIZE) for cam in self.cams]


    def createCamObjList(self):
        l = []
        for i, url in enumerate(STREAM_URLS):
            saved_data = self.saving.getDataFor(url)
            cam = BufferedCamera(url, i, saved_data)
            l.append(cam)
        return l


    def startStreamCapture(self):
        queue_for_cams = multiprocessing.Queue()
        processes = [multiprocessing.Process(
            target=cam.readloop, args=[queue_for_cams]).start() for cam in self.cams]
        while True:
            if not queue_for_cams.empty():
                from_queue = queue_for_cams.get()
                self.buffers[from_queue[0]].add(from_queue[1])



class BufferedCamera():
    def __init__(self, streamURL, cam_id, saved_data=None):
        self.streamURL = streamURL
        self.cam_id = cam_id

        # get current camera's framerate
        cam = cv2.VideoCapture(streamURL)
        self.FPS = cam.get(5)
        if self.FPS == 0:
            self.FPS = 24
        cam.release()
        print(f"Input res: {cam.get(3)}x{cam.get(4)} | FPS: {self.FPS}")

        # use that framerate to adjust the time between each iteration of mainloop
        self.period = int((1.0/self.FPS)*1000)


    def readloop(self, queue):
        while True:
            self.read(queue)

    
    def read(self, queue):
        cam = cv2.VideoCapture(self.streamURL)
        _, frame = cam.read()
        if frame is not None:
            queue.put((self.cam_id, frame))
        cv2.waitKey(self.period)

【问题讨论】:

  • 听起来cv2 不支持多线程,所以你不能,而且你没有正确地进行多线程处理(但如果没有看到代码就很难说)。
  • 我添加了一些代码sn-ps。你介意再看一下吗?
  • 由于通常进程之间不会共享内存,因此必须传输大量内存通常会使事情变得太慢(即使您使用Queue 来执行此操作)。在 Python 3.8 中添加了一个 multiprocessing.shared_memory 模块“用于分配和管理一个或多个进程访问的共享内存”,因此也许您可以使用它来(更多)快速传输图像数据。

标签: python python-3.x cv2


【解决方案1】:

我通过在我的 Process 函数内和 readloop 之前创建 cv2.VideoCapture 对象让 multiprocessing 工作:

def readloop(self, queue):
    cam = cv2.VideoCapture(self.streamURL)
    while True:
        self.read(queue, cam)

【讨论】:

    猜你喜欢
    • 2017-07-10
    • 2021-12-20
    • 2019-06-12
    • 2019-10-05
    • 1970-01-01
    • 2015-06-02
    • 1970-01-01
    • 2021-11-13
    • 1970-01-01
    相关资源
    最近更新 更多