【问题标题】:Read images to a pre-allocated numpy array将图像读取到预先分配的 numpy 数组
【发布时间】:2019-12-01 08:45:24
【问题描述】:

我正在 Python 中进行一些 快速 图像处理(使用 Numpy/Scipy + OpenCV)。 有几千张形状完全相同的图片 - 一旦我阅读了第一张,我就知道其他所有图片的样子。

问题在于读取每个下一张图像从磁盘会导致分配新内存(速度很慢)。有没有办法通过将下一张图片直接读入一些已经存在的内存(ndarray)来避免它?我知道 cv2.imdecode 在 C++ 中可以接受指向预分配 Mat 的指针,但它似乎没有 Python 绑定(唯一的选择是返回一个全新的数组)。

我需要这个用于多处理 - 我想将图像读入共享内存,然后在工作进程中对它们做一些繁重的工作。现在,我不得不将cv2.imread 分配和返回的数组中的数据复制到共享内存中,这又需要时间。我希望能够直接在那里写。

【问题讨论】:

  • 这听起来像是对 OpenCV 有用的 PR。你使用什么文件格式?可能可以使用较低级别的库之一。
  • 您是否有分析器数据表明您的瓶颈确实在于内存分配?如果是这样,为什么不慢慢将图像读入张量并将该张量缓存到磁盘?
  • @NilsWerner 不仅仅是内存分配成为瓶颈。它也是对子进程的复制,它对图像做一些工作——无论是在通过管道发送数据期间,还是在从 OpenCV 分配的缓冲区复制到共享内存期间。我想直接将数据读取到该共享内存中,一块石头杀死分配和复制鸟;)MadPhysicist 现在我正在使用PNG,但最终我希望有一种更通用的解决方案。跨度>
  • 我也面临同样的问题。我想将帧捕获到预先分配的 numpy 数组中。你能分享我你的解决方案吗?现在,我必须编写一个 C 扩展来调用 C/C++ api,并包装一个接受 numpy 缓冲区指针的新函数。
  • 没有人找到办法做到这一点??

标签: python numpy opencv


【解决方案1】:
height, width = (50, 50)
image = np.zeros((height, width))
id(image)
# outputs: 140411457307552
image[:, :] = np.ones((height, width))
id(image)
# outputs: 140411457307552
image = np.ones((height, width))
id(image)
# outputs -> 140411437723280

# when reading from disk (assuming your images are 50x50 pixels)
image[:, :] = cv2.imread("/home/.../your_im_50x50.png")

通过寻址每个图像的尺寸,python 将尝试将给定的数组存储到现有的数组中。这导致内存分配给预分配的内存区域。如果数组的形状不同,则会引发 ValueError。 当只提到变量名时,会创建一个对数组的新引用,从而在内存中产生一个新对象(cf ids)

【讨论】:

  • 虽然是一个很好的提示,但它完全忽略了我想从磁盘读取数据并将其直接放入此内存的事实。但是,您让我意识到我的问题可能会更清楚,因此我对其进行了相应的编辑。
  • cv2.imread 返回 numpy.ndarray 对象。这就是为什么 image[:, :] = np.ones(...)image[:, :] = cv2.imread("/home/.../your_im.png") 是完全相同的事情
  • 这就是为什么你错过了问题的重点。 imread 调用已经创建了新缓冲区。花哨的复制不会让你摆脱困境。您也可以直接删除旧缓冲区并在此时替换为新缓冲区。
猜你喜欢
  • 1970-01-01
  • 2014-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多