如何在两个python程序中共享OpenCV图像?

2024-03-29 07:44:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我有三个python文件:glob_变量py,阅读_凸轮.py,阅读_全局变量.py. 其内容如下: 球_变量py:

globVar = {}
def set(name, val):
    globVar[name] = val

def get(name):
    val = globVar.get(name, None)
    return val

阅读_凸轮.py

^{pr2}$

阅读_全局变量.py

import glob_var
import cv2
from time import sleep

if __name__ == '__main__':
    key = 0
    while key != 27:
        img = glob_var.get('image')
        if img is None:
            print(f"no image in globVar")
            sleep(1)
            continue

        print(f"read image with shape {img.shape}")
        cv2.imshow('image', img)
        key = cv2.waitKey(1) & 0xFF

从那三只Python的苍蝇中,我想你们知道我想做什么。是的,我想读书_凸轮.py从摄像机读取图像并将其广播到全局变量。然后读_全局变量.py可以把图像显示出来。我读_凸轮.py在一个终端上读取_全局变量.py另一个。 但我没有让它正常工作。我想的可能吗?我怎么办?谢谢!在

=====update1:python中的Pub和Sub=====
我使用ROS(机器人操作系统)系统有一段时间了。它提供了pub和sub功能来在不同的程序或所谓的节点之间交换变量。所以我的问题是python中有没有提供这种功能的包?Redis提供这种服务,是最快的还是最好的?在


Tags: keynamepyimageimportnoneimgget
2条回答

您可以使用Python的多处理模块中的共享数组在进程之间快速共享大量数据。我没有任何像我建议的Redis答案那样的完整的、经过测试的代码,但是我有足够的代码让你开始。在

所以你可以使用:

from multiprocessing import Process, Queue
from multiprocessing.sharedctypes import Array
from ctypes import c_uint8

然后在您的main中,您将声明一个大数组,可能大到足以容纳2-4个大图像:

^{pr2}$

以及

# Create zeroed out shared array
buffer = Array(c_uint8, bufShape[0] * bufShape[1] * bufShape[2])
# Make into numpy array
buf_arr = np.frombuffer(buffer.get_obj(), dtype=c_uint8)
buf_arr.shape = bufShape

# Create a list of workers
workers = [Worker(1, buffer, str(i)) for i in range(2)]

# Start the workers
for worker in workers:
    worker.start()

然后,您将从流程类中派生工人,如下所示:

class Worker(Process):
    def __init__(self, q_size, buffer, name=''):
        super().__init__()
        self.queue = Queue(q_size)
        self.buffer = buffer
        self.name = name

    def run(self,):
        buf_arr = np.frombuffer(self.buffer.get_obj(), dtype=c_uint8)
        buf_arr.shape = bufShape
        while True:
            item = self.queue.get()
            ...

您可以在run()的开头看到,worker只是从大的共享缓冲区生成一个Numpy数组,所以worker正在读取主程序正在写入的内容,但希望您对它进行同步,以便main在写入帧2-4时,worker正在读取帧1。在

然后希望您可以看到,主程序可以通过使用以下方法将一个简单的帧索引写入工人的队列(而不是发送整个帧本身),从而告诉工人存在一个数据帧:

worker.queue.put(i)

您可以使用Redis来完成此操作。它是一个非常快速的内存数据结构服务器,可以为字符串、整数、哈希、列表、队列、集合、有序集、图像提供服务。它是免费和简单的安装在macOSLinuxWindows上。在

也可以使用^ {CD1>}、Python、PHP、C/C++或其他许多语言读写ReDIS值。此外,您可以通过网络或世界各地的服务器进行读写操作,只需更改初始连接中的IP地址即可。所以,你可以在Linux下的树莓Pixon上获取图片,并在C/C++环境下在Windows下存储并在PC上处理。在

然后,您只需将图像放入名为Camera1或{}的Redis,或者将它们放入一个已排序的散列中,这样就可以按帧号对图像进行缓冲。您还可以给图像(或其他数据结构)一个“生存时间”,这样您的RAM不会被填满。在

下面是您为使用Redis而重写的代码的要点。暂时没有严重的错误检查或灵活性。一切正常。在

以下是read_cam.py

#!/usr/bin/env python3

import cv2
import struct
import redis
import numpy as np

def toRedis(r,a,n):
   """Store given Numpy array 'a' in Redis under key 'n'"""
   h, w = a.shape[:2]
   shape = struct.pack('>II',h,w)
   encoded = shape + a.tobytes()

   # Store encoded data in Redis
   r.set(n,encoded)
   return

if __name__ == '__main__':

    # Redis connection
    r = redis.Redis(host='localhost', port=6379, db=0)

    cam = cv2.VideoCapture(0)
    key = 0
    while key != 27:
        ret, img = cam.read()
        cv2.imshow('img', img)

        key = cv2.waitKey(1) & 0xFF
        toRedis(r, img, 'image')

这里是read_globvar.py

^{pr2}$

请注意,您可以在JSON中同样地存储图像的高度和宽度,并将其存储在Redis中,而不是我所做的struct.pack和{}中。在

另外请注意,您可以在内存中将图像编码为JPEG并将其存储在Redis中(而不是Numpy数组),这样可以节省内存和网络带宽。在

不管怎样,使用Redis的概念都是一样的。在

相关问题 更多 >