tensorflow框架一般都是基於Python調用,但是有些時候跟應用場景,我們希望調用tensorflow C語言的接口,在C++的應用開發中使用它。要這麼幹,首先需要下載tensorflow源碼,完成編譯,然後調用相關的API函數實現C語言版本的調用,完成模型的加載、前向推理預測與解析。
本文主要講DeeplabV3+語義分割模型的tensorflow C接口部署,不涉及到模型的訓練過程,訓練過程可以參考:
https://github.com/tensorflow/models/tree/master/research/deeplab.
官方提供了PASCAL VOC 2012,Cityscapes,ADE20K不同數據集上預訓練好的模型,同時還有基於ImageNet預訓練好的不同backbone網絡, 包括mobilenetv2,xception,resnet,我們可以根據自己的需求來選擇合適的backbone。本文不涉及tensorflow C版本的編譯,只是講解如何通過API調用預訓練模型進行前向推理預測,模型的導出文件為:
frozen_inference_graph.pb
在tensorflow中,輸入數據格式為Tensor格式,有專門的函數讀取圖片及轉換,但這樣給圖像預處理帶來了不便,所以一般情況下,會先用opencv對圖像進行讀取及預處理,再從opencv的Mat格式轉為tensorflow的Tensor格式,代碼如下:區區幾行代碼,卻是參考了無數資料及測試才得出來的,真是心酸
1TF_Tensor* CreateTensor(TF_DataTypedata_type, conststd::int64_t* dims, std::size_tnum_dims, constvoid* data, std::size_tlen)
2{
3 if (dims == nullptr || data == nullptr)
4 {
5 returnnullptr;
6 }
7 TF_Tensor* tensor = TF_AllocateTensor(data_type, dims, static_cast<int>(num_dims), len);
8 if (tensor == nullptr)
9 {
10 returnnullptr;
11 }
12 void* tensor_data = TF_TensorData(tensor);
13 if (tensor_data == nullptr)
14 {
15 TF_DeleteTensor(tensor);
16 returnnullptr;
17 }
18 std::memcpy(TF_TensorData(tensor), data, std::min(len, TF_TensorByteSize(tensor)));
19 return tensor;
20}
21
22TF_Tensor* Mat2Tensor(cv::Matimg)
23{
24 conststd::vector<std::int64_t>input_dims = { 1, 513, 513, 3 };
25 autodata_size = sizeof(std::uint8_t);
26 for (autoi : input_dims)
27 {
28 data_size *= i;
29 }
30 cv::resize(img, img, cv::Size(513, 513));
31 cvtColor(img, img, cv::COLOR_RGB2BGR);
32 TF_Tensor* image_input = CreateTensor(TF_UINT8, input_dims.data(), input_dims.size(), img.data, data_size);
33 returnimage_input;
34}
我們在執行推理的過程中,可能並不希望模型使用全部的GPU資源,又或者希望不同模型使用不同的GPU資源,這個時候需要設置。代碼如下:
1TF_SessionOptions *options = TF_NewSessionOptions();
2uint8_tconfig[16] = { 0x32, 0xe, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd0, 0x3f, 0x20, 0x1, 0x2a, 0x1, 0x30};
3TF_SetConfig(options, (void*)config, 16, status);
這個是模型使用25%的GPU資源,GPU的id為0,通過如下python代碼即可獲得配置參數。
1import tensorflow as tf
2gpu_options = tf.GPUOptions(allow_growth=True,per_process_gpu_memory_fraction=0.25,visible_device_list='0')
3config = tf.ConfigProto(gpu_options=gpu_options)
4serialized = config.SerializeToString()
5list(map(hex, serialized))
6print(list(map(hex, serialized)))
利用上面的配置,逐步打開及關閉3個模型的GPU使用情況如下圖: