You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenCV读取含UpSampling2D层的TensorFlow冻结图报错求解决方案

问题:OpenCV读取含UpSampling2D层的TensorFlow冻结图报错

调用cv2.dnn.readNetFromTensorflow('./frozen.pb')读取包含UpSampling2D层的TensorFlow冻结图时,出现如下错误:

cv_model = cv2.dnn.readNetFromTensorflow('./frozen.pb')
cv2.error: OpenCV(4.6.0) /io/opencv/modules/dnn/src/tensorflow/tf_importer.cpp:2824: error: (-2:Unspecified error) More than one input is Const op in function 'getConstBlob'

可复现问题的Python代码如下(错误出现在最后一行):

import cv2
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2

# Create model
model = keras.Sequential([
    layers.Input((10, 10, 3)),
    layers.Conv2D(8, 3, activation='elu', padding='same'),
    layers.UpSampling2D(size=(2, 2)),
])
model.compile(optimizer='adam', loss='mse')
model.summary()

# Freeze model
full_model = tf.function(lambda x: model(x))
full_model = full_model.get_concrete_function(
    tf.TensorSpec(model.inputs[0].shape, model.inputs[0].dtype))
frozen_func = convert_variables_to_constants_v2(full_model)
frozen_func.graph.as_graph_def()
tf.io.write_graph(frozen_func.graph, './', 'frozen.pb', False)

# read frozen graph with opencv
cv_model = cv2.dnn.readNetFromTensorflow('./frozen.pb') # Error here

注释掉UpSampling2D层后,生成的冻结图可被OpenCV正常读取。已在Windows 10、Ubuntu 22.04系统,多个版本OpenCV和TensorFlow(含最新版),以及C++中使用OpenCV 4.5.5加载模型,均出现相同错误。


解决办法

方案1:替换UpSampling2D为Conv2DTranspose

OpenCV的DNN模块对UpSampling2D的TensorFlow实现支持存在问题,可将模型中的UpSampling2D替换为Conv2DTranspose,功能近似且能被OpenCV正常解析:

# 修改后的模型定义
model = keras.Sequential([
    layers.Input((10, 10, 3)),
    layers.Conv2D(8, 3, activation='elu', padding='same'),
    # 用Conv2DTranspose替代UpSampling2D,参数对应2倍上采样
    layers.Conv2DTranspose(8, 3, strides=(2,2), padding='same', activation='elu'),
])

注:Conv2DTranspose会引入可训练参数,若不需要额外训练,可将其权重固定为上采样的等效值(比如核权重设置为单位矩阵相关值)。

方案2:通过ONNX格式中转

先将TensorFlow模型转换为ONNX格式,再用OpenCV读取ONNX模型,绕开TensorFlow冻结图的解析问题:

  1. 安装ONNX转换工具:
pip install tf2onnx onnx
  1. 修改模型导出代码,转为ONNX:
# 替换原冻结图导出代码,改为导出ONNX
import tf2onnx
spec = tf.TensorSpec(model.inputs[0].shape, model.inputs[0].dtype, name="input")
output_path = "./model.onnx"
tf2onnx.convert.from_keras(model, input_signature=[spec], output_path=output_path)

# 用OpenCV读取ONNX模型
cv_model = cv2.dnn.readNetFromONNX(output_path)

方案3:手动修改冻结图的节点结构

如果必须保留UpSampling2D层,可手动编辑冻结图,合并或调整导致错误的Const节点:

  1. 用TensorFlow加载冻结图,查看节点结构:
import tensorflow as tf
graph_def = tf.compat.v1.GraphDef()
with open('./frozen.pb', 'rb') as f:
    graph_def.ParseFromString(f.read())
# 打印所有Const节点
for node in graph_def.node:
    if node.op == 'Const':
        print(node.name)
  1. 找到UpSampling2D相关的多个Const节点,尝试将其合并为单个输入(需熟悉TensorFlow图结构),重新保存冻结图后再用OpenCV读取。

内容的提问来源于stack exchange,提问作者Andrew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 14:24:52