使用在python中使用grpc和共享内存,实现功能调用。

初衷:grpc可以很好的作为跨语言,跨机器的服务模式。但是对于大量数据的传输,进程之间还是共享内存要快一些,所以这里将grpc与共享内存混合使用。

功能实现:

        客户端:从摄像头不断的读取图片,并传输给服务端,并呈现从服务端返回的处理结果。

        服务端:读取客户端的请求,并从中读取共享内存中的图片,在图片上写入”ok“,并将结果传回给客户端。

创建文件:image_processing.proto

syntax = "proto3";

package image_processing;

import "google/protobuf/empty.proto";

// 定义一个请求消息,包含共享内存的名称
message ImageRequest {
    string input_shm_name = 1;
    string output_shm_name = 2;
}

// 定义一个响应消息,包含处理后的图像的共享内存地址
message ImageResponse {
    string output_shm_name = 1;
}

// 定义清理共享内存的请求消息
message CleanupRequest {
    string output_shm_name = 1;
}

// 定义服务接口
service ImageProcessingService {
    rpc ProcessImage (ImageRequest) returns (ImageResponse);
    rpc CleanupSharedMemory (CleanupRequest) returns (google.protobuf.Empty);
}

安装python库:

pip install grpcio grpcio-tools opencv-python-headless

使用grpcio-tools生成Python代码:

python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. image_processing.proto

客户端

import grpc
import cv2
import numpy as np
from multiprocessing import shared_memory

import image_processing_pb2
import image_processing_pb2_grpc
def main():
    # 捕获图像
    #img = capture_image()
    vc=cv2.VideoCapture(0)
   

    with grpc.insecure_channel('localhost:50051') as channel:
        stub = image_processing_pb2_grpc.ImageProcessingServiceStub(channel)
        while 1:
            res,img=vc.read()
            shm = shared_memory.SharedMemory(create=True, size=img.nbytes)
            shm_array = np.ndarray(img.shape, dtype=img.dtype, buffer=shm.buf)
            shm_array[:] = img[:]

            response = stub.ProcessImage(image_processing_pb2.ImageRequest(input_shm_name=shm.name, output_shm_name=""))

            # 读取处理后的图像
            output_shm = shared_memory.SharedMemory(name=response.output_shm_name)
            output_array = np.ndarray(img.shape, dtype=img.dtype, buffer=output_shm.buf)

            # 显示处理后的图像
            cv2.imshow("Processed Image", output_array)
            cv2.waitKey(1)
        cv2.destroyAllWindows()

        # 清理共享内存
        shm.close()
        shm.unlink()
        output_shm.close()
        output_shm.unlink()

        # 通知服务端清理共享内存
        with grpc.insecure_channel('localhost:50051') as channel:
            stub = image_processing_pb2_grpc.ImageProcessingServiceStub(channel)
            stub.CleanupSharedMemory(image_processing_pb2.CleanupRequest(output_shm_name=response.output_shm_name))

if __name__ == '__main__':
    main()

服务端:

import grpc
from concurrent import futures
import cv2
import numpy as np
from multiprocessing import shared_memory
import time
import threading

import image_processing_pb2
import image_processing_pb2_grpc

# 全局字典存储共享内存对象引用
shared_memory_store = {}
lock = threading.Lock()

class ImageProcessingServiceServicer(image_processing_pb2_grpc.ImageProcessingServiceServicer):
    def ProcessImage(self, request, context):
        # 读取共享内存中的图像
        shm = shared_memory.SharedMemory(name=request.input_shm_name)
        img_array = np.ndarray((480, 640, 3), dtype=np.uint8, buffer=shm.buf)
        img = img_array.copy()  # 复制图像以确保共享内存可以被释放

        # 在图像上写“ok”
        cv2.putText(img, "ok", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2, cv2.LINE_AA)

        # 创建新的共享内存并将处理后的图像写入
        output_shm = shared_memory.SharedMemory(create=True, size=img.nbytes)
        output_array = np.ndarray(img.shape, dtype=img.dtype, buffer=output_shm.buf)
        output_array[:] = img[:]

        # 将共享内存对象存储在全局字典中
        with lock:
            shared_memory_store[output_shm.name] = output_shm

        # 启动一个线程在一段时间后清理共享内存
        threading.Timer(60, self.cleanup_shared_memory, args=(output_shm.name,)).start()

        # 返回处理后的图像的共享内存名称
        response = image_processing_pb2.ImageResponse(output_shm_name=output_shm.name)
        return response

    def cleanup_shared_memory(self, shm_name):
        with lock:
            if shm_name in shared_memory_store:
                shm = shared_memory_store.pop(shm_name)
                shm.close()
                shm.unlink()

def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=1))
    image_processing_pb2_grpc.add_ImageProcessingServiceServicer_to_server(ImageProcessingServiceServicer(), server)
    server.add_insecure_port('[::]:50051')
    server.start()
    print("Server started, listening on port 50051.")
    try:
        while True:
            time.sleep(86400)  # 运行一整天
    except KeyboardInterrupt:
        server.stop(0)

if __name__ == '__main__':
    serve()

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python使用gRPC是一种方便的方式来构建分布式系统和微服务。gRPC是一个高性能、开源的远程过程调用(RPC)框架,它使用Protocol Buffers作为接口定义语言(IDL)来定义服务接口和消息格式。 要在Python使用gRPC,首先需要安装gRPC库。可以使用pip命令进行安装: ``` pip install grpcio ``` 安装完成后,可以开始编写gRPC服务和客户端代码。首先需要定义服务接口和消息格式,这可以通过编写.proto文件来完成。然后使用gRPC提供的工具将.proto文件编译成Python代码。 接下来,可以编写服务端代码。在服务端代码,需要实现.proto文件定义的服务接口,并提供相应的方法来处理客户端请求。 最后,可以编写客户端代码来调用服务端提供的方法。客户端代码需要创建一个gRPC通道,并使用通道创建一个stub对象,然后可以通过stub对象调用服务端提供的方法。 下面是一个简单的示例代码,演示了如何在Python使用gRPC: ```python # 导入所需的模块 import grpc import helloworld_pb2 import helloworld_pb2_grpc # 创建一个gRPC通道 channel = grpc.insecure_channel('localhost:50051') # 创建一个stub对象 stub = helloworld_pb2_grpc.GreeterStub(channel) # 调用服务端提供的方法 response = stub.SayHello(helloworld_pb2.HelloRequest(name='Alice')) # 打印服务端返回的结果 print(response.message) ``` 以上代码,假设服务端提供了一个名为`SayHello`的方法,客户端通过创建一个stub对象来调用该方法,并传递一个`HelloRequest`对象作为参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值