问题描述
我已经使用Tensorflow 2对象检测API训练了SSD resnet V1模型。然后我想在C ++代码中将此模型与OpenCV一起使用。
首先,经过培训,我得到了三个文件:
- 检查点
- ckpt-101.data-00000-of-00001
- ckpt-101.index
然后,我使用对象检测API中的exporter_main_v2.py
脚本从这些文件中创建了SavedModel:
python3 exporter_main_v2.py input_type=image_tensor --pipeline_config_path /path/to/pipeline.config --trained_checkpoint_dir=/path/to/checkouts --output_directory=/path/to/output/directory
运行此脚本后,我得到了save_model.pb
我试图通过以下方式在OpenCV中使用此文件:
cv::dnn::Net net = cv::dnn::readNetFromTensorflow("/path/to/saved_model.pb");
但是我遇到了以下错误:
OpenCV(4.2.0) /home/andrew/opencv/modules/dnn/src/tensorflow/tf_io.cpp:42: error: (-2:Unspecified error) Failed: ReadProtoFromBinaryFile(param_file,param). Failed to parse GraphDef file: /home/andrew/Documents/tensorflow_detection/workspace/pb_model/saved_model/saved_model.pb in function 'ReadTFNetParamsFromBinaryFileOrDie'
然后我尝试冻结save_model.pb。但是,据我所知,在TF2.x中是不可能的,因为TF2.x不支持会话和图形。我也没有.pbtxt文件。
我的问题:是否可以在OpenCV C ++中使用经过TF2对象检测API训练的模型?
如果您能帮助我解决此问题或提供任何有用的建议,我将不胜感激。
解决方法
可以使用Tensorflow 2模型和对象检测API和Opencv,如专用Wiki中所述:https://github.com/opencv/opencv/wiki/TensorFlow-Object-Detection-API
到目前为止,它们与Tensorflow 1兼容的型号更多,但对于SSD来说应该可以。 要冻结图形,您必须执行以下操作:
import tensorflow as tf
from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2
loaded = tf.saved_model.load('my_model')
infer = loaded.signatures['serving_default']
f = tf.function(infer).get_concrete_function(input_1=tf.TensorSpec(shape=[None,224,3],dtype=tf.float32))
f2 = convert_variables_to_constants_v2(f)
graph_def = f2.graph.as_graph_def()
# Export frozen graph
with tf.io.gfile.GFile('frozen_graph.pb','wb') as f:
f.write(graph_def.SerializeToString())
如OpenCV Github问题中的此评论所述:https://github.com/opencv/opencv/issues/16582#issuecomment-603819498
然后,您可能需要使用OpenCV Wiki中提供的tf_text_graph_ssd.py
来生成冻结模型的文本图表示形式!
Tensorflow 2不再支持会话,因此您无法轻松地将模型导出为冻结图。我发现this解决了我在opencv中使用Tensorflow对象检测模型时遇到的问题。希望这会有所帮助。