个人博客原文:http://www.bearoom.xyz/2019/08/25/ubuntu-tensorflow-cc-example/

之前记录的运行Tensorflow的C++接口的例子都是零散的,现在写一个完整的例子。

一、模型文件转换

首先是需要有训练好的模型文件,然后将其转化为tensorflow的C++接口能够读取的.pb文件,这个前面也有记录,现在贴下完整的代码:

###################################################
#
# Script to
# - Loading a pre-trained model(.h5)
# - Generate a .pb model file from .h5
#
################################################## #Python
import numpy as np
import configparser
import time
from matplotlib import pyplot as plt
#Keras
from keras.models import model_from_json
from keras.models import Model
#scikit learn
from sklearn.metrics import roc_curve
from sklearn.metrics import roc_auc_score
from sklearn.metrics import confusion_matrix
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import jaccard_similarity_score
from sklearn.metrics import f1_score
import sys from keras.models import load_model
import tensorflow as tf
from keras import backend as K
from tensorflow.python.framework import graph_io
from tensorflow.python.framework.graph_util import convert_variables_to_constants def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
graph = session.graph
with graph.as_default():
freeze_var_names = list(set(v.op.name for v in tf.global_variables()).difference(keep_var_names or []))
output_names = output_names or []
output_names += [v.op.name for v in tf.global_variables()]
input_graph_def = graph.as_graph_def()
if clear_devices:
for node in input_graph_def.node:
node.device = ""
frozen_graph = convert_variables_to_constants(session, input_graph_def, output_names, freeze_var_names)
return frozen_graph model = model_from_json(open('CDNet_v4_architecture.json').read())
model.load_weights('CDNet_v4_best_weights.h5') model.summary() print('input is :', model.input.name)
print ('output is:', model.output.name) """------------------------保存为.pb格式------------------------"""
sess = K.get_session()
frozen_graph = freeze_session(K.get_session(), output_names=[model.output.op.name])
graph_io.write_graph(frozen_graph, './', 'CDNet_v4_best_weights.pb', as_text=False)

然后会输出模型的每层信息,以及输入输出信息:

二、CMakeLists.txt文件

CMakeLists.txt文件里面会添加opencv和tensorflow的路径:

#设置cmake的最小版本
cmake_minimum_required(VERSION 3.0)
#项目名称
project(demo)
#设置c++编译器
set(CMAKE_CXX_STANDARD 11)
#设置TENSORFLOW_DIR变量,变量内容为安装的tensorflow文件夹路径
set(TENSORFLOW_DIR /home/zcx/tensorflow-r1.12)
#项目中的include路径
include_directories(${TENSORFLOW_DIR})
include_directories(${TENSORFLOW_DIR}/tensorflow/contrib/makefile/downloads/absl)
include_directories(${TENSORFLOW_DIR}/bazel-genfiles)
include_directories(${TENSORFLOW_DIR}/tensorflow/contrib/makefile/downloads/eigen) # opencv
include_directories(/usr/local/opencv347/include /usr/local/opencv347/include/opencv /usr/local/opencv347/include/opencv2) #项目中lib路径
link_directories(${TENSORFLOW_DIR}/tensorflow/contrib/makefile/gen/lib)
link_directories(${TENSORFLOW_DIR}/bazel-bin/tensorflow) link_directories(/usr/local/opencv347/lib) add_executable(demo main.cpp)
#连接libtensorflow_cc.so和libtensorflow_framework库。
target_link_libraries(demo tensorflow_cc tensorflow_framework opencv_core opencv_highgui opencv_imgproc opencv_imgcodecs)

三、C++文件:

因为我这个模型是进行视网膜血管图像分割,最终的输出层是一个2维tensor,第一维图像长宽的乘积,即数据大小,第二维是通道数,因为有背景和血管两个类,所以分了两个通道。最后得到输出张量的时候也要通过赋值或者变形等操作将数据转为图像数据来显示。

