如何通过JSON向TensorFlow Model Server发送图片发起推理请求
问题根因
报错来自三个明确的问题:
- 当前导出模型的
serving_default签名输入为DT_FLOAT类型张量,固定形状(-1, 256, 256, 3),只接收解码、归一化完成的浮点型像素数组,原生不支持直接传入base64编码的图片二进制。b64传参仅适用于计算图内内置了图片解码预处理逻辑的模型,当前模型没有这层逻辑,自然会报类型不匹配错误。 __saved_model_init_op是模型加载时的内部初始化签名,不具备推理能力,用这个签名发请求必然报错。- 请求URL路径错误,TF Serving的REST预测接口路径不是
/models/resnet_model/1,该路径是模型元信息查询接口,预测接口固定为/v1/models/resnet_model:predict。
解决方案
方案1:客户端预处理图片后传浮点数组(无需重导模型,快速可用)
发请求前在客户端把图片处理成符合模型输入要求的浮点数组,按正确格式调用即可:
- 预处理图片:将256×256尺寸的PNG图片解码为RGB三通道数组,严格按照训练时的归一化规则处理(通常是将0-255的像素值除以255缩放到0-1区间,必须和训练逻辑完全一致,否则推理结果会失真),最终得到形状为
(256,256,3)的float32类型数组。 - 构造请求:向
POST http://localhost:8501/v1/models/resnet_model:predict地址发请求,请求体可参考以下两种格式:- 显式指定输入名(和签名里的
keras_layer_1_input对应):
{ "signature_name": "serving_default", "instances": [ { "keras_layer_1_input": [[[0.1,0.2,0.3], /* 此处放处理完成的256*256*3浮点数组 */]] } ] }- 单输入场景可省略输入名,直接传数组:
{ "signature_name": "serving_default", "instances": [[[/* 256*256*3浮点数组 */]]] } - 显式指定输入名(和签名里的
Python端调用参考代码:
import requests import numpy as np from PIL import Image # 加载并预处理图片 img = Image.open("test.jpg").resize((256,256)).convert("RGB") img_arr = np.array(img).astype(np.float32) / 255.0 # 归一化逻辑和训练保持一致 img_arr = np.expand_dims(img_arr, axis=0).tolist() # 发送预测请求 resp = requests.post( "http://localhost:8501/v1/models/resnet_model:predict", json={"instances": img_arr} ) print(resp.json()) # 返回结果中dense_2字段为长度2的数组,分别对应两个类别的概率,取最大值索引即为分类结果
方案2:重导模型内置预处理逻辑(支持直接传base64,调用更简便)
如果不想每次调用都在客户端做图片预处理,可以在导出模型时把base64解码、图片缩放、归一化逻辑封装进模型计算图,部署后即可直接传base64格式的图片。
重导模型参考代码:
import tensorflow as tf # 定义base64图片预处理逻辑 def preprocess_b64(b64_tensor): img_bytes = tf.io.decode_base64(b64_tensor) img = tf.io.decode_png(img_bytes, channels=3) # 如果是jpg就换成decode_jpeg img = tf.image.resize(img, [256, 256]) img = tf.cast(img, tf.float32) / 255.0 # 和训练时归一化逻辑一致 return img # 加载训练好的原模型 trained_model = tf.keras.models.load_model("/home/pc3/deep_learning/models/resnet/1") # 构建带预处理层的新模型,输入直接接收字符串类型的base64值 input_layer = tf.keras.Input(shape=(), dtype=tf.string, name="image_b64") preprocessed_img = tf.keras.layers.Lambda(preprocess_b64)(input_layer) output = trained_model(preprocessed_img) export_model = tf.keras.Model(inputs=input_layer, outputs=output) # 导出新模型,重启TF Serving加载新模型路径即可 tf.saved_model.save(export_model, "/home/pc3/deep_learning/models/resnet_b64/1")
新模型部署后,即可直接用你之前的base64格式传参请求。
内容的提问来源于stack exchange,提问作者blnks
相关产品推荐
相关产品推荐

