需要用C++调用tensoeflow模型,但我发现现在的tensorflow2.x的版本都是用keras搭建的,不想用动态库,决定直接用Opencv调用模型。
库版本:
tensorflow 2.2.0
opencv 4.2.0.32
参考:OpenCV使用Tensorflow2-Keras模型_风翼冰舟的博客-CSDN博客_opencv调用keras模型
tensorflow Frozen-Graph-TensorFlow/TensorFlow_v2 at master · leimao/Frozen-Graph-TensorFlow · GitHub
主要保存模型部分
# Convert Keras model to ConcreteFunction
full_model = tf.function(lambda x: model(x))
full_model = full_model.get_concrete_function(
x=tf.TensorSpec(model.inputs[0].shape, model.inputs[0].dtype))
# Get frozen ConcreteFunction
frozen_func = convert_variables_to_constants_v2(full_model)
frozen_func.graph.as_graph_def()
# Save frozen graph from frozen ConcreteFunction to hard drive
tf.io.write_graph(graph_or_graph_def=frozen_func.graph,
logdir="./frozen_models",
name="simple_frozen_graph.pb",
as_text=False)
用的github里面的例子1测试
训练模型,用的mnist数据集,下载数据集部分,如果报错(url无效什么的)可以手动下载后放在C:\Users\Administrator\.keras\datasets\fashion-mnist 里面
def wrap_frozen_graph(graph_def, inputs, outputs, print_graph=False):
def _imports_graph_def():
tf.compat.v1.import_graph_def(graph_def, name="")
wrapped_import = tf.compat.v1.wrap_function(_imports_graph_def, [])
import_graph = wrapped_import.graph
return wrapped_import.prune(
tf.nest.map_structure(import_graph.as_graph_element, inputs),
tf.nest.map_structure(import_graph.as_graph_element, outputs))
训练以及保存模型
def trainmodel2():
tf.random.set_seed(seed=0)
# Get data
(train_images, train_labels), (test_images,
test_labels) = get_fashion_mnist_data()
# Create Keras model
model = keras.Sequential(layers=[
keras.layers.InputLayer(input_shape=(28, 28), name="input"),
keras.layers.Flatten(input_shape=(28, 28), name="flatten"),
keras.layers.Dense(128, activation="relu", name="dense"),
keras.layers.Dense(10, activation="softmax", name="output")
], name="FCN")
# Print model architecture
model.summary()
# Compile model with optimizer
model.compile(optimizer="adam",
loss="sparse_categorical_crossentropy",
metrics=["accuracy"])
# Train model
model.fit(x={"input": train_images}, y={"output": train_labels}, epochs=1)
# Save model to SavedModel format
tf.saved_model.save(model, "./frozen_models/simple_model")
#tf.model.save((model, "./frozen_models/simple_model"))
# Convert Keras model to ConcreteFunction
full_model = tf.function(lambda x: model(x))
full_model = full_model.get_concrete_function(
x=tf.TensorSpec(model.inputs[0].shape, model.inputs[0].dtype))
# Get frozen ConcreteFunction
frozen_func = convert_variables_to_constants_v2(full_model)
frozen_func.graph.as_graph_def()
# Save frozen graph from frozen ConcreteFunction to hard drive
tf.io.write_graph(graph_or_graph_def=frozen_func.graph,
logdir="./frozen_models",
name="simple_frozen_graph.pb",
as_text=False)
tensorflow调用测试
def tftest():
# Load frozen graph using TensorFlow 1.x functions
with tf.io.gfile.GFile("./frozen_models/simple_frozen_graph.pb", "rb") as f:
graph_def = tf.compat.v1.GraphDef()
loaded = graph_def.ParseFromString(f.read())
# Wrap frozen graph to ConcreteFunctions
frozen_func = wrap_frozen_graph(graph_def=graph_def,
inputs=["x:0"],
outputs=["Identity:0"],
print_graph=True)
print("-" * 50)
print("Frozen model inputs: ")
print(frozen_func.inputs)
print("Frozen model outputs: ")
print(frozen_func.outputs)
#调用测试
test_x = cv2.imread("1.png",0)
test_x=cv2.resize(test_x,(28,28))
pred_y = frozen_func(x=tf.constant(test_x,dtype=tf.float32))[0]
print(pred_y[0].numpy())
python-opencv调用测试
def opencvtest():
test_x = cv2.imread("1.png",0)
test_x = cv2.dnn.blobFromImage(image=test_x, scalefactor=1.0, size=(28, 28))
net = cv2.dnn.readNetFromTensorflow("./frozen_models/simple_frozen_graph.pb")
net.setInput(test_x)
pred = net.forward()
print(pred)
c++opencv调用测试
int main() {
Mat test_x = imread("1.png", 0);
test_x = cv::dnn::blobFromImage(test_x,1.0,Size(28, 28));
dnn::Net net = cv::dnn::readNetFromTensorflow("simple_frozen_graph.pb");
net.setInput(test_x);
Mat pred = net.forward();
cout << pred << endl;
return 0;
}
更多完整代码参考:
GitHub - ziyaoma/Opencv-Tensorflow2.x: 用opencv调用tensorflow2.x的keras训练的模型
问题:
用tensorflow2.6版本出现opencv调动报错,
error: (-2:Unspecified error) Can't create layer "NoOp" of type "NoOp" in function 'cv::dnn::dnn4_v20191202::LayerData::getLayerInstance'
解决:
估计是版本不匹配吧,降到了2.2就可以了,
对比发现输出多了一层,不知道怎么解决,有知道的大佬求告知