1. 程式人生 > >opencv DNN模組 +tensorflow

opencv DNN模組 +tensorflow

使用的版本是tensorflow0.12.0 + python3.6,搭建一個簡單的模型,用來訓練得到pb檔案。

opencv3.4.1 + VS2015,用來載入使用pb檔案。

訓練PD檔案。

建立專案,新建save_pb.py。

在該網路中,設定輸入結點的名字為:conv1/input,輸出結點的名字為:conv1/y,(輸入輸出結點的名稱必須設定)建立網路結構:x*w1*w2=y,w1,w2均為隨機數,其中X的尺寸:[1,2],w1:[2,3],w2:[3,1],輸出的結點y:[1]。

儲存該網路,即儲存網路結構,與變數值,即w1和w2兩個隨機數也儲存下來程式碼如下:

import tensorflow as tf
from tensorflow.python.framework import graph_util
 
 
def save_pb(sess):
    constant_graph = graph_util.convert_variables_to_constants(sess, sess.graph_def, ['conv1/y'])
    with tf.gfile.FastGFile("D://python//hand//graph.pb", mode='wb') as f:
        f.write(constant_graph.SerializeToString())
 
 
def main():
    with tf.variable_scope('conv1'):
        w1 = tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1))
        w2 = tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1))
        x = tf.placeholder(tf.float32, shape=(1, 2), name='input')
        a = tf.matmul(x, w1)
        y = tf.matmul(a, w2, name="y")
 
    with tf.Session() as sess:
        tf.initialize_all_variables().run()
        print(sess.run(y, feed_dict={x:[[7, 9]]}))
        save_pb(sess)
 
main()

 

PB檔案測試

接下來可以在python中測試一下PB檔案是否正確。

從檔案中取出.pb檔案,獲取其輸入結點conv1/input,輸出結點conv1/y,將引數傳入,並得到輸出結果。

import tensorflow as tf
from tensorflow.python.platform import gfile
 
 
def main():
    with tf.Session() as sess:
        with gfile.FastGFile("D://python//hand//graph.pb", 'rb') as f:
            graph_def = tf.GraphDef()
            graph_def.ParseFromString(f.read())
            sess.graph.as_default()
            tf.import_graph_def(graph_def, name='')
            
        sess.run(tf.global_variables_initializer())
        input_x = sess.graph.get_tensor_by_name('conv1/input:0')
 
        op = sess.graph.get_tensor_by_name('conv1/y:0')
        print(sess.run(op, feed_dict={input_x:[[7, 9]]}))
 
main()

C ++呼叫:

在C ++中呼叫時需要使用到DNN。

使用readNetFromTensorflow得到PD中​​儲存的網路模型,在OpenCV中的中的輸入輸出都為墊型別,所以輸入的墊需要定義為大小與輸入張量相等的[2,1],對輸入墊進行賦值後使用blobFromImage對墊進行處理,執行平均減法來對輸入影象進行歸一化,從而產生一個已知的斑點形狀。

setInput設定函式為傳遞引數到輸入結點 conv1/input.forword為得到輸出結點的值,值的形式為墊型。

#include<opencv2\opencv.hpp>
#include<opencv2\dnn.hpp>
#include<stdlib.h>
#include<iostream>
#include<string.h>
 
using namespace cv;
using namespace std;
using namespace dnn;
 
int main() {
    String weights = "D://python//hand//graph.pb";
    Net net = readNetFromTensorflow(weights);
    Mat input(Size(2, 1), CV_8UC1);
    input.at<uchar>(0, 0) = 7;
    input.at<uchar>(0, 1) = 9;
    input = blobFromImage(input, 1.0, Size(2, 1), Scalar(), false, false);
    net.setInput(input, "conv1/input");
    Mat pred = net.forward("conv1/y");
    cout << pred << endl;
    system("pause");
    return 0;
}