本篇做一个没有实用价值的mnist rpc服务,重点记录我在调试整合tensorflow和opencv时遇到的问题;

准备模型

mnist的基础模型结构就使用tensorflow tutorial给的例子,卷积-池化-卷积-池化-全连接-dropout-softmax,然后走常规的优化训练,得到一个错误率2.0%的结果;

然后准备一个单张图片的输入,一个(1, 28, 28, 1)的tensor,输入到模型里,得到一个单条的输出,给它们定好名字;

将模型保存下来:

加载模型

用c++写一个thrift rpc server,在handler的实例化阶段加载模型,加载过程与上一篇一致:

bool
MNISTRecognizeServletHandler::Init() {
// init session
Status status = NewSession(SessionOptions(), &session_);
if (!status.ok()) {
LOG(ERROR) << status.ToString();
return false;
} else {
session_inited_ = true;
}
// load graph
graph_def_ = new GraphDef();
std::string model_path = FLAGS_model_path;
status = ReadBinaryProto(Env::Default(), model_path, graph_def_);
if (!status.ok()) {
LOG(ERROR) << status.ToString();
return false;
} else {
graph_loaded_ = true;
}
// prepare session
status = session_->Create(*graph_def_);
if (!status.ok()) {
LOG(ERROR) << status.ToString();
return false;
} else {
session_prepared_ = true;
}
}

识别图片

接下来就可以识别图片了,输入是一个图片内容,输出是识别结果,这里是我耗时最多的部分,主要原因是对opencv不熟悉;

载入图片

  std::vector<uint8> vectordata(image_content.begin(), image_content.end());
cv::Mat data_mat(vectordata, true);
cv::Mat raw_image(cv::imdecode(data_mat, CV_LOAD_IMAGE_COLOR));
//cv::Mat raw_image(cv::imdecode(data_mat, CV_LOAD_IMAGE_GRAYSCALE));

这里从string将图片数据存入Mat,然后对图片进行解码;

解码时加载彩色图,其实也可以直接加载灰度图,但是因为我计划将一些图片的预处理过程封装成一个函数,所以这里就不加载成灰度图了;

图片预处理

  cv::Mat prepared_image;
prepare_image(raw_image, prepared_image); void prepare_image(const Mat& img, Mat& prepared_img) {
cvtColor(img, prepared_img, CV_BGR2GRAY);
resize(prepared_img, prepared_img, Size(INPUT_WIDTH, INPUT_HEIGHT));
prepared_img = - prepared_img; }

预处理主要做了三件事,彩图转灰度图,转换大小,取反色;

这里的取反色浪费了我许多时间,一开始不知道要取反,直接丢进模型里,得到的识别结果非常差,总以为是从Mat往Tensor转换时出了问题,后来把tensorflow做模型训练时的python PIL输入数据和C++ opencv的Mat打印出来一比对,才发现灰度值反了;

Mat转Tensor

这里参考了tensorflow issue 8033的最佳答案,避免一次数据拷贝从而提升图像处理速度,我虽然不关心速度,但是也不想一行行的拷贝数据,所以就参考了这个方案;

  Tensor input_image(DT_FLOAT, TensorShape({, INPUT_WIDTH, INPUT_HEIGHT, }));
float *p = input_image.flat<float>().data();
cv::Mat input_mat(INPUT_WIDTH, INPUT_HEIGHT, CV_32FC1, p);
prepared_image.convertTo(input_mat, CV_32FC1);

丢入模型

把输入准备好,再把输出取出来

  std::vector<std::pair<string, tensorflow::Tensor>> inputs = {
{FLAGS_input_tensor_name, input_image},
};
std::vector<tensorflow::Tensor> outputs;
Status status = session_->Run(inputs, {FLAGS_output_tensor_name}, {}, &outputs);

这里的input_tensor_name和output_tensor_name分别对应第一步准备模型时定好的名字;

得到结果

这一步做的有点丑,因为不知道有没有现成的对标numpy.argmax的函数,于是遍历了一遍输出tensor的buffer;

  Tensor prediction_tensor = outputs[];
float *results = prediction_tensor.flat<float>().data();
int ret = -;
int max = ;
for (int i = ; i < prediction_tensor.NumElements(); i++) {
if (results[i] > max) {
max = results[i];
ret = i;
}
}

调用RPC

写一个python thrift client,读入图片内容,然后丢给rpc server

    thrift_client = ThriftClient(FLAGS.thrift_ip, FLAGS.thrift_port, MNISTRecognizeServlet)
fh = open(FLAGS.image_path)
img_buf = fh.read()
v = thrift_client.Recognize(img_buf)
print v

