如何在multiprocessing多进程间共享numpy数组,实现Kivy GUI展示3D扫描实时数据
问题原因
多进程模式下,每个进程拥有独立的虚拟内存空间,子进程的全局变量是主进程对应变量的副本,修改子进程的变量不会同步到主进程,所以你之前用全局变量传数据的写法无法生效。
解决方案
通过multiprocessing提供的共享内存+锁的方案实现numpy数组跨进程共享,相比Manager序列化传输的方案,共享内存的读写效率更高,完全满足实时帧传输的需求。
修改后的完整代码
import numpy as np import cv2 from kivy.app import App from kivy.uix.image import Image from kivy.uix.gridlayout import GridLayout from kivy.clock import Clock from kivy.graphics.texture import Texture from multiprocessing import Process, Array, Lock import ctypes # 帧参数:高度、宽度、通道数,可根据你的实际输出调整 FRAME_H = 480 FRAME_W = 640 FRAME_CH = 3 class CamApp(App): # 初始化时传入共享内存和锁 def __init__(self, shared_frame, lock, **kwargs): super().__init__(**kwargs) self.shared_frame = shared_frame self.lock = lock def update_slider(self, instance, value): self.slider_value = value*3 def build(self): self.img1=Image() layout = GridLayout(cols = 1) layout.add_widget(self.img1) Clock.schedule_interval(self.update, 1.0/33.0) return layout def update(self, dt): # 加锁读取共享内存,避免读写冲突 with self.lock: # 把共享内存转成numpy数组 frame = np.frombuffer(self.shared_frame.get_obj(), dtype=np.uint8).reshape(FRAME_H, FRAME_W, FRAME_CH) # 原有渲染逻辑不变 buf1 = cv2.flip(frame, 0) buf = buf1.tobytes() texture1 = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr') texture1.blit_buffer(buf, colorfmt='bgr', bufferfmt='ubyte') self.img1.texture = texture1 def cam(message, shared_frame, lock): print(message) dc = DepthCamera() while True: ret, depth_frame, colour_frame = dc.get_frame() frame = cv2.applyColorMap(cv2.convertScaleAbs(depth_frame, alpha=0.2), cv2.COLORMAP_BONE) # 加锁写入共享内存 with lock: # 把numpy数组数据写入共享内存 shared_array = np.frombuffer(shared_frame.get_obj(), dtype=np.uint8).reshape(FRAME_H, FRAME_W, FRAME_CH) np.copyto(shared_array, frame) if __name__ == '__main__': # 创建锁,防止读写冲突 frame_lock = Lock() # 创建共享内存,大小对应单帧所有像素的字节数 shared_frame = Array(ctypes.c_ubyte, FRAME_H * FRAME_W * FRAME_CH) # 启动子进程时传入共享内存和锁 p = Process(target=cam, args=('beginning capture', shared_frame, frame_lock)) p.start() # 启动Kivy应用时传入共享内存和锁 CamApp(shared_frame, frame_lock).run() cv2.destroyAllWindows()
关键修改说明
- 提前定义好帧的高度、宽度、通道数参数,确保共享内存大小和实际帧大小完全匹配
- 新增
Lock对象,保证读写帧操作互斥执行,避免出现画面撕裂、花屏问题 - 子进程和主进程都通过
np.frombuffer直接访问共享内存,不需要额外序列化传输,延迟极低 - 移除了全局变量的使用,所有共享数据通过参数传递给对应进程和实例
内容的提问来源于stack exchange,提问作者John G
相关产品推荐
相关产品推荐

