如何在Python Linux中使用内存映射文件
正如我在Python文档中看到的 Linux中的Python可以完全支持内存映射文件。然而,当我试图将这个想法应用到我的应用程序中时。我无法运行样本 我的应用程序是将帧从Python文件(客户端)发送到另一个Python文件(服务器) 客户端代码如何在Python Linux中使用内存映射文件,python,image,frames,Python,Image,Frames,正如我在Python文档中看到的 Linux中的Python可以完全支持内存映射文件。然而,当我试图将这个想法应用到我的应用程序中时。我无法运行样本 我的应用程序是将帧从Python文件(客户端)发送到另一个Python文件(服务器) 客户端代码 import mmap import time import os import cv2 as cv print("Opening camera...") cap = cv.VideoCapture('/home/hunglv/
import mmap
import time
import os
import cv2 as cv
print("Opening camera...")
cap = cv.VideoCapture('/home/hunglv/Downloads/IMG_8442.MOV')
mm = None
try:
while True:
ret, img = cap.read()
if not ret:
break
if mm is None:
mm = mmap.mmap(-1,img.size,mmap.MAP_SHARED, mmap.PROT_WRITE)
# write image
start = time.time()
buf = img.tobytes()
mm.seek(0)
mm.write(buf)
mm.flush()
stop = time.time()
print("Writing Duration:", (stop - start) * 1000, "ms")
except KeyboardInterrupt:
pass
print("Closing resources")
cap.release()
mm.close()
服务器代码
import mmap
import time
import os
import cv2 as cv
import numpy as np
shape = (1080, 1920, 3)
n = np.prod(shape)
mm = mmap.mmap(-1, n)
while True:
# read image
print (mm)
start = time.perf_counter()
mm.seek(0)
buf = mm.read(12)
img = np.frombuffer(buf, dtype=np.uint8).reshape(shape)
stop = time.perf_counter()
print("Reading Duration:", (stop - start) * 1000, "ms")
cv.imshow("img", img)
key = cv.waitKey(1) & 0xFF
key = chr(key)
if key.lower() == "q":
break
cv.destroyAllWindows()
mm.close()
在服务器端,我将内存索引设置为0,并尝试从内存中读取字节。然而,服务器似乎无法正确地从客户端读取数据
[更新]
我尝试在服务器端读取前12个字节。该值是恒定的,不再变化
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
此外,,
随机帧的前12个字节是
b'\xf5\xff\xff\xf0\xfa\xfe\xdf\xe9\xed\xd2\xdc\xe0'
首先,我找到了可能有效的示例,但它使用了
标记名(客户机和服务器也是如此),这意味着它仅适用于窗口:
接下来,我找到了在Linux上工作的代码:
它在磁盘上创建真实文件,将其大小调整为图像大小,然后在mmap()中使用其fd
我使用网络摄像机进行测试
服务器
import mmap
import time
import os
import cv2
print("Opening camera...")
cap = cv2.VideoCapture(0)
#print(cap.get(cv.CAP_PROP_FRAME_WIDTH)) # 640
#print(cap.get(cv.CAP_PROP_FRAME_HEIGHT)) # 480
shape = (480, 640, 3)
n = (480*640*3)
fd = os.open('/tmp/mmaptest', os.O_CREAT | os.O_TRUNC | os.O_RDWR)
#os.write(fd, b'\x00' * n) # resize file
os.truncate(fd, n) # resize file
mm = None
try:
while True:
ret, img = cap.read()
if not ret:
break
if mm is None:
mm = mmap.mmap(fd, n, mmap.MAP_SHARED, mmap.PROT_WRITE) # it has to be only for writing
# write image
start = time.perf_counter()
buf = img.tobytes()
mm.seek(0)
mm.write(buf)
mm.flush()
stop = time.perf_counter()
print("Writing Duration:", (stop - start) * 1000, "ms")
except KeyboardInterrupt:
pass
print("Closing resources")
cap.release()
mm.close()
客户端
import mmap
import time
import os
import cv2
import numpy as np
shape = (480, 640, 3)
n = (480*640*3)
fd = os.open('/tmp/mmaptest', os.O_RDONLY)
mm = mmap.mmap(fd, n, mmap.MAP_SHARED, mmap.PROT_READ) # it has to be only for reading
while True:
# read image
start = time.perf_counter()
mm.seek(0)
buf = mm.read(n)
img = np.frombuffer(buf, dtype=np.uint8).reshape(shape)
stop = time.perf_counter()
print("Reading Duration:", (stop - start) * 1000, "ms")
cv2.imshow("img", img)
key = cv2.waitKey(1) & 0xFF
key = chr(key)
if key.lower() == "q":
break
cv2.destroyAllWindows()
mm.close()
顺便说一句:可能mmap()
与-1
(不在磁盘上创建文件)可以与线程(或分叉)一起工作,因为它们共享相同的内存。您收到了什么错误?数据是不正确的还是根本没有阅读?@rassar我已将信息添加到帖子中。从内存中读取的数据是相同的。对于我来说,在mmap()
中使用-1
可以创建两个分开的mmap
,两个程序使用不同的mmap
。您必须在两个mmaps
中使用相同的fileno
,也许您更应该使用共享内存或管道到套接字
从一个进程发送到另一个进程。在文档中,-1是匿名内存,我尝试使用另一个号码,但它说找不到该号码。我认为这两个Python文件将创建不同的mmaps
(两个不同的对象)。这就是服务器不理解客户端中的mmaps
的原因。非常感谢您的解决方案。现在我可以完全理解mmap
背后的机制了。我对你的解决方案非常满意。基本上,我们需要在系统中分配临时文件(虚拟文件),并告诉两个程序使用相同的文件进行访问。>我的方法与上面的链接完全相同(不幸的是,仅适用于Windows)。