tensorflow学习笔记3:写一个mnist rpc服务的更多相关文章

  1. python 学习笔记 12 -- 写一个脚本获取城市天气信息

    近期在玩树莓派,前面写过一篇在树莓派上使用1602液晶显示屏,那么可以显示后最重要的就是显示什么的问题了. 最easy想到的就是显示时间啊,CPU利用率啊.IP地址之类的.那么我认为呢,假设可以显示当 ...

  2. TensorFlow学习笔记(三)MNIST数字识别问题

    一.MNSIT数据处理 MNSIT是一个非常有名的手写体数字识别数据集.包含60000张训练图片,10000张测试图片.每张图片是28X28的数字. TonserFlow提供了一个类来处理 MNSIT ...

  3. DuiLib学习笔记2——写一个简单的程序

    我们要独立出来自己创建一个项目,在我们自己的项目上加皮肤这才是初衷.我的新建项目名为:duilibTest 在duilib根目录下面有个 Duilib入门文档.doc 我们就按这个教程开始入门 首先新 ...

  4. TensorFlow学习笔记(二)-- MNIST机器学习入门程序学习

    此程序被称为TF的 Hello World,19行代码,给人感觉很简单.第一遍看的时候,不到半个小时,就把程序看完了.感觉有点囫囵吞枣的意思,没理解透彻.现在回过头来看,感觉还可以从中学到更多东西. ...

  5. 《python灰帽子》学习笔记:写一个windos 调试器(一)

    一.开发内容介绍 为了对一个进程进行调试,你首先必须用一些方法把调试器和进程连接起来.所以, 我们的调试器要不然就是装载一个可执行程序然后运行它, 要不然就是动态的附加到一个运行的进程.Windows ...

  6. DuiLib学习笔记2.写一个简单的程序

    我们要独立出来自己创建一个项目,在我们自己的项目上加皮肤这才是初衷.我的新建项目名为:duilibTest 在duilib根目录下面有个 Duilib入门文档.doc 我们就按这个教程开始入门 首先新 ...

  7. 深度学习-tensorflow学习笔记(1)-MNIST手写字体识别预备知识

    深度学习-tensorflow学习笔记(1)-MNIST手写字体识别预备知识 在tf第一个例子的时候需要很多预备知识. tf基本知识 香农熵 交叉熵代价函数cross-entropy 卷积神经网络 s ...

  8. 深度学习-tensorflow学习笔记(2)-MNIST手写字体识别

    深度学习-tensorflow学习笔记(2)-MNIST手写字体识别超级详细版 这是tf入门的第一个例子.minst应该是内置的数据集. 前置知识在学习笔记(1)里面讲过了 这里直接上代码 # -*- ...

  9. tensorflow学习笔记——使用TensorFlow操作MNIST数据(2)

    tensorflow学习笔记——使用TensorFlow操作MNIST数据(1) 一:神经网络知识点整理 1.1,多层:使用多层权重,例如多层全连接方式 以下定义了三个隐藏层的全连接方式的神经网络样例 ...

随机推荐

  1. 使用javascript和css模拟帧动画的几种方法浅析

    我们平时在开发前端页面的时候,经常会播放一段帧序列.这段帧序列就像gif图片那样,反复循环播放.那大家可能会说,直接用gif图片就好了,干嘛还去模拟呢?那是因为要做得更加灵活,我们要做到以下几点: 1 ...

  2. requirejs的使用和快速理解

    样例来自https://www.jianshu.com/p/b8a6824c8e07 requirejs有以下功能 声明不同js文件之间的依赖 可以按需.并行.延时载入js库 可以让我们的代码以模块化 ...

  3. Solve Error: MissingSchemaError: Schema hasn't been registered for model "YourModel".

    使用MongoDB的时候,如果遇到下面这个错误: /home/ec2-user/YourProject/node_modules/mongoose/lib/index.js: throw new mo ...

  4. JS-预解析(提升)与代码执行过程

    1,预解析的过程. 2,代码的执行过程. 预解析:程序在执行过程,会先将代码读取到内存中检查,会将所有的声明在此处进行标记,所谓的标记就是让js解析器知道这个名字,后面在使用这个名字的时候,不会出现未 ...

  5. 客户端无法加入域,报错:“无法与域‘xxx.com’的Active Directory域控制器(AD DC)链接” 请确保键入的域名正确

    1.客户端能不能解析到域名? nslookup 一下域名看看解析到的IP的地址 2.客户端的DNS要指向DC 3.客户端的相关服务,workstation,TCP/IP NetBios Helper, ...

  6. 跨界!Omi 发布多端统一框架 Omip 打通小程序与 Web 腾讯开源 2月28日

    https://mp.weixin.qq.com/s/z5qm-2bHk_BCJAwaodrMIg 跨界!Omi 发布多端统一框架 Omip 打通小程序与 Web 腾讯开源 2月28日

  7. Pycharm汉化

    简单的汉化方法:    需要把以下链接的文件放到Pycharm安装目录的lib目录下记得重启pycharm即可https://pan.baidu.com/s/1GG4zXZ_0xSB-AlDdu0Tu ...

  8. mysql查询两个日期之前相隔的天数

    select timestampdiff(SECOND,'2011-09-25 23:23:13','2011-09-26 22:23:11'); 其中SECOND同样可以改为HOUR,MINUTE

  9. 搭建docker私有仓库

    保存镜像的地方成为仓库(registry).目前有2种仓库:公共仓库和私有仓库. 最方便的是使用公共仓库上传和下载镜像,下载不需要注册,上传需要到公共仓库注册.公共仓库网站:https://hub.d ...

  10. linux架构师之路!

    目录 1.shell编程总结 2.python编程总结 3.网络基础总结 4.存储的基本知识 5.linux常用 架构学习目录 1.网站架构 2.架构师技术图谱 3.python之路 4.IBM技术主 ...