不止一个输入是 Const Op

Posted

技术标签:

【中文标题】不止一个输入是 Const Op【英文标题】:More than one input is Const Op 【发布时间】:2020-04-25 20:04:57 【问题描述】:

我正在尝试在 opencv 中提供以下 gitrepo:https://github.com/una-dinosauria/3d-pose-baseline,并且可以在以下链接中找到检查点数据:https://drive.google.com/file/d/0BxWzojlLp259MF9qSFpiVjl0cU0/view

我已经构建了一个可以在 python 中提供服务的冻结图,并且是使用以下脚本生成的:

meta_path = 'checkpoint-4874200.meta' # Your .meta file
output_node_names = ['linear_model/add_1']    # Output nodes
export_dir=os.path.join('export_dir')
graph=tf.Graph()

with tf.Session(graph=graph) as sess:
# Restore the graph
    loader=tf.train.import_meta_graph(meta_path)
    loader.restore(sess,'checkpoint-4874200')

    builder=tf.saved_model.builder.SavedModelBuilder(export_dir)
    builder.add_meta_graph_and_variables(sess,
                                     [tf.saved_model.SERVING],
                                     strip_default_attrs=True)


# Freeze the graph
frozen_graph_def = tf.graph_util.convert_variables_to_constants(
    sess,
    sess.graph_def,
    output_node_names)

# Save the frozen graph
with open('C:\\Users\\FrozenGraph.pb', 'wb') as f:
  f.write(frozen_graph_def.SerializeToString())

然后我通过运行优化图表:

optimized_graph_def=optimize_for_inference_lib.optimize_for_inference(
    frozen_graph_def,
    ['inputs/enc_in'],
    ['linear_model/add_1'],
    tf.float32.as_datatype_enum)
g=tf.gfile.FastGFile('optimized_inference_graph.pb','wb')
g.write(optimized_graph_def.SerializeToString())

优化的冻结图可以在:https://github.com/alecda573/frozen_graph/blob/master/optimized_inference_graph.pb

当我尝试在 opencv 中运行时,出现以下运行时错误:

OpenCV(4.3.0) Error: Unspecified error (More than one input is Const op) in cv::dnn::dnn4_v20200310::`anonymous-namespace'::TFImporter::getConstBlob, file C:\build\master_winpack-build-win64-vc15\opencv\modules\dnn\src\tensorflow\tf_importer.cpp, line 570

复制步骤

要重现问题,您只需要从上面的链接下载冻结图或从检查点数据创建自己,然后在 opencv 中使用以下标题调用以下内容:

 #include <iostream>
 #include <vector>
 #include <cmath>
 #include <opencv2/core/core.hpp>
 #include <opencv2/highgui/highgui.hpp>
 #include <opencv2/imgproc.hpp>
 #include "opencv2/dnn.hpp"


string pbFilePath = "C:/Users/optimized_inferene_graph.pb";
//Create 3d-pose-baseline model
cv::dnn::Net inputNet;
inputNet = cv::dnn::readNetFromTensorflow(pbFilePath);

想知道是否有人对如何解决此错误有任何想法。

您可以从附加的照片中看到我使用 tensorboard 生成的冻结图和优化图。

我感觉错误是由训练标志输入引起的,但我不确定,如果不是问题,我不想尝试编辑图表。

我在 opencv 中附加了导致问题的函数:

const tensorflow::TensorProto& TFImporter::getConstBlob(const tensorflow::NodeDef &layer, std::map<String, int> const_layers,
                                              int input_blob_index, int* actual_inp_blob_idx) 
    if (input_blob_index == -1) 
        for(int i = 0; i < layer.input_size(); i++) 
            Pin input = parsePin(layer.input(i));
            if (const_layers.find(input.name) != const_layers.end()) 
                if (input_blob_index != -1)
                    CV_Error(Error::StsError, "More than one input is Const op");

                input_blob_index = i;
            
        
    

    if (input_blob_index == -1)
        CV_Error(Error::StsError, "Const input blob for weights not found");

    Pin kernel_inp = parsePin(layer.input(input_blob_index));
    if (const_layers.find(kernel_inp.name) == const_layers.end())
        CV_Error(Error::StsError, "Input [" + layer.input(input_blob_index) +
                                  "] for node [" + layer.name() + "] not found");
    if (kernel_inp.blobIndex != 0)
        CV_Error(Error::StsError, "Unsupported kernel input");

    if(actual_inp_blob_idx) 
        *actual_inp_blob_idx = input_blob_index;
    

    int nodeIdx = const_layers.at(kernel_inp.name);
    if (nodeIdx < netBin.node_size() && netBin.node(nodeIdx).name() == kernel_inp.name)
    
        return netBin.node(nodeIdx).attr().at("value").tensor();
    
    else
    
        CV_Assert_N(nodeIdx < netTxt.node_size(),
                    netTxt.node(nodeIdx).name() == kernel_inp.name);
        return netTxt.node(nodeIdx).attr().at("value").tensor();
    

【问题讨论】:

【参考方案1】:

正如您所指出的,错误源自getConstBlob (https://github.com/opencv/opencv/blob/master/modules/dnn/src/tensorflow/tf_importer.cpp#L570)。 getConstBlobpopulateNet (https://github.com/opencv/opencv/blob/master/modules/dnn/src/tensorflow/tf_importer.cpp#L706) 中被多次调用,在readNetFromTensor (https://github.com/opencv/opencv/blob/master/modules/dnn/src/tensorflow/tf_importer.cpp#L2278) 的所有重载定义中都会调用。如果您想使用调试器单步执行,这些可能是放置断点的起点。

我注意到的另一件事是我相信您正在使用的populateNet 的定义(提供std::string:https://docs.opencv.org/master/d6/d0f/group__dnn.html#gad820b280978d06773234ba6841e77e8d)需要两个参数——模型路径(model)和@ 987654333@config`),这是可选的,默认为空字符串。在单元测试中,似乎有两种情况 - 提供和不提供配置 (https://github.com/opencv/opencv/blob/master/modules/dnn/test/test_tf_importer.cpp)。我不确定这是否会产生影响。

最后,在您提供的用于复制结果的脚本中,我认为模型文件名拼写错误 - 它显示为 optimized_inferene_graph.pb,但您在 github 存储库中指向的文件拼写为 Optimize_inference_graph.pb.

只是一些建议,希望对你有帮助!

【讨论】:

以上是关于不止一个输入是 Const Op的主要内容,如果未能解决你的问题,请参考以下文章

如何举一个例子来反驳使用 `==` 来比较 `const char*`

程序员的3年之痒改变的不止薪水------转载

是否可以输入不止一种类型的提示?

c语言判断输入的是不是是数字(不止一位)

修改 std::string::op[] 的结果是不是合法?

static, readonly, const