首页 文章

如何使用opencv dnn模型加载预训练的张量流模型

提问于
浏览
0

readNetFromTensorflow函数无法加载tensorflow预训练模型(.pb) .

第1步:训练张量流的模型 . 线性回归码的张量流模型如下:

#!/usr/bin/python
import tensorflow as tf
import numpy as np
x_ = tf.placeholder(np.float32, [None, 1], 'input')
y_ = tf.placeholder(np.float32, [None, 1], 'label')
#layer1
w1 = tf.Variable(tf.random_normal([1,3]))
b1 = tf.Variable(tf.random_normal([3]) )
a1 = tf.add(b1,tf.matmul(x_,w1)) 
#layer2
w2 = tf.Variable(tf.random_normal([3,1]))
b2 = tf.Variable(tf.random_normal([1]) )
a2 = tf.add(b2,tf.matmul(a1,w2),name="output") 
#global steps
steps = 5000 
x = []
y = []
for i in range(1,200,5):
    temp = (1.0 * i)/10
    x.append([temp])
    y.append([3. + 2. * temp])
x = np.array(x)
y = np.array(y)
#loss function
loss =  tf.reduce_mean(tf.reduce_sum(tf.square(a2-y_)))
#optimizer
optimizer = tf.train.GradientDescentOptimizer(0.00001).minimize(loss)
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    length = len(x)
    #training...
    for i in range(steps):
        sess.run(optimizer,feed_dict={x_:x,y_:y})
        result = sess.run(loss,feed_dict={x_:x,y_:y})
        if i % 50 == 0:
            print("loss: ",result,"\tstep: ",i)
    saver = tf.train.Saver()
    saver.save(sess,"./model/model.ckpt")
    tf.train.write_graph(sess.graph.as_graph_def(), "./model/", "graph.pbtxt")
    print("predict...")
    pre = sess.run(a2,feed_dict={x_:[[0]]})
    print("x = 2 pre: ",pre)

步骤2:将模型保存为张量流的.pb文件 . 怎么做?

步骤3:使用带有C的opencv3.4.1函数readNetFromTensorflow加载.pb文件 . 这样的代码:

#include <fstream>
#include <sstream>
#include <iostream>
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
using namespace dnn;

std::vector<std::string> classes;

int main(int argc,char**argv)
{
    if(argc != 2)
    {
        cout<<"Usage: ./main [tensorflow modle path(.pb)]"<<endl;
        return -1;
    }
    String model = argv[1];
    Net net = cv::dnn::readNetFromTensorflow(model,argv[2]);
    cout<<"load Net OK!!"<<endl;

    float inp[1*1] = {2};
    Mat Matrix(1,1,CV_32FC1,inp);
    cout<<"Matrix:\n"<<Matrix<<endl;
    net.setInput(Matrix);

    Mat output = net.forward();
    cout<<"output: " << output <<endl;
    return 0;
}

结果应该是7.有两个问题 . 首先是如何生成训练模型的完整.pb文件,另一个是如何在opencv3.4.1 dnn中使用预先训练的模型与C?

1 回答

  • 0

    我发现这个程序发生了什么 . 问题出现在步骤2中 . 必须使用tensorflow函数convert_variables_to_constants将默认图形转换为新图形 . 然后使用tf.train.write_graph可以完全保存旧的预训练模型 . 最后只需修改步骤2中的代码,即可成功加载预训练模型 . 第2步的新代码如下:

    #!/usr/bin/python
    import tensorflow as tf
    import numpy as np
    x_ = tf.placeholder(np.float32, [None, 1], 'input')
    y_ = tf.placeholder(np.float32, [None, 1], 'label')
    #layer1 
    a1 = tf.layers.dense(input=x_,units=3,name="layer1") 
    #layer2
    a2 = tf.layers.dense(input=x_,units=1,name="layer2")
    #global steps
    steps = 5000 
    x = []
    y = []
    for i in range(1,200,5):
        temp = (1.0 * i)/10
        x.append([temp])
        y.append([3. + 2. * temp])
    x = np.array(x)
    y = np.array(y)
    #loss function
    loss =  tf.reduce_mean(tf.reduce_sum(tf.square(a2-y_)))
    #optimizer
    optimizer = tf.train.GradientDescentOptimizer(0.00001).minimize(loss)
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        length = len(x)
        #training...
        for i in range(steps):
            sess.run(optimizer,feed_dict={x_:x,y_:y})
            result = sess.run(loss,feed_dict={x_:x,y_:y})
            if i % 50 == 0:
                print("loss: ",result,"\tstep: ",i)
         #save the .pbtxt file of the pre-trained model.
         tf.train.write_graph(sess.graph.as_graph_def(), "./model/", 
         #transfrom default graph  and save as a new graph.
         # the param 'output_node_names' should be the last op's name in the pre-trained model. In this model, last op's name is "layer2/BiasAdd" that found in the .pbtxt file like this:
         #node{
         #     name: "layer2/BiasAdd"
         #     op:   "BiasAdd"
         # .....
         output_graph_def = tf.graph_util.convert_variables_to_constants(sess,sess.graph_def,output_node_names=['layer2/BiasAdd'])
         tf.train.write_graph(output_graph_def, "./model/", "graph.pbtxt",as_txt = False)
         print("predict...")
         pre = sess.run(a2,feed_dict={x_:[[0]]})
         print("x = 2 pre: ",pre)
    

    C代码与上述内容几乎相同:

    #include <fstream>
    #include <sstream>
    #include <iostream>
    #include <opencv2/dnn.hpp>
    #include <opencv2/imgproc.hpp>
    #include <opencv2/highgui.hpp>
    using namespace std;
    using namespace cv;
    using namespace dnn;
    
    std::vector<std::string> classes;
    
    int main(int argc,char**argv)
    {
        if(argc != 2)
        {
            cout<<"Usage: ./main [tensorflow modle path(.pb)]"<<endl;
            return -1;
        }
        String model = argv[1];
        Net net = cv::dnn::readNetFromTensorflow(model,argv[2]);
        if(net.empty())
        {
            cout<<"load Net failed"<<endl;
            return -1;
        }
        cout<<"load Net OK!!"<<endl;
        float inp[1*1] = {0};
        Mat Matrix(1,1,CV_32FC1,inp);
        cout<<"Matrix:\n"<<Matrix<<endl;
        net.setInput(Matrix);
    
        Mat output = net.forward();
        #the value of the output should be equal to the output of the Step 1.
        cout<<"output: " << output <<endl;
        return 0;
    }
    

    另外,当我使用w1,b1和w2,b2而不是tf.layers.dense构建网络时,出现了一个我现在不理解的错误:

    Error: Unspecified error (More than one input is Const op) in getConstBlob, file /home/wy/Downloads/opencv 3.4.1/modules/dnn/src/tensorflow/tf_importer.cpp, line 571
    

    例外:OpenCV(3.4.1)/home/wy/Downloads/opencv-3.4.1/modules/dnn/src/tensorflow/tf_importer.cpp:571:错误:( - 2)多个输入是函数中的Const op getConstBlob

相关问题