You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 11:57:04