OpenCV的VideoWriter可以在单独的过程中编写吗?

时间:2019-03-29 16:21:05

标签: python-3.x opencv python-multiprocessing

我正在尝试通过单独的过程将视频保存到磁盘。该程序创建图像缓冲区以保存在原始过程中。完成录制后,它将文件名和图像缓冲区传递给第二个进程,该进程将制作自己的VideoWriter并保存文件。但是,当第二个进程调用write时,什么也没有发生。它会挂起,并且不会输出任何错误。

我检查了VideoWriter是否已经打开。我尝试将代码移至原始流程,以查看其是否在其中正常工作。我不知道这是我需要在新流程中初始化的设置还是与VideoWriter的工作方式有关。

这是我的代码

def stop_recording(self):
    """Stops recording in a separate process"""
    if self._file_dump_process is None:
        self._parent_conn, child_conn = multiprocessing.Pipe()
        self._file_dump_process = multiprocessing.Process(
            target=self.file_dump_loop, args=(child_conn, self.__log))
        self._file_dump_process.daemon = True
        self._file_dump_process.start()

    if self._recording:
        self.__log.info("Stopping recording. Please wait...")
        # Dump VideoWriter and image buffer to process

        # Comment out when running on main procress
        self._parent_conn.send([self._record_filename, self._img_buffer])
        """ Comment in when running on main procress
        fourcc = cv2.VideoWriter_fourcc(*"MJPG")
        effective_fps = 16.0
        frame_shape = (640, 480)

        record_file = cv2.VideoWriter(self._record_filename, fourcc,
                                      effective_fps, frame_shape,
                                      isColor=1)

        for img in self._img_buffer:
            self.__log.info("...still here...")
            record_file.write(img)

        # Close the file and set it to None
        record_file.release()
        self.__log.info("done.")
        """

    # Delete the entire image buffer no matter what
    del self._img_buffer[:]
    self._recording = False

@staticmethod
def file_dump_loop(child_conn, parent_log):
    fourcc = cv2.VideoWriter_fourcc(*"MJPG")
    effective_fps = 16.0
    frame_shape = (640, 480)
    while True:
        msg = child_conn.recv()
        record_filename = msg[0]
        img_buffer = msg[1]
        record_file = cv2.VideoWriter(record_filename, fourcc,
                                      effective_fps, frame_shape,
                                      isColor=1)
        for img in img_buffer:
            parent_log.info("...still here...")
            record_file.write(img)
        # Close the file and set it to None
        record_file.release()
        del img_buffer[:]
        parent_log.info("done.")

这是我在一个进程上运行时的日志输出:

2019-03-29 16:19:02,469 - image_processor.stop_recording - INFO: Stopping recording. Please wait...
2019-03-29 16:19:02,473 - image_processor.stop_recording - INFO: ...still here...
2019-03-29 16:19:02,515 - image_processor.stop_recording - INFO: ...still here...
2019-03-29 16:19:02,541 - image_processor.stop_recording - INFO: ...still here...
2019-03-29 16:19:02,567 - image_processor.stop_recording - INFO: ...still here...
2019-03-29 16:19:02,592 - image_processor.stop_recording - INFO: ...still here...
2019-03-29 16:19:02,617 - image_processor.stop_recording - INFO: ...still here...
2019-03-29 16:19:02,642 - image_processor.stop_recording - INFO: ...still here...
2019-03-29 16:19:02,670 - image_processor.stop_recording - INFO: done.

这是在第二个进程上运行时的日志输出:

2019-03-29 16:17:27,299 - image_processor.stop_recording - INFO: Stopping recording. Please wait...
2019-03-29 16:17:27,534 - image_processor.file_dump_loop - INFO: ...still here...

1 个答案:

答案 0 :(得分:0)

我尝试了此操作,并成功使用以下代码:

import cv2
cap, imgs = cv2.VideoCapture('exampleVideo.MP4'), []

# This function writes video
def write_video(list_of_images):
    vid_writer = cv2.VideoWriter('/home/stephen/Desktop/re_encode.avi',cv2.VideoWriter_fourcc('M','J','P','G'),120, (640,480))
    for image in list_of_images: vid_writer.write(image)

# Loop to read video and save images to a list
for frame in range(123):
    _, img = cap.read()
    imgs.append(img)
write_video(imgs)

cap.release()

一切都按预期工作,当我检查了运行需要多长时间时,我发现上面的代码读取视频花费了0.33秒,而写入视频花费了0.43秒。如果我在同一循环(如下所示)中读取视频并写入视频,则总处理时间为0.56秒(即.13 + .43)。

# Loop to save image to video
for frame in range(123):
    _, img = cap.read()
    vid_writer.write(img)

最大的缺点是先将图像写入缓冲区(在内存中),然后再将图像写入视频文件(在硬盘上)。缓冲区保存在RAM中,这将很快填满,您可能会遇到内存错误。