opencv3.3之后推出了DNN的神经网络接口,这样的OpenCV的中就可以调用tensorflow训练得到的网络了。
我这里使用的版本是tensorflow1.4.0 + python3.5,搭建一个简单的模型,用来训练得到pb文件。
opencv3.4.0 + 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_utildef 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文件:
-
PB文件测试
接下来可以在python中测试一下PB文件是否正确。
从文件中取出.pb文件,获取其输入结点conv1/input,输出结点conv1/y,将参数传入,并得到输出结果。
import tensorflow as tf
from tensorflow.python.platform import gfiledef 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()
运行结果:
与保存时的运行结果一致,所以pb文件保存正确。
-
C ++调用:
在C ++中调用时需要使用到DNN。
使用readNetFromTensorflow得到PD中??保存的网络模型,在OpenCV中的中的输入输出都为mat类型,所以输入的 mat 需要定义为大小与输入张量相等的[2,1],对输入mat 进行赋值后使用blobFromImage对mat进行处理,执行平均减法来对输入图像进行归一化,从而产生一个已知的斑点形状。得到可以作为网络模型输入的数据。
setInput设置函数为传递参数到输入结点 conv1/input.forword为得到输出结点的值,值的形式为mat型。
#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;
}
运行结果:
输出的结果一致。