C++ 调用tensorflow

2023-11-16

1.安装protobuf 3.6

# 安装依赖软件
sudo apt-get install autoconf automake libtool curl make g++ unzip
# 克隆版本为3.6.0的protobuf源码
git clone -b v3.6.0 https://github.com/protocolbuffers/protobuf.git
# 下载 protobuf 的子模块
cd protobuf
git submodule update --init --recursive


./autogen.sh
./configure
make
# make check 如果失败会导致使用某些功能时报错
make check
sudo make install
sudo ldconfig
# 输出protobuf版本信息则表示安装成功
protoc --version

2.安装eigen3

Tensorflow依赖Eigen矩阵运算库,在编译和使用视需要安装对应的版本.可以在 tensorflow/tensorflow/workspace.bzl 中找到对应版本的下载地址

  tf_http_archive(
      name = "eigen_archive",
      urls = [
          "https://mirror.bazel.build/bitbucket.org/eigen/eigen/get/2355b229ea4c.tar.gz",
           "https://bitbucket.org/eigen/eigen/get/2355b229ea4c.tar.gz",
       ],
# 解压下载的文件夹到 /usr/local/include
sudo tar -xzvf eigen-eigen-5a0156e40feb.tar.gz -C /usr/local/include
# 重命名为 eigen3
sudo mv /usr/local/include/eigen-eigen-5a0156e40feb /usr/local/include/eigen3

3.依赖C++库 Abseil 库

下载abseil-cpp,并放在子目录中

在cmake中添加 abseil-cpp

add_subdirectory(abseil-cpp)

target_link_libraries(xx ...  absl::base absl::synchronization absl::strings)

4.编译tensorflow

安装bazel

在tensorflow源码目录运行.configure

bazel build --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package //tensorflow:libtensorflow_cc.so

编译python和c++库

生成python wheal文件

bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg

生成的c++ so包在 bazel-bin/tensorflow下面:libtensorflow_cc.so和libtensorflow_framework.so

4.1 编译其他依赖

  • 进入 tensorflow/contrib/makefile 目录下,运行 ./build_all_linux.sh ,成功后会出现一个gen文件夹

  • 若出现如下错误 /autogen.sh: 4: autoreconf: not found ,安装相应依赖即可 sudo apt-get install autoconf automake libtool

5.C++调用逻辑

tensorflow加载文件构建网络,所需加载的pb文件由checkpoints 和 pb 冻结生成.

创建头文件

#ifndef TENSORFLOW_C_RECOVER_TOOL_H
#define TENSORFLOW_C_RECOVER_TOOL_H

#include <strings.h>

#include <stdio.h>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

#include <tensorflow/core/framework/tensor_shape.h>
#include <tensorflow/core/platform/init_main.h>
#include <tensorflow/core/public/session.h>
#include "opencv2/opencv.hpp"

using namespace tensorflow;
using tensorflow::Tensor;
using tensorflow::Status;
using tensorflow::string;

using tensorflow::int32;
using namespace std;
using namespace cv;

class RecoverTool {

public:
    RecoverTool();

    int modelLoader(const string &model_path);

    string predict(cv::Mat &cvImg);

    void resize(Mat &inImg, Mat &outImg);

private:
    Session *session;

    string dict_vector = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-'_&.!?,\\\"";

    bool session_statu = false;

    void padding_img(Mat &src, Mat &out);

    string tensor_to_str(vector<Tensor> &outputs);
};


#endif //TENSORFLOW_C_RECOVER_TOOL_H

生成Session

RecoverTool::RecoverTool() {
    Status status = NewSession(SessionOptions(), &this->session);
    if (!status.ok()) {
        cout << "Session create failed.\n";
        cout << status.ToString() << "\n";
        this->session_statu = false;
    } else {
        this->session_statu = true;
        cout << "Session successfully created.\n";
    }
}

加载pb模型

int RecoverTool::modelLoader(const string &model_path) {
    tensorflow::GraphDef graphdef;
    Status status_load = ReadBinaryProto(Env::Default(), model_path, &graphdef);
    if (!status_load.ok()) {
        cout << "ERROR: Loading model failed..." << model_path << endl;
        cout << status_load.ToString() << "\n";
        return -1;
    }

    // Add the graph to the session
    Status status_create = this->session->Create(graphdef);
    if (!status_create.ok()) {
        cout << "ERROR: Creating graph in session failed..." << status_create.ToString() << endl;
        return -1;
    }
    return 0;
}

预测函数,需要先生成输入 tensor,tensor的维度( b,h,w,c)和 dtype 需要与模型一致.

string RecoverTool::predict(cv::Mat &cvImg) {
    std::vector<Tensor> outputs;

    int inputHeight = cvImg.size().height;
    int inputWidth = cvImg.size().width;

    // Run tensorflow
    cv::TickMeter tm;
    tm.start();

    // 生成输入 tensor
    tensorflow::Tensor imgTensorWithSharedData(
            tensorflow::DT_UINT8, {16, inputHeight, inputWidth, cvImg.channels()});

    // 将图片的数据加载到 tensor 中
    auto x_map = imgTensorWithSharedData.tensor<uint8_t, 4>();
    for (int b = 0; b < 16; b++) {
        for (int h = 0; h < inputHeight; h++) {
            const uchar *inData = cvImg.ptr<uchar>(h);
            for (int w = 0; w < inputWidth; w++) {
                x_map(b, h, w, 0) = inData[w];
            }
        }
    }

    tensorflow::Status run_status = this->session->Run({{"input:0", imgTensorWithSharedData}},
                                                       {"crnn/dense_out:0"}, {}, &outputs);
    if (!run_status.ok()) {
        std::cerr << "TF_Session->Run Error: " << run_status << std::endl;
    }
    tm.stop();

    cout << "spent:" << tm.getTimeMilli() << endl;

    return tensor_to_str(outputs);
}

结果处理

string RecoverTool::tensor_to_str(vector<Tensor> &outputs) {

    Tensor t = outputs[0];                   // Fetch the first tensor
    int ndim = t.shape().dims();

    // Get the dimension of the tensor
    tensorflow::TTypes<int>::Flat scores = outputs[0].flat<int>(); // Tensor Shape: [batch_size, target_class_num]

    string result = "";
    for (int i = 0; i < scores.size(); i++) {
        int index = scores.data()[i];
        if (index != -1 && index < this->dict_vector.size()) {
            result += this->dict_vector.at(index);
        }
    }

    return result;
}

cmake 文件

cmake_minimum_required(VERSION 3.6)
project(tensorflow_c__)

set(CMAKE_CXX_STANDARD 14)

find_package(Threads REQUIRED)
find_package(OpenCV REQUIRED)

# protobuf
find_package(Protobuf REQUIRED)

include_directories(${Protobuf_INCLUDE_DIRS})

#opencv
include_directories(/usr/local/include)

#tensorflow
include_directories(~/tensorflow)
include_directories(/usr/local/include/eigen3)
include_directories(~/anaconda3/lib/python3.6/dist-packages/tensorflow/include)
include_directories(~/tensorflow/bazel-genfiles/)

#abseil-cpp
add_subdirectory(abseil-cpp)

add_executable(tensorflow_c__ main.cpp recover_tool.cpp recover_tool.h)

target_link_libraries(tensorflow_c__
        ~/tensorflow/bazel-bin/tensorflow/libtensorflow_cc.so
        ~/tensorflow/bazel-bin/tensorflow/libtensorflow_framework.so
        ${OpenCV_LIBS} ${Protobuf_LIBRARIES} absl::base absl::synchronization absl::strings)

cmake中include文件夹也可以直接指向 4.1 编译的文件夹

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 调用tensorflow 的相关文章

随机推荐

  • 信道编码知识点总结

    通信系统常用差错控制方法 自动重发请求法 ARQ 前向纠错法 FEC 信头差错校验法 HEC 自动重发法 接收端译码器判决收到的码序列有没有错误 通过反馈信道把判决结果告诉发送端 发送端根据判决信号重发接收端认为有错的信息 直到接收端认为正
  • 期货交易服务行业调研报告 - 市场现状分析与发展前景预测

    期货交易服务市场的企业竞争态势 该报告涉及的主要国际市场参与者有Daniels Trading Saxo Tradovate NinjaTrader AGT Futures CQG Gain Capital Group ABLWSYS Sm
  • MIPS系统网络的配置

    4 MIPS系统网络的配置 模拟MPIS系统 并配置MIPS系统网络 01 安装依赖文件 sudo apt get install uml utilities bridge utils 02 修改Ubuntu主机网络配置 将Ubuntu系统
  • 单目测距(yolo目标检测+标定+测距代码)

    单目测距 目标检测 标定 测距 实时感知本车周围物体的距离对高级驾驶辅助系统具有重要意义 当判定物体与本车距离小于安全距离时便采取主动刹车等安全辅助功能 这将进一步提升汽车的安全性能并减少碰撞的发生 上一章本文完成了目标检测任务 接下来需要
  • 一枚芯片的成本是多少?(2)芯片硬件成本

    芯片硬件成本 计算封装和测试的成本这个没有具体的公式 只是测试的价格大致和针脚数的二次方成正比 封装的成本大致和针脚乘功耗的三次方成正比 如果CPU X采用40nm低功耗工艺的自主芯片 其测试成本约为2美元 封装成本约为6美元 因40nm低
  • nodejs调用mongodb!!!

    Nodejs调用MongoDB 要在 MongoDB 中创建一个数据库 首先我们需要创建一个 MongoClient 对象 然后配置好指定的 URL 和 端口号 如果数据库不存在 MongoDB 将创建数据库并建立连接 导入MongoDB包
  • 华为VS谷歌:万物互联,谁主沉浮?

    一 一周两套操作系统发布 6月2日 华为通过直播形式举行了鸿蒙HarmonyOS 2及华为全场景新品发布会 关于该发布会的详细内容老猿在 鸿蒙最新功能及承载设备详解 HarmonyOS 2及华为全场景新品发布会全纪录 进行了详细介绍 在此不
  • 【科普】一文读懂以太网PHY芯片

    物理层器件PHY Physical Layer Interface Devices 是将各网元连接到物理介质上的关键部件 负责完成互连参考模型 OSI 第1层中的功能 即为链路层实体之间进行bit传输提供物理连接所需的机械 电气 光电转换和
  • 嵌入式中锁机制杂谈

    在之前的文章中有提到操作系统中锁机制一般依赖于硬件CPU提供的原子数据操作指令 如SWP TEST AND SET等原子原语实现 基于此 才能真正保证锁机制的有效实现 通过上面原子操作 我们比较容易实现所谓的自旋操作 原子性的原地循环判断条
  • np.random.choice用法

    np random choice a size replace p 其作用是按要求生成一个一维数组 a是生成一维数组的来源 可以是int类型 可以是数组 也可以是list size 为从a中抽取的个数 即生成数组的维度 replace 表示
  • 《数据库系统》课程之实验七 通过ODBC/JDBC转移异构数据库中数据

    注 查看全文请关注作者 或点击前往 数据库系统 课程之实验七 通过ODBC JDBC转移异构数据库中数据 数据库系统 课程之实验七 通过ODBC JDBC转移异构数据库中数据 1 实验目的 学会配置ODBC JDBC数据源 熟悉使用ODBC
  • QueryWrapper方法解释

    继承自 AbstractWrapper 自身的内部属性 entity 也用于生成 where 条件 及 LambdaQueryWrapper 可以通过 new QueryWrapper lambda 方法获取 queryWrapper lt
  • PyTorch实战——搭建PyTorch神经网络进行气温预测

    如果觉得我的分享对您的学习有帮助 可以点赞关注哈 谢谢哈 目录 编辑 一 理论部分 二 代码实战 1 导入模块 1 matplotlib inline 2 warnings filterwarnings ignore 2 读入数据 3 展示
  • 三极管电路共集、共基、共射的区别

    共集 共基 共射指的是电路 是三极管电路的连接状态而不是三极管 所谓 共 就是输入 输出回路共有的部分 其判断是在交流等效电路下进行的 共集电极电路 三极管的集电极接地 集电极是输入与输出的公共极 共基极电路 三极管的基极接地 基极是输入与
  • 安装ubuntu系统时给/home分配空间太小,导致训练模型时数据集无法存放,所以给/home增大100GGB的存储空间

    1 从Windows系统中分配出100GB的存储空间 2 制作gparted的U盘启动项 3 插入U盘 进入bios界面 选择U盘启动项 4 进入gparted软件界面进行存储空间的转移重新分配 5 Exit退出 重新进入linux系统 参
  • 微信小程序 WebSocket 端口号配置

    https blog liuguofeng com p 4630 服务端开启 WebSocket 使用 WorkerMan phpSocket io 开启的端口为 2120 访问为 ws wanaioa unetu net 2120 由于微
  • 基于 java Swing 客户端 和 Spring Boot/Spring Cloud & Alibaba 后台管理系统

    基于 java Swing 客户端 和 Spring Boot Spring Cloud Alibaba 后台管理系统 基于 java Swing 客户端 和 Spring Boot Spring Cloud Alibaba 后台管理系统
  • 【Java JDK的使用方法】

    Java JDK的使用方法 第一步 同时按住窗口键和R键 在弹出的运行框中输入cmd打开编译框 第二步 输入cd 空格 地址 可以查看桌面文本文档的属性 找到桌面地址 第三步 notepad 空格 文件名 java 新建java文件 第四步
  • 何为UNP技术?

    为了解决移动视频监控系统中的这种穿NAT型 宇视科技特意提出了UNP UniversalNetwork Passport 万能网络护照 技术 目前 针对监控系统穿越NAT设备 防火墙和安全网闸时 基本上都是使用引流方案 内部服务器 双网口方
  • C++ 调用tensorflow

    安装protobuf 3 6 安装依赖软件 sudo apt get install autoconf automake libtool curl make g unzip 克隆版本为3 6 0的protobuf源码 git clone b