【问题标题】:Right way to share opencv video frame as Numpy array between multiprocessing processes在多处理进程之间将opencv视频帧共享为Numpy数组的正确方法
【发布时间】:2018-08-17 21:34:04
【问题描述】:

我想与我的多处理子进程共享我在 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()

但是缓冲区bread() 函数覆盖。所以我不写入我的缓冲区/共享数组。

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

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

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

【问题讨论】:

  • 如果你这样做ret, b[:] = video_capture.read() 可能吗? (也不需要在每次循环迭代时不断调用np.frombuffer 吗?)
  • 谢谢!我试过了,我认为这是正确的方法。但它是说:“无法将输入数组从形状(720,1280,3)广播到形状(691200)”。所以我将原始opencv帧的形状分配给缓冲区(共享数组),但随后它说“ValueError:无法将大小为691200的数组重塑为形状(720,1280,3)”。你知道我如何修复数组的大小吗?
  • shared_array 似乎是扁平的

标签: python numpy opencv shared-memory python-multiprocessing


【解决方案1】:

有几个问题,一个是共享数组的大小和形状,另一个是您如何访问它。要解决第一个问题,首先需要确保创建的数组的大小与视频帧的大小相对应。您已经阅读了一个框架并使用了它的宽度和高度(尽管you can do it without reading any frame),但没有考虑它的通道数。

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

【讨论】:

  • 谢谢。这是有道理的:) 我还有一个小问题。当我在我的子进程中显示图像时,框架是黑色的。 b = np.frombuffer(self.shared_array, dtype=np.uint16) b = n.reshape(self.shape) cv2.imshow('Video', b) if cv2.waitKey(1) & 0xFF == ord('q'): break print(b) print(b) 打印正确的数组。输出矩阵填充了数字,但窗口保持黑色。
  • @Frey 我不知道为什么会这样,我对 Python 中的 OpenCV 了解不多,这似乎是一个不同的问题。
  • 谢谢。它适用于 np.uint8,但不适用于 uint16。我认为捕获的帧有 8 位。我无法从 video_capture 中读取实际的 dtype,因为枚举未知(“模块 'cv2.cv2' 没有属性 'CV_CAP_PROP_FORMAT'”)
  • @Frey 对,抱歉,好像是cv2.cv.CV_CAP_PROP_FORMAT(有关返回值,请参阅VideoCapture::getMat::depth 的文档,cv2.cv.CV8U 等)。很高兴你解决了这个问题。
  • (顺便说一句,OpenCV HTTPS 证书似乎已过期,因此浏览器在访问其网站时会显示警告...)
猜你喜欢
  • 2013-07-21
  • 1970-01-01
  • 2021-09-23
  • 1970-01-01
  • 1970-01-01
  • 2021-03-19
  • 2011-12-15
  • 2017-04-01
相关资源
最近更新 更多