Python 中的命名内存映射文件?
Named memory-mapped files in Python?
我正在使用 OpenCV 来处理网络服务中的一些视频数据。在调用 OpenCV 之前,视频已经加载到 bytearray
缓冲区,我想将其传递给 VideoCapture
对象:
# The following raises cv2.error because it can't convert '_io.BytesIO' to 'str' for 'filename'
cap = cv2.VideoCapture(buffer)
不幸的是,VideoCapture()
需要字符串文件名,而不是缓冲区。现在,我将 bytearray
保存到一个临时文件,并将其名称传递给 VideoCapture()
.
问题:
- 有没有办法在 Python 中创建 named 内存文件,这样我就可以安抚 OpenCV?
- 或者,是否有另一个支持缓冲区的 OpenCV API?
部分回答问题:我不知道在 python 中创建指向内存的命名类文件对象:这是一个操作系统来做。在 most modern *nixs 中创建命名内存映射文件有一个非常简单的方法喜欢:将文件保存到 /tmp
。这些天 /tmp
是 almost 总是一个 ramdisk。但当然它可能是 zram(基本上是压缩的 ramdisk),您可能想先检查一下。无论如何,它比抖动磁盘或依赖 os 缓存要好。
顺便说一下,制作专用 ramdisk 和 mount -t tmpfs -o size=1G tmpfs /path/to/tmpfs
一样简单,或者与 ramfs
类似。
仔细研究一下,我认为您也不会在其他 api 方面有太多好运:文件名的使用一直到 cap.cpp
,我们有这样的东西:
VideoCapture::VideoCapture(const String& filename, int apiPreference) : throwOnFail(false)
{
CV_TRACE_FUNCTION();
open(filename, apiPreference);
}
python 绑定似乎只是在此之上的薄层。但我愿意被证明是错误的!
参考资料
https://github.com/opencv/opencv/blob/master/modules/videoio/src/cap.cpp#L72
如果 VideoCapture 是 一个常规 Python 对象, 和 除了路径之外,它还接受“类文件对象” ,您可以 给它提供一个“类文件对象”,它可以从中读取。
Python的StringIO和BytesIO是内存中的类文件对象。记住一些有用的东西 ;)
OpenCV 特别需要那里的文件系统路径,所以不可能。
OpenCV 是一个计算机视觉库。它不是处理视频文件的库。
你应该看看 PyAV. It's a (proper!) wrapper for ffmpeg's libraries. You can feed data directly in there and it will decode. Here are some examples and here are its tests that demonstrate further functionality。它的文档很薄,因为大多数用法是(或应该是......)由 ffmpeg 本身记录的。
您可能能够摆脱命名管道。您可以使用 os.mkfifo
创建一个,然后使用 multiprocess
模块生成一个后台进程,将视频文件输入其中。请注意 Windows 不支持 mkfifo
。
最重要的限制是管道不支持搜索,因此您的视频也无法搜索或倒带。它是否真的有效可能取决于视频格式和 OpenCV 使用的后端(gstreamer、v4l2、...)。
注意:POSIX 专用!由于您没有提供 OS 标签,我认为没问题。
根据 this answer (and this shm_overview
manpage) there is /dev/shm
always present on the system. That's a tmpfs
mapped in a shared (not Python process memory) memory pool, as suggested ,但优点是您 不需要 创建它,所以没有有趣的发明:
os.system("mount ...")
或
Popen(["mount", ...])
包装。
只需像这样使用tempfile.NamedTemporaryFile()
:
from tempfile import NamedTemporaryFile
with NamedTemporaryFile(dir="/dev/shm") as file:
print(file.name)
# /dev/shm/tmp2m86e0e0
然后您可以将其输入 OpenCV 的 API 包装器。或者,利用 pyfilesystem
作为 device/FS.
的更广泛的包装
此外,multiprocessing.heap.Arena
uses it too, so if it didn't work, there'd be much more trouble present. For Windows check this implementation 使用 winapi
.
对于/dev/shm
的尺寸:
- this是我找到的尺寸“规格”之一,
shm.h
, shm_add_rss_swap()
, newseg()
来自 Linux 源代码可能包含更多详细信息
根据 sudo ipcs
判断,如果您不使用套接字、管道或磁盘,很可能 您希望在进程之间共享内容时使用的方式。
因为它是 POSIX,它应该可以在 POSIX 兼容系统上工作,因此 也可以在 MacOS( no) 或 Solaris,但我没有办法尝试。
我正在使用 OpenCV 来处理网络服务中的一些视频数据。在调用 OpenCV 之前,视频已经加载到 bytearray
缓冲区,我想将其传递给 VideoCapture
对象:
# The following raises cv2.error because it can't convert '_io.BytesIO' to 'str' for 'filename'
cap = cv2.VideoCapture(buffer)
不幸的是,VideoCapture()
需要字符串文件名,而不是缓冲区。现在,我将 bytearray
保存到一个临时文件,并将其名称传递给 VideoCapture()
.
问题:
- 有没有办法在 Python 中创建 named 内存文件,这样我就可以安抚 OpenCV?
- 或者,是否有另一个支持缓冲区的 OpenCV API?
部分回答问题:我不知道在 python 中创建指向内存的命名类文件对象:这是一个操作系统来做。在 most modern *nixs 中创建命名内存映射文件有一个非常简单的方法喜欢:将文件保存到 /tmp
。这些天 /tmp
是 almost 总是一个 ramdisk。但当然它可能是 zram(基本上是压缩的 ramdisk),您可能想先检查一下。无论如何,它比抖动磁盘或依赖 os 缓存要好。
顺便说一下,制作专用 ramdisk 和 mount -t tmpfs -o size=1G tmpfs /path/to/tmpfs
一样简单,或者与 ramfs
类似。
仔细研究一下,我认为您也不会在其他 api 方面有太多好运:文件名的使用一直到 cap.cpp
,我们有这样的东西:
VideoCapture::VideoCapture(const String& filename, int apiPreference) : throwOnFail(false)
{
CV_TRACE_FUNCTION();
open(filename, apiPreference);
}
python 绑定似乎只是在此之上的薄层。但我愿意被证明是错误的!
参考资料
https://github.com/opencv/opencv/blob/master/modules/videoio/src/cap.cpp#L72
如果 VideoCapture 是 一个常规 Python 对象, 和 除了路径之外,它还接受“类文件对象” ,您可以 给它提供一个“类文件对象”,它可以从中读取。
Python的StringIO和BytesIO是内存中的类文件对象。记住一些有用的东西 ;)
OpenCV 特别需要那里的文件系统路径,所以不可能。
OpenCV 是一个计算机视觉库。它不是处理视频文件的库。
你应该看看 PyAV. It's a (proper!) wrapper for ffmpeg's libraries. You can feed data directly in there and it will decode. Here are some examples and here are its tests that demonstrate further functionality。它的文档很薄,因为大多数用法是(或应该是......)由 ffmpeg 本身记录的。
您可能能够摆脱命名管道。您可以使用 os.mkfifo
创建一个,然后使用 multiprocess
模块生成一个后台进程,将视频文件输入其中。请注意 Windows 不支持 mkfifo
。
最重要的限制是管道不支持搜索,因此您的视频也无法搜索或倒带。它是否真的有效可能取决于视频格式和 OpenCV 使用的后端(gstreamer、v4l2、...)。
注意:POSIX 专用!由于您没有提供 OS 标签,我认为没问题。
根据 this answer (and this shm_overview
manpage) there is /dev/shm
always present on the system. That's a tmpfs
mapped in a shared (not Python process memory) memory pool, as suggested
os.system("mount ...")
或Popen(["mount", ...])
包装。
只需像这样使用tempfile.NamedTemporaryFile()
:
from tempfile import NamedTemporaryFile
with NamedTemporaryFile(dir="/dev/shm") as file:
print(file.name)
# /dev/shm/tmp2m86e0e0
然后您可以将其输入 OpenCV 的 API 包装器。或者,利用 pyfilesystem
作为 device/FS.
此外,multiprocessing.heap.Arena
uses it too, so if it didn't work, there'd be much more trouble present. For Windows check this implementation 使用 winapi
.
对于/dev/shm
的尺寸:
- this是我找到的尺寸“规格”之一,
shm.h
,shm_add_rss_swap()
,newseg()
来自 Linux 源代码可能包含更多详细信息
根据 sudo ipcs
判断,如果您不使用套接字、管道或磁盘,很可能 您希望在进程之间共享内容时使用的方式。
因为它是 POSIX,它应该可以在 POSIX 兼容系统上工作,因此 也可以在 MacOS( no) 或 Solaris,但我没有办法尝试。