在多处理进程之间将 opencv 视频帧共享为 Numpy 数组的正确方法

2024-04-22

我想与我的多处理子进程共享 OpenCV 中的捕获帧,但是video_capture.read()创建一个新对象,并且不会写入我将通过包装它来共享的 numpy 数组multiprocessing.Array()

这是代码:

ret, frame = video_capture.read()
shared_array = mp.Array(ctypes.c_uint16, frame.shape[0] * frame.shape[1], lock=False)
while True:
    b = np.frombuffer(shared_array)
    ret, b = video_capture.read()

但缓冲b被覆盖read()功能。所以我不写入我的缓冲区/共享数组。

在子流程中我执行以下操作:

img = np.frombuffer(shared_array)
cv2.imshow('Video', img)

共享数组仅包含视频的第一帧。如何正确写入共享数组以便能够读取子进程中的每一帧? 我不想使用队列或管道。共享内存是一种可行的方法,因为更多的进程将消耗帧。


有几个问题,一个是共享数组的大小和形状,另一个是访问它的方式。要解决第一个问题,首先需要确保创建的数组的大小与视频帧的大小相对应。您已经阅读了一个框架并使用了它的宽度和高度(尽管你可以在不阅读任何框架的情况下做到这一点 https://stackoverflow.com/questions/39953263/get-video-dimension-in-python-opencv),但没有考虑其通道数。

ret, frame = video_capture.read()
shape = frame.shape
shared_array = mp.Array(ctypes.c_uint16, shape[0] * shape[1] * shape[2], lock=False)

你选择了uint16作为数据类型,这很好(同样,您可以使用video_capture.get(cv2.CAP_PROP_FORMAT)获取帧的确切数据类型,但您可以选择您想要的任何类型,因为 NumPy 会将值转换为数组数据类型)。但是,当您创建 NumPy 数组时,您必须指定您要使用的数据类型,否则它将使用float64默认情况下:

b = np.frombuffer(shared_array, dtype=np.uint16)

然后你必须将其重塑为框架的形状(请注意,这不会创建新的 NumPy 数组,它只是一个视图,因此它仍然使用共享缓冲区):

b = b.reshape(shape)

最后,当你读取框架时,你不想覆盖b变量,而是写入数组。另外,您应该只在实际读取帧时执行此操作:

while True:
    ret, frame = video_capture.read()
    if ret:
        b[:] = frame
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在多处理进程之间将 opencv 视频帧共享为 Numpy 数组的正确方法 的相关文章

随机推荐