我看了这个[post](Right way to share opencv video frame as Numpy array between multiprocessing processes),尝试完成实现。相机正在拍摄图像,只是发现,图像的形状,缓冲区和另一个进程中接收到的图像是匹配的。但接收到的图像显示白色噪声线。我尝试在读/写数组之前添加锁,但没有效果。
下面是代码,基本上我想把一个图像放入一个numpy,然后放入一个Array,这样另一个进程就可以读取图像了:
class VideoWorker(Process):
def __init__(self, shared_Array, shape,width, height, fps):
super(VideoWorker, self).__init__()
# passing width /height as want to write video file later...
self.width = width
self.height = height
self.fps = fps
self.shared_Array = shared_Array
self.shape = shape
def run(self):
name = "VideoWorker"
print ('%s %s' % (name, self.name))
cv2.namedWindow(name,cv2.WINDOW_NORMAL)
cv2.resizeWindow(name,640,480)
while True:
img = np.frombuffer(self.shared_Array,dtype=ctypes.c_uint8)
print("%s : got img shape %s " % (name, str(img.shape)))
cv2.imshow(name, img)
if cv2.waitKey(20) & 0xFF == ord('q'):
break
print("%s: done" %name)
if __name__ == '__main__':
camera = cv2.VideoCapture(0)
camera.set(cv2.CAP_PROP_FRAME_WIDTH,1280)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT,720)
width = camera.get(cv2.CAP_PROP_FRAME_WIDTH)
height = camera.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps = camera.get(cv2.CAP_PROP_FPS)
cv2.namedWindow("orig",cv2.WINDOW_NORMAL)
cv2.resizeWindow("orig",640,480)
cv2.namedWindow("loop",cv2.WINDOW_NORMAL)
cv2.resizeWindow("loop",640,480)
grabbed, frame = camera.read()
shape = frame.shape
cv2.imshow("orig",frame)
print("main: shape ",shape, "size ", frame.size, "fps ",fps)
# size is L x W x channels
shared_Array = Array(ctypes.c_uint8, shape[0] * shape[1] *shape[2], lock=False)
worker = VideoWorker(shared_Array, shape, width, height, fps )
worker.start()
print("main: reshape size ",shape[0]*shape[1]*shape[2])
while True:
buf = np.frombuffer(shared_Array,dtype=np.uint8)
print("main: frombuffer shape ",buf.shape)
buf = buf.reshape(shape)
print("main: loop buf reshape ",buf.shape)
grabbed, frame = camera.read()
cv2.imshow("loop",frame)
print ("main: frame shape ",frame.shape)
if not grabbed:
break
buf[:] = frame
if worker.is_alive() == False:
break
if cv2.waitKey(20) & 0xFF == ord('q'):
break
print("Main process done")
worker.join()
camera.release()
cv2.destroyAllWindows()
输出为两个良好窗口和一个白色条纹窗口,以及以下内容(已修整):
VideoWorker VideoWorker-1
VideoWorker : got img shape (2764800,)
VideoWorker: done
main: shape (720, 1280, 3) size 2764800 fps 30.0
main: reshape size 2764800
main: frombuffer shape (2764800,)
main: loop buf reshape (720, 1280, 3)
main: frame shape (720, 1280, 3)
main: frombuffer shape (2764800,)
main: loop buf reshape (720, 1280, 3)
main: frame shape (720, 1280, 3)
main: frombuffer shape (2764800,)
main: loop buf reshape (720, 1280, 3)
main: frame shape (720, 1280, 3)
main: frombuffer shape (2764800,)
main: loop buf reshape (720, 1280, 3)
main: frame shape (720, 1280, 3)
Main process done
在数组上共享帧时有点卡住了。我的队列工作得很好。第一篇文章是stackoverflow。有什么建议吗?
4条答案
按热度按时间k4aesqcs1#
我想明白了。是的,正如Dan指出的,我必须加入锁定(以前试过一次)。另外,我还必须得到正确的类型和大小。整形像h x w x c,而我习惯于w x h x c。这里是一个没有循环的工作解决方案,两个进程通过Array显示相同的opencv3图像。
感谢您的评论。
vxf3dgd42#
尝试添加
添加到np.frombuffer行下面的run方法
IMG看起来具有错误的形状,因此被误解。
sg24os4d3#
顺便说一句,我放弃了这种方法。我发现在Raspberry Pi 3B上,跨进程地址空间发送1280x720图像的开销太大了。CPU在98%的时候就被固定在移动帧上。我回到线程上,看起来比单线程代码的性能提高了几个百分点。
xjreopfe4#
我也遇到过类似的问题。我有4台摄像机从网络上传输数据。图像帧发生了变化并被堆叠。队列对我来说太慢了,所以我用管道解决了整个问题。队列就是基于此。4台摄像机堆叠在一个4瓦片中,并使用多处理进行处理。在我看来效果非常好。我也没有更多的延迟,使用管道代替队列。