Ubuntu上运行tensorflow C++的完整例子
个人博客原文: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++的完整例子的更多相关文章
- 在 Ubuntu 上安装 TensorFlow (官方文档的翻译)
本指南介绍了如何在 Ubuntu 上安装 TensorFlow.这些指令也可能对其他 Linux 变体起作用, 但是我们只在Ubuntu 14.04 或更高版本上测试了(我们只支持) 这些指令. 一 ...
- .netcore跨平台 之 windows上编译,ubuntu上运行
1 下载并安装netcore sdk 下载地址 https://github.com/dotnet/cli 选取合适的版本下载安装即可 打开 CMD ,输入dotnet,出现以下信息说明已安装好 ...
- [转]linux(ubuntu)上运行网易popo
popo没有linux版,连web版和android版都没有,这个实在是不方便.搞了很久,终于搞定了ubuntu上运行popo,暂时还没出现什么问题. 首先要安装PlayOnLinux,直接安装win ...
- 在 ubuntu 上运行 php 脚本
在 ubuntu 上运行 php 脚本 一.配置运行环境 1.要在 ubuntu 上运行 php 脚本,需要安装 Apache2 和 PHP 具体步骤,请参考:Ubuntu 搭建Web服务器(MySQ ...
- Ubuntu上运行Blender,在控制台上查看运行结果
1.首先在控制台打开Blender. 具体操作:找到Blender的安装路径,我的是:/home/lcx/下载/blender-2.78c-linux-glibc219-x86_64 $cd /hom ...
- 在64位ubuntu上安装tensorflow
首先从ubuntu14.04的安装讲起 1.下载ubuntu14.04 64位的系统,下载地址如下: http://www.ubuntu.com/download/desktop 2.下载好64位的u ...
- 怎么在ubuntu上运行php代码?
1. 首先,你需要安装Apache2. sudo apt-get update sudo apt-get install apache2 当安装完以后,Apache就已经开始运行啦,你可以进行测试,通 ...
- 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 ...
- 在CPU上运行Tensorflow
如果你是用的GPU版本的Tensorflow,你可以这样来使用CPU版本的Tensorlfow: config = tf.ConfigProto( device_count = {'GPU': 0} ...
随机推荐
- 51nod 1515:明辨是非 并查集合并
1515 明辨是非 题目来源: 原创 基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 收藏 关注 给n组操作,每组操作形式为x y p. 当p为1时,如果第x ...
- 被疯狂吐槽的iPhoneXR屏幕真如传言中的那么差吗?
在双十一期间,最受果粉关注的电商平台不是天猫,也不是京东,而是拼多多!原因很简单,拼多多疯狂给出iPhone的各种超低价格,直接压制了竞争对手.以iPhone XR为例,依据容量不同,价格分别为558 ...
- 自动填充IP地址
在windows下的DOS窗口中 要利用Netsh命令,进入到DOS下的网络配置状态,就能实现各种网络配置. 进入IP设置模式 在DOS环境中,设置网络参数之前,必须先进入IP设置模式才可以.先打开系 ...
- matlab和fortran混合编程
matlab2016b+vs2010+ivf2013+f90 其实默认是f77语法,但通过配置可以改变为自由格式. 默认只能f77代码,怎样修改: https://ww2.mathworks.cn/m ...
- 一百零四、SAP中ALV事件之十六,让ALV表格能点击修改
一.上一篇我们写到生产的ALV表格,但是表格内容不支持修改,如果我们需要修改下图的数量,需要怎么操作呢 二.代码如下,设置 ls_fieldcat-edit = 'X'. "允许编辑. ...
- 八十九、SAP中ALV事件之三,查看事件自带说明
一.双击REUSE_ALV_GRID_DISPLAY,来到SE37的这个函数模块中,查看IT_EVENT的相关说明,点击后面的显示按钮 二.翻译第一句 三.翻译第二句 四.翻译第三句 五.翻译第四句 ...
- Codeforces Round #585 (Div. 2) CF1215A~C
CF1215A. Yellow Cards简单的模拟,给定了黄票张数,判断最少和最多有多少人被罚下场. #include <bits/stdc++.h> using namespace s ...
- HDU 5280 BestCoder Round #47 1001:Senior's Array
Senior's Array Accepts: 199 Submissions: 944 Time Limit: 2000/1000 MS (Java/Others) Memory Limit ...
- java.sql.Date转换
---恢复内容开始--- JAVA 处理时间 - java.sql.Date.java.util.Date与数据库中的Date字段的转换方法,以及util包下的Date类与字符串的相互转换 在java ...
- BZOJ:1927: [Sdoi2010]星际竞速
题解:最小费用流+二分图模型: 左边表示出这个点,右边表示入这个点: #include<iostream> #include<cstdio> #include<cstri ...