#include <tensorflow/core/platform/env.h>
#include <tensorflow/core/public/session.h> #include <iostream> #include <opencv.hpp> using namespace std;
using namespace tensorflow; void CVMat_to_Tensor(cv::Mat &img, Tensor* output_tensor, int input_rows,int input_cols)
{
//imshow("input image",img);
//图像进行resize处理
cv::resize(img,img,cv::Size(input_cols,input_rows));
//imshow("resized image",img); //归一化
img.convertTo(img,CV_32FC1);
img=img/255; float *p = output_tensor->flat<float>().data(); cv::Mat tempMat(input_rows, input_cols, CV_32FC1, p);
img.convertTo(tempMat,CV_32FC1); } int main()
{
Session* session;
Status status = NewSession(SessionOptions(), &session);
if (!status.ok())
{
cout << status.ToString() << "\n";
return -1;
}
cout << "Session successfully created.\n"; string model_path = "./CDNet_v4_best_weights.pb"; GraphDef graphdef;
Status status_load = ReadBinaryProto(Env::Default(), model_path, &graphdef);
if (!status_load.ok())
{
cout << status_load.ToString() << "\n";
return -1;
}
Status status_create = session->Create(graphdef);
if (!status_create.ok())
{
cout << status_create.ToString() << "\n";
return -1;
} //输出每一曾的名字
for (int i=0; i < graphdef.node_size(); i++)
{
std::string name = graphdef.node(i).name();
std::cout << name << std::endl;
} cv::Mat src = cv::imread("21_training.tif", 0);
Tensor src_tensor = Tensor(DT_FLOAT, TensorShape({ 1, 1, 544, 544}));
CVMat_to_Tensor(src, &src_tensor, 544, 544); string input_tensor_name="input_1:0";
string output_tensor_name="activation_1/truediv:0";
vector<tensorflow::Tensor> outputs;
string output_node = output_tensor_name; Status status_run = session->Run({{input_tensor_name, src_tensor}}, {output_node}, {}, &outputs);
if (!status_run.ok())
{
cout << status_run.ToString() << "\n";
return -1;
} std::cout << outputs[0].shape().dim_size(1) << std::endl;
std::cout << outputs[0].shape().dim_size(2) << std::endl; float *pDstTensor = outputs[0].flat<float>().data();
cv::Mat tmp = cv::Mat(544, 544, CV_32FC2, pDstTensor);
cv::Mat tmp1 = cv::Mat(cv::Size(544, 544), CV_32FC1);
cv::Mat dst0 = cv::Mat(cv::Size(544, 544), CV_8UC1);
cv::Mat dst1 = cv::Mat(cv::Size(544, 544), CV_8UC1); for (int i = 0; i < 544; i++)
{
float *ptrTmp = tmp.ptr<float>(i);
float *ptrTmp1 = tmp1.ptr<float>(i);
for (int j = 0; j < 544; j++)
{
*(ptrTmp1 + j) = *(ptrTmp + j*2)*255;
}
} tmp1.convertTo(dst0, CV_8UC1);
cv::imwrite("dst0.jpg", dst0); for (int i = 0; i < 544; i++)
{
float *ptrTmp = tmp.ptr<float>(i);
float *ptrTmp1 = tmp1.ptr<float>(i);
for (int j = 0; j < 544; j++)
{
*(ptrTmp1 + j) = *(ptrTmp + j*2 + 1)*255;
}
} tmp1.convertTo(dst1, CV_8UC1);
cv::imwrite("dst1.jpg", dst1); return 0;
}

输入图像:

输出图像我可视化了背景和血管两个通道,转为图像来显示,当然每个像素是乘以255转出来的,毕竟输出的是概率,在0-1之间:

背景(白的背景,黑的为血管):

血管(白的为血管,黑的为背景):

完结,撒花...

风鬟雨鬓,偏是来无准。

倦倚玉兰看月晕,容易语低香近。

软风吹遍窗纱,心期便隔天涯。

从此伤春伤别,黄昏只对梨花。

-- 纳兰性德 《清平乐·风鬟雨鬓》

