Window下搭建Tensorflow的C++環境
參考Tensorflow官網安裝文章:https://www.tensorflow.org/install/source_windows?hl=zh-cn
一. 下載需要的軟體
- bazel:Google 的一款可再生的程式碼構建工具,類似於Cmake。使用scoop進行安裝:
scoop install bazel
- python3.7:這裡最好用pip 安裝下必要的第三方包,比如
tensorflow,kears,numpy
等。 - 下載官方原始碼:
git clone https://github.com/tensorflow/tensorflow.git
二. 進行bazel原始碼編譯
2.1 配置build
- cd到原始碼目錄:
cd tensorflow-master
- 通過在 TensorFlow 原始碼樹的根目錄下執行以下命令來配置系統構建:
python3 ./configure.py
- 這裡選擇的是cpu版本的,每個配置的選擇如下:
You have bazel 3.7.0 installed.
Please specify the location of python. [Default is C:\soft\python3.7.9\python3.exe]:
Found possible Python library paths:
C:\soft\python3.7.9\lib\site-packages
Please input the desired Python library path to use. Default is [ C:\soft\python3.7.9\lib\site-packages]
Do you wish to build TensorFlow with ROCm support? [y/N]: n
Do you wish to build TensorFlow with CUDA support? [y/N]: n
No CUDA support will be enabled for TensorFlow.
Please specify optimization flags to use during compilation when bazel option "--config=opt" is specified [Default is /arch:AVX]:
Would you like to override eigen strong inline for some C++ compilation to reduce the compilation time? [Y/n]: y
Eigen strong inline overridden.
Would you like to interactively configure ./WORKSPACE for Android builds? [y/N]: n
Not configuring the WORKSPACE for Android builds.
Preconfigured Bazel build configs. You can use any of the below by adding "--config=<>" to your build command. See .bazelrc for more details.
--config=mkl # Build with MKL support.
--config=mkl_aarch64 # Build with oneDNN support for Aarch64.
--config=monolithic # Config for mostly static monolithic build.
--config=numa # Build with NUMA support.
--config=dynamic_kernels # (Experimental) Build kernels into separate shared objects.
--config=v2 # Build TensorFlow 2.x instead of 1.x.
Preconfigured Bazel build configs to DISABLE default on features:
--config=noaws # Disable AWS S3 filesystem support.
--config=nogcp # Disable GCP support.
--config=nohdfs # Disable HDFS support.
--config=nonccl # Disable NVIDIA NCCL support.
2.2 bazel編譯
-
修改bazel中間檔案儲存的路徑(磁碟可用空間 Release 版本 >= 16G , Debug版本 >= 40G 編譯的中間檔案預設會放到 C:\使用者\你的賬號名\ _bazel_你的賬號名 下. C 盤可能沒有那麼大的空間, 所以要改一下輸出檔案的路徑),開啟tensorflow資料夾,
vim .bazelrc
,在最後一行加上startup --output_user_root=D:/tf
,如果不修改路徑,可能會編譯到一半就卡死。 -
bazel編譯動態連結庫命令(這裡加上使用的最大記憶體):
bazel build --config=opt //tensorflow:tensorflow_cc.dll --local_ram_resources=1024
-
編譯的過程可能會很長,千萬不要以為有問題就
Ctrl C
了(分2個過程:下中間資源+編譯),編譯完成後會出現Build completed successfully
-
編譯好的庫檔案在
tensorflow-master\bazel-bin\tensorflow
目錄下,分別是tensorflow_cc.dll
和tensorflow_cc.dll.if.lib
。 -
bazel編譯標頭檔案命令:
bazel build --config=opt //tensorflow:install_headers --local_ram_resources=1024
-
編譯好的標頭檔案在
tensorflow-master\bazel-bin\tensorflow\include
目錄下。
三. 新建專案測試
注意:
1. 這裡編譯的是tensorflow的release版本,因此構建專案的時候把環境從debug變成release
2. 在新建專案屬性表(這裡無論是opencv還是tensorflow)中,要選擇release版本的x64(64位)
- 新建一個專案
- 在專案中新建一個資料夾存放之前編譯好的標頭檔案,庫檔案,具體結構如下所示
├── tf_test// 整個專案
├── x64 // 這裡是生成解決方案得到的
├── tf // 這裡存放所有編譯好的檔案
├──bin // 存放dll動態庫檔案
├──tensorflow_cc.dll
├──lib // 存放靜態庫檔案
├──tensorflow_cc.lib
├──include // 直接是tensorflow編譯好的include目錄
├──main.cpp
-
屬性管理器 —— Release X64 —— 新增新專案屬性表(如果程式碼中還需要新增opencv庫的可以參考本人另一篇部落格)
-
VC++目錄中的包含目錄中新增:
D:tf_test\tf\include
-
VC++目錄中的庫目錄中新增:
D:tf_test\tf\lib
-
連結器——輸入——附加依賴項中新增:
tensorflow_cc.lib
-
-
選擇專案為release和x64平臺。
-
使用以下程式碼進行測試
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include<opencv2/opencv.hpp>
#include"tensorflow/core/public/session.h"
#include"tensorflow/core/platform/env.h"
using namespace std;
using namespace tensorflow;
using namespace cv;
int main()
{
const string model_path = "D:\\code\\yinbao_face\\live.pb";
const string image_path = "0.jpg";
Mat img = imread(image_path);
cvtColor(img, img, COLOR_BGR2RGB);
resize(img, img, Size(112, 112), 0, 0, INTER_NEAREST);
int height = img.rows;
int width = img.cols;
int depth = img.channels();
// 影象預處理
img = (img - 0) / 255.0;
// img.convertTo(img, CV_32FC3, 1.0 / 255, 0);
// 取影象資料,賦給tensorflow支援的Tensor變數中
const float* source_data = (float*)img.data;
Tensor input_tensor(DT_FLOAT, TensorShape({ 1, height, width, 3 }));
auto input_tensor_mapped = input_tensor.tensor<float, 4>();
for (int i = 0; i < height; i++) {
const float* source_row = source_data + (i * width * depth);
for (int j = 0; j < width; j++) {
const float* source_pixel = source_row + (j * depth);
for (int c = 0; c < depth; c++) {
const float* source_value = source_pixel + c;
input_tensor_mapped(0, i, j, c) = *source_value;
//printf("%d");
}
}
}
Session* session;
Status status = NewSession(SessionOptions(), &session);
if (!status.ok()) {
cerr << status.ToString() << endl;
return -1;
}
else {
cout << "Session created successfully" << endl;
}
GraphDef graph_def;
Status status_load = ReadBinaryProto(Env::Default(), model_path, &graph_def);
if (!status_load.ok()) {
cerr << status_load.ToString() << endl;
return -1;
}
else {
cout << "Load graph protobuf successfully" << endl;
}
// 將graph載入到session
Status status_create = session->Create(graph_def);
if (!status_create.ok()) {
cerr << status_create.ToString() << endl;
return -1;
}
else {
cout << "Add graph to session successfully" << endl;
}
cout << input_tensor.DebugString() << endl; //列印輸入
vector<pair<string, Tensor>> inputs = {
{ "input_1:0", input_tensor }, //input_1:0為輸入節點名
};
// 輸出outputs
vector<Tensor> outputs;
vector<string> output_nodes;
output_nodes.push_back("output_1:0"); //輸出有多個節點的話就繼續push_back
double start = clock();
// 執行會話,最終結果儲存在outputs中
Status status_run = session->Run({ inputs }, { output_nodes }, {}, &outputs);
Tensor boxes = move(outputs.at(0));
cout << boxes.DebugString() << endl; //列印輸出
double end = clock();
cout << "time = " << (end - start) << "\n";
if (!status_run.ok()) {
cerr << status_run.ToString() << endl;
return -1;
}
else {
//cout << "Run session successfully" << endl;
}
}
四. 測試中出現的問題
4.1 生成解決方案的時候報錯無法開啟包括檔案:
解決方式:在本地的通過python pip安裝後的tensorflow資料夾中(C:\soft\python3.7.9\Lib\site-packages\tensorflow\include
)將google
資料夾複製到D:tf_test\tf\include
下面,即可解決
4.2 生成解決方案的時候報錯Link1120:
解決方式:將vs2019上報錯資訊複製,cd到tensorflow-master\tensorflow\tools\def_file_filter
(這裡的tensorflow-master是自己下載tensorflow原始碼的地方),編輯def_file_filter.py.tpl
檔案:
# Header for the def file. (找到這一行程式碼)
if args.target:
def_fp.write("LIBRARY " + args.target + "\n")
def_fp.write("EXPORTS\n")
def_fp.write("\t [email protected]@@[email protected]\n")
# 下面兩個就是複製的錯誤資訊
def_fp.write("\t [email protected]@@[email protected]@[email protected]@[email protected]@@Z\n")
def_fp.write("\t [email protected]@@[email protected]\n")
重新編譯DLL,標頭檔案(雖然很麻煩,但是還是得做啊)
4.3 有太多的錯誤導致IntelliSense引擎無法正常工作,其中有些錯誤無法在編輯器
解決方式:在專案->屬性->配置屬性->C/C+±>前處理器->前處理器定義中加入_XKEYCHECK_H
就消失了
4.4 找不到tensorflow_cc.dll檔案
解決方式:將tensorflow_cc.dll
檔案複製到x64/release
資料夾下。
喜歡我的文章,還請大大們關注一波,當然可以直接訪問我的主頁:lixiaofei2yy.website