老师周末布置的作业,现在记录一下,方便以后学习。也为了帮助其他在学习遇到困难的小伙伴们。
接下来我们 以最简单的 神经网络手写体识别为例。
一、简单的流程图:
- 图片尺寸为 20*20
- 类别为 10分类
- 模型Tensorflow
- C++ Opencv实现推理
二、name添加
----大致模型结构(只截取了一部分)
self.X = tf.placeholder(tf.float32, [None, 400],name='inputx')#这里做了添加
self.Y = tf.placeholder(tf.float32, [None, 10])
# 隐藏层 1
with tf.variable_scope('layer1') as scope:
W1 = tf.Variable(tf.random_normal([400, hidden_one]))
b1 = tf.Variable(tf.random_normal([hidden_one]))
a1 = tf.sigmoid(tf.matmul(self.X, W1) + b1)
# 隐藏层 2
with tf.variable_scope('layer2') as scope:
W2 = tf.Variable(tf.random_normal([hidden_one, hidden_two]))
b2 = tf.Variable(tf.random_normal([hidden_two]))
a2 = tf.sigmoid(tf.matmul(a1, W2) + b2)
# 隐藏层 3
with tf.variable_scope('layer3') as scope:
W3 = tf.Variable(tf.random_normal([hidden_two, hidden_three]))
b3 = tf.Variable(tf.random_normal([hidden_three]))
a3 = tf.sigmoid(tf.matmul(a2, W3) + b3)
# 全连接
with tf.variable_scope('all_layer') as scope:
W4 = tf.Variable(tf.random_normal([hidden_three, 10]))
b4 = tf.Variable(tf.random_normal([10]))
#预测
self.logist = tf.sigmoid(tf.matmul(a3, W4) + b4,name='final_result') #这里做了添加
#代价
self.loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=self.logist,labels=self.Y))
三、生成pb
1、 导入包
from tensorflow.python.framework import graph_util
2、训练效果好时进行保存
#放入训练过程中 准确度大于一定阈值进行保存
constant_graph = graph_util.convert_variables_to_constants(sess, sess.graph_def,['final_result']) #[这里只放最后的预测h的name就好]
with tf.gfile.FastGFile('model.pb', mode='wb') as f:
f.write(constant_graph.SerializeToString())
四、Opencv DNN推理
新建一个类别文件 例如words.txt
完整代码
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include<String>
#include <fstream>
using namespace cv;
using namespace cv::dnn;
using namespace std;
String labels_txt_file = "words.txt";//类别文件
vector<String> readLabels() { //读取words.txt 文件
vector<String> classNames; // 创建一个名为classNames的容器
ifstream fp(labels_txt_file); //读取文件 words.txt
String name;
while (!fp.eof()) { //判断文件是否读到末尾 是则停止循环
getline(fp, name); //读取每行 将对应的值放入name中
if (name.length()) {
classNames.push_back(name);//添加到容器中
}
}
fp.close();
return classNames;
}
int main(int argc, char** argv) {
//1、读取一张图片
Mat src = imread("test.jpg", 0);
//2、加载模型
vector<String> labels = readLabels(); //打印类别信息
for (int i = 0; i < labels.size(); i++)
{
cout << labels[i] << endl;
}
//3、加载网络结构
Net net = readNetFromTensorflow("model.pb");
//4、 将图像数据转换成OpenCV DNN能用的blob形式 blobFromImage
Mat inputBlob = blobFromImage(src, 1.0, Size(20,20)); //blobFromImage 参数(图片,缩放比例,缩放尺寸) 我的图片尺寸为20*20
//5、将blob数据放入网络结构中 对应的 placeholder X中的占位符的name;
Mat prob;
net.setInput(inputBlob, "inputx");// 输入层 X
//6、前向传播
prob = net.forward("final_result");//输出层 h
cout << prob << endl;
Point Max_index;
double classProb;//最大概率
minMaxLoc(prob, NULL, &classProb, NULL, &Max_index);// 在一个数组中找到全局最小值和全局最大值 minMaxLoc 参数(图片数据,最小值,最大值,最小点的位置,最大点的位置)
int classidx = Max_index.x;//概率最大的下标
printf("\n 图片预测为: %s, 概率为 : %.2f", labels.at(classidx).c_str(), classProb);
imshow("预测图片", src);
waitKey(0);
return 0;
}
五、测试
运行 ~~~
成功搞定。