【问题标题】:gRPC python sending image + meta datagRPC python发送图像+元数据
【发布时间】:2020-06-03 10:49:06
【问题描述】:

我需要将图像(numpy 数组)、有关图像的其他元信息(例如高度、宽度等)从 python grpc 客户端传递到 python grpc 服务器。

我需要运行这个方法。

import numpy as np 

def predict(img, w, h):
    # some operations
    return img.shape[2], np.mean(img)

我查看了文档,但 protobuf 中的 numpy 数组没有兼容的数据类型。

https://developers.google.com/protocol-buffers/docs/proto3

image_procedure.proto

syntax = "proto3";

// input image, width, height
message Image {
    image_type image = 1;
    int32 width = 2;
    int32 height = 3;
}

// output prediction

message Prediction {
    int32 channel = 4;
    float mean = 5;
}

// service
service ImageProcedure {
    rpc ImageMeanWH(Image) returns (Prediction) {}
}

如何将图像和其他相关数据发送到服务器并获得响应?

【问题讨论】:

    标签: python grpc


    【解决方案1】:

    您始终可以将您的 numpy 数组编码为 base64 字符串并将其传递给服务器。

    您的.proto 文件应如下所示:

    syntax = "proto3";
    
    // input image, width, height
    message B64Image {
        string b64image = 1;
        int32 width = 2;
        int32 height = 3;
    }
    
    // output prediction
    
    message Prediction {
        int32 channel = 4;
        float mean = 5;
    }
    
    // service
    service ImageProcedure {
        rpc ImageMeanWH(B64Image) returns (Prediction) {}
    }
    

    一旦你编译了你的.proto文件

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

    将为您生成两个.py 文件:

    image_procedure_pb2.py

    image_procedure_pb2_grpc.py

    在客户端代码中,通过使用base64对图像进行编码来生成请求消息。

    frame = np.random.randint(0,255, (416,416,3), dtype=np.uint8) # dummy rgb image
    
    data = base64.b64encode(frame)
    
    
    # create a valid request message
    image_req = image_procedure_pb2.B64Image(b64image = data, width = 416, height = 416)
    

    在您的程序中,只需解码 base64 并运行您想要的任何操作。

    import numpy as np 
    import base64
    
    def predict(b64img, w, h):
        b64decoded = base64.b64decode(b64img)
    
        imgarr = np.frombuffer(b64decoded, dtype=np.uint8).reshape(w, h, -1)
    
        return imgarr.shape[2], np.mean(imgarr)
    

    我将代码扩展成教程,你可以在这里查看:https://github.com/zabir-nabil/simple-gRPC

    【讨论】:

    • 谢谢,您能建议如何为这种情况编写服务器/客户端代码吗?
    【解决方案2】:

    似乎是一个老话题,但希望其他人仍然可以从答案中受益。

    在我的例子中,我有一个用 Qt 编写的 C++ GUI 应用程序来显示图像(服务器)。客户端我有 Matlab (Mex/C++) 和 Python。

    protobuf 文件 (Proto3) 如下所示:

    message DataElement {
        string name = 1;
        ElementType type = 2;
        repeated int32 dimension = 3;
        repeated int32 offset = 4;        
        bytes data = 5;
        int32 viewIndex = 6;
    }
    message EmptyReply {}
    service ImageServer {
        rpc setImage(DataElement) returns (EmptyReply) {}
    }
    

    我的 python 客户端看起来像:

    class SetImageClient:
        def __init__(self):
            self.channel = grpc.insecure_channel('localhost:50061')
            self.stub = ImageProtoBuf_pb2_grpc.ImageServerStub(self.channel)    
    
        def setImage(self, viewIndex, name, offset, ndarray):
            dataElement = ImageProtoBuf_pb2.DataElement(viewIndex = viewIndex, 
                name = name, offset=offset, dimension=ndarray.shape, data=ndarray.tobytes())
            self.stub.setImage(dataElement)
    

    我没有 python 服务器端代码(正如我提到的,我使用 C++ 服务器)。但基本上它应该只是一个相反的过程。收到数据(DataElement 格式)后,可以通过以下方式转换为 numpy.ndarray:

    ndarray1 = np.frombuffer(dataElement.data, dtype='uint8')
    ndarray1 = np.reshape(ndarray1, dataElement.dimension)
    

    你应该很高兴。

    【讨论】:

      猜你喜欢
      • 2017-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-21
      • 1970-01-01
      • 2019-03-09
      • 2020-05-24
      • 2021-04-14
      相关资源
      最近更新 更多