Ubuntu上运行tensorflow C++的完整例子的更多相关文章

  1. 在 Ubuntu 上安装 TensorFlow (官方文档的翻译)

    本指南介绍了如何在 Ubuntu 上安装 TensorFlow.这些指令也可能对其他 Linux 变体起作用, 但是我们只在Ubuntu 14.04 或更高版本上测试了(我们只支持)  这些指令. 一 ...

  2. .netcore跨平台 之 windows上编译,ubuntu上运行

    1 下载并安装netcore sdk    下载地址 https://github.com/dotnet/cli 选取合适的版本下载安装即可 打开 CMD ,输入dotnet,出现以下信息说明已安装好 ...

  3. [转]linux(ubuntu)上运行网易popo

    popo没有linux版,连web版和android版都没有,这个实在是不方便.搞了很久,终于搞定了ubuntu上运行popo,暂时还没出现什么问题. 首先要安装PlayOnLinux,直接安装win ...

  4. 在 ubuntu 上运行 php 脚本

    在 ubuntu 上运行 php 脚本 一.配置运行环境 1.要在 ubuntu 上运行 php 脚本,需要安装 Apache2 和 PHP 具体步骤,请参考:Ubuntu 搭建Web服务器(MySQ ...

  5. Ubuntu上运行Blender,在控制台上查看运行结果

    1.首先在控制台打开Blender. 具体操作:找到Blender的安装路径,我的是:/home/lcx/下载/blender-2.78c-linux-glibc219-x86_64 $cd /hom ...

  6. 在64位ubuntu上安装tensorflow

    首先从ubuntu14.04的安装讲起 1.下载ubuntu14.04 64位的系统,下载地址如下: http://www.ubuntu.com/download/desktop 2.下载好64位的u ...

  7. 怎么在ubuntu上运行php代码?

    1. 首先,你需要安装Apache2. sudo apt-get update sudo apt-get install apache2 当安装完以后,Apache就已经开始运行啦,你可以进行测试,通 ...

  8. ubuntu 上运行的django 出现No space left on device错误

    运行django出现错误信息: [2016-02-16 14:33:24,476 pyinotify ERROR] add_watch: cannot watch /usr/local/lib/pyt ...

  9. 在CPU上运行Tensorflow

    如果你是用的GPU版本的Tensorflow,你可以这样来使用CPU版本的Tensorlfow: config = tf.ConfigProto( device_count = {'GPU': 0} ...

随机推荐

  1. 学习进度05(billbill长评爬取02)

    今天下雪了,是个看<白色相簿2>的好日子. 昨天我们获取所有长评url,今天要解析这些url获取更多的信息随便,点开一个,我们需要的数据有标题,时间,内容.点赞数和评论先不弄了. 解析js ...

  2. 适配器之SimpleAdapter

    前言: 在写适配器时,SimpleAdapter会经常使用到,虽然他比ArrayAdapter复杂,但是也提供了更多的功能 正文: 我们接下来先从SimpleAdapter中较为简单的显示两行文本开始 ...

  3. 【Linux】linux内核学习

    linux内核获取 官网: https://www.kernel.org/ Linux操作系统的核心是模块化,可以使用lsmod命令查看内核模块,下面展示已载入系统的模块: [root@172.16. ...

  4. Ajax学习系列——jQuery中Ajax的请求方式

    在jQuery中,Ajax常见的请求方式主要有4种. 1.$.ajax()返回其创建的XMLHttpRequest对象. $.ajax({ type:"POST", content ...

  5. 二十五、SAP中输出一条横线

    一.我们代码如下,这个是不输出横线的时候 效果如下 二.输出横线的代码如下 效果如下,多出一条横线

  6. 苏州大学ICPC集训队新生赛第二场

    A - Score UVA - 1585 水 #include<bits/stdc++.h> using namespace std; int main(){ int n; cin> ...

  7. 洛谷 P5146 最大差值

    题目传送门 好水的题... AC代码: #include<iostream> #include<cstdio> using namespace std; ,a,ans = -; ...

  8. Arduino - -- 串口双向通信

    需要用到Arduino UNO的串口双向通信功能,以下源码: int val; void setup() {   Serial.begin(9600); // opensserial port, se ...

  9. C++基础--随机数

    C/C++要产生随机数的方法一般是采用rand()函数核srand()函数来实现的. rand()函数返回的是一个伪随机数,这个函数内部采用线性同余法来实现伪随机数,而这个伪随机数是在一定范围内可以看 ...

  10. EL&JSTL简单介绍

    EL表达式 是为了简化咱们的jsp代码,具体一点就是为了简化在jsp里面写的那些java代码. 写法格式 ${表达式 } 如果从作用域中取值,会先从小的作用域开始取,如果没有,就往下一个作用域取. 一 ...