TensorFlow2目标检测API转Frozen Graph报input_tensor缺失错求解决
报错根因
报错核心为输入张量键名完全不匹配:
- 原参考转换代码适配MNIST手写数字模型,对应输入键名为
flatten_input;当前使用的SSD目标检测模型,serving_default签名的必填输入键名与报错提示一致,为input_tensor - 转换过程中手动填写
input_1作为参数名,未匹配模型签名的实际参数定义,因此触发必填参数缺失的类型错误
报错修复方案
按以下步骤调整转换代码即可解决问题:
- 加载自身导出的目标检测SavedModel,打印签名输入参数,确认实际要求的键名(避免凭猜测填参数):
loaded = tf.saved_model.load("./exported-models/models/Bel_model/saved_model") print(loaded.signatures['serving_default'].inputs) # 目标检测API导出的image_tensor类型模型,固定输入键名为input_tensor - 替换原转换代码里错误的输入键名,匹配模型实际的输入要求,调整后的完整可运行代码如下:
关键注意点:不可直接套用MNIST示例的28x28单通道输入参数,目标检测API导出图已内置640x640预处理逻辑,原生支持任意尺寸的3通道uint8图像输入import tensorflow as tf from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2 # 加载实际训练导出的目标检测模型路径 loaded = tf.saved_model.load("./exported-models/models/Bel_model/saved_model") infer = loaded.signatures['serving_default'] # 输入键名严格匹配签名要求的input_tensor,类型对应模型支持的uint8 RGB图像 f = tf.function(infer).get_concrete_function( input_tensor=tf.TensorSpec(shape=[None, None, None, 3], dtype=tf.uint8) ) f2 = convert_variables_to_constants_v2(f) graph_def = f2.graph.as_graph_def() # 导出冻结图文件 with tf.io.gfile.GFile('./frozen_inference_graph.pb', 'wb') as f: f.write(graph_def.SerializeToString())
其他Frozen Graph生成的可行路径
除手动写代码转换外,还有几个兼容性更高的方案:
- 直接使用目标检测API导出流程内置的冻结图生成逻辑:执行模型导出脚本时,输出目录会自动生成适配的冻结图文件,不需要二次转换
- 走ONNX转换链路:通过标准tf2onnx工具将SavedModel转为ONNX格式,OpenCV 4.5以上版本可直接读取ONNX模型推理,不需要处理冻结图的算子兼容问题
- 跳过冻结图生成环节:OpenCV 4.8及以上版本已支持直接加载TF2格式的SavedModel,搭配训练时的pipeline.config文件即可完成推理,减少中间转换的误差
Keras训练路径的简便性说明
- 如果使用纯Keras接口实现目标检测模型训练,整个导出链路不需要依赖目标检测API的自定义脚本,模型本身是标准Keras结构,保存、转换的接口均为TensorFlow原生支持,不需要手动匹配自定义的serving签名,转换流程代码量更少、坑点更少
- 但纯Keras实现的目标检测模型,缺失目标检测API自带的推理优化(比如算子融合、TensorRT适配、内置后处理加速),同精度下的推理速度会低于API导出的专用模型
内容的提问来源于stack exchange,提问作者Bleach
相关产品推荐
相关产品推荐

