TensorFlow2.3.0类ResNet模型转OpenCV推理报错排查
让我们一步步拆解你的问题,找到根源并解决它:
一、你操作中的核心问题
- 输入层名称错误:你在
setInput时用了'x'作为输入名称,但从你的模型结构来看,输入层的实际名称是input_1。错误的输入名称会导致OpenCV无法正确绑定输入张量,进而引发维度解析错误。 - 输入维度传递不规范:虽然你尝试了
(1,50,50)和(1,50,50,1)两种格式,但OpenCV的DNN模块对TensorFlow导出的模型,需要严格匹配模型定义的输入维度格式(你的模型是NHWC:(batch, height, width, channel)),且必须明确传递4维张量。
二、错误原因的深层解析
为什么报错里输入形状显示为input[0] = [ 1 50 ]?
这是因为OpenCV的DNN模块在无法正确匹配输入张量时,会错误解析输入维度:当你传入(1,50,50)的3维张量,又用了错误的输入名称'x',OpenCV无法对应到模型定义的4维输入层,就会把输入错误识别为2维张量(1,50),剩下的一个维度被忽略,这直接导致后续卷积层无法处理不匹配的输入通道数,触发断言失败。
卷积层断言错误的根源
报错里的ngroups > 0 && inpCn % ngroups == 0 && outCn % ngroups == 0,本质是输入通道数和卷积核的通道数不匹配:你的第一个卷积层conv2d的卷积核是[20,1,3,3](对应20个3x3的1通道核),但错误解析后的输入通道数被识别为50,和卷积核的输入通道数1不匹配,触发了断言检查。
三、具体解决步骤
按照以下顺序操作,应该能解决问题:
确认输入层的正确名称
打开你的optmized_graph.pbtxt文件,找到输入层的名称(应该是input_1),在设置输入时使用这个正确名称,或者如果模型只有一个输入,可以省略名称。构造正确的4维输入张量
严格按照模型定义的(None,50,50,1)格式构造输入:# 生成符合要求的输入:batch=1, 50x50, 单通道 image = np.random.rand(1, 50, 50, 1).astype("float32")正确设置模型输入
使用正确的输入名称(如果需要),并确保OpenCV正确识别输入维度:# 方法1:使用正确的输入层名称 net.setInput(image, 'input_1') # 方法2:省略名称(单输入模型) # net.setInput(image)可选:显式设置输入形状(如果仍有问题)
如果OpenCV还是无法正确解析输入维度,可以提前显式设置输入形状:net.setInputShape((1, 50, 50, 1)) # NHWC格式,匹配你的模型定义验证导出模型的正确性
如果你按照上述步骤仍有问题,需要确认冻结优化后的模型是否正确:import tensorflow as tf tf.compat.v1.disable_eager_execution() with tf.compat.v1.Session() as sess: # 加载pb模型 with tf.io.gfile.GFile("optmized_graph.pb", 'rb') as f: graph_def = tf.compat.v1.GraphDef() graph_def.ParseFromString(f.read()) sess.graph.as_default() tf.import_graph_def(graph_def, name='') # 查看输入张量的信息 input_tensor = sess.graph.get_tensor_by_name('input_1:0') print("输入张量名称:", input_tensor.name) print("输入张量形状:", input_tensor.shape)确保输出的形状是
(?, 50, 50, 1),如果不是,说明模型冻结优化过程中出现了问题,需要重新导出。
额外注意事项
- 你的TensorFlow版本是2.3.0,而你用了TensorFlow1.5的优化工具,版本差异可能导致模型导出时出现兼容性问题,建议使用TensorFlow 2.x自带的冻结导出方法(比如
tf.saved_model.save后转pb,或者使用tf.compat.v1.graph_util.convert_variables_to_constants),避免跨版本工具的兼容性问题。 - OpenCV 4.4.0对TensorFlow模型的支持已经比较完善,但确保你的pbtxt文件正确生成,包含了所有层的形状和参数信息。
内容的提问来源于stack exchange,提问作者Boris Brodski

