在多处理进程之间将 opencv 视频帧共享为 Numpy 数组的正确方法
Right way to share opencv video frame as Numpy array between multiprocessing processes
我想与我的多处理子进程共享我在 OpenVC 中捕获的帧,但是 video_capture.read()
创建了一个新对象并且没有写入我将通过用 multiprocessing.Array()
包装它来共享的我的 numpy 数组
代码如下:
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()
函数覆盖。所以我不写入我的 buffer/shared 数组。
在子流程中,我执行以下操作:
img = np.frombuffer(shared_array)
cv2.imshow('Video', img)
共享数组仅包含视频的第一帧。我怎样才能正确写入共享数组以便能够读取子进程中的每一帧?
我不想使用队列或管道。共享内存是可行的方法,因为更多进程将消耗帧。
有几个问题,一个是共享数组的大小和形状,另一个是访问它的方式。要解决第一个问题,首先需要确保创建的数组的大小与视频帧的大小相对应。你已经阅读了一个框架并使用了它的宽度和高度(尽管 ),但没有考虑它的通道数。
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
我想与我的多处理子进程共享我在 OpenVC 中捕获的帧,但是 video_capture.read()
创建了一个新对象并且没有写入我将通过用 multiprocessing.Array()
包装它来共享的我的 numpy 数组
代码如下:
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()
函数覆盖。所以我不写入我的 buffer/shared 数组。
在子流程中,我执行以下操作:
img = np.frombuffer(shared_array)
cv2.imshow('Video', img)
共享数组仅包含视频的第一帧。我怎样才能正确写入共享数组以便能够读取子进程中的每一帧? 我不想使用队列或管道。共享内存是可行的方法,因为更多进程将消耗帧。
有几个问题,一个是共享数组的大小和形状,另一个是访问它的方式。要解决第一个问题,首先需要确保创建的数组的大小与视频帧的大小相对应。你已经阅读了一个框架并使用了它的宽度和高度(尽管
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