Tensorflowlite 部署到 arm开发板
一 先在本机上操作
本机:Ubuntu18.04
1 下载TensorFlow
我选择的版本是:tensorflow-2.6.0
下载网址:
https://github.com/tensorflow/tensorflow
点master,选择tag,v2.6.0
(注:我是直接下载文件夹,进行解压。也可以 git clone,由于网速不行,clone不下来,就直接下载文件了,结果都一样)
下载依赖
#切换目录,切换到解压的tensorflow-2.6.0目录
cd tensorflow-2.6.0
#执行download_dependencies.sh脚本,下载依赖,下载时,资源可能因网速下载失败,多试几次,增量下载。或者,哪一个下载不下来,会提示网址,手动下载,然后在sh脚本里将其下载代码注释掉即可。
./tensorflow/lite/tools/make/download_dependencies.sh
上述命令,会在make目录下生成downloads目录,目录下依赖目录如下:
在make目录下:ls
absl eigen fft2d fp16 googletest ruy
cpuinfo farmhash flatbuffers gemmlowp neon_2_sse
2 准备ARM的交叉编译环境
交叉编译选择的是:arm-linux-gnueabihf-gcc 7.5.0
2.1 下载安装包
位置:
https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/
gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
2.2 解压安装包
2.3 配置环境变量
这里本文配置用户私有环境变量
vim .bashrc
#末尾添加:
export PATH=$PATH:/解压位置/gcc-linaro-arm-linux-gnueabihf-4.7-2013.03-20130313_linux/bin
#配置生效
source .bashrc
(base) power@raspberrypi:~$ ./load_iden -v 1 -m ./model/load_iden_v2_quant.tflite
-i ./light.bin -l ./multilabel.txt
INFO: Loaded model ./model/load_iden_v2_quant.tflite
INFO: tensors size:173
INFO: inputs:1
INFO: wanted with,height,channels:20,28,1
INFO: average time:19.954ms
INFO: predict result:
INFO: 【0,1,0,0,0】 白炽灯
2.4 查看编译器版本
直接在命令窗口输入命令:
arm-linux-gnueabihf-gcc --version
3 交叉编译生成静态库
#所在目录:tensorflow/lite/tools/make
#执行下面脚本
./build_rpi_lib.sh
主要目的:生成libtensorflow-lite.a静态库,交叉编译的时候用到
结果展示:
#所在目录:tensorflow/lite/tools/make
cd cd gen/rpi_armv7l
ls
bin lib obj
cd lib
benchmark-lib.a libtensorflow-lite.a
4 官方Demo :label_image的编译
4.1 整理头文件
cd tensorflow-2.6.0/tensorflow/lite
find -name "*.h" | tar -cf headers.tar -T -#这一步,是将lite头文件压缩打包
#找另外任意一个地方(离开tensorflow-2.6.0目录),新建一个目录,将我们需要进行编译相关的文件放在一起
mkdir test
cd test
mkdir -p include/tensorflow/lite#这一步
tar xvf headers.tar -C include/tensorflow/lite#将前面压缩打包的文件拷贝过来,解压
将absl flatbuffers gmock gtest tensorflow头文件也移动include目录下:
演示:flatbuffers,其他同理
#在test目录下操作
mkdir -p include/flatbuffers
cp tensorflow-2.6.0/tensorflow/lite/tools/make/downloads/flatbuffers/include/flatbuffers /* ./include/flatbuffers/
将tensorflow-2.6.0/tensorflow/lite/examples目录下的label_image目录也拷贝到test目录下
将tensorflow-2.6.0/tensorflow/lite/tools/make/gen/rpi_armv7l目录下的lib目录也拷贝到test目录下
即:test目录下目录
include label_image lib
4.2 cmake ,make 进行编译
cd test/label_image
修改CMakeLists.txt;#alter 标识,是我修改的地方
#
# Copyright 2020 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Builds the minimal Tensorflow Lite example.
cmake_minimum_required(VERSION 2.9)
project(label_image)
set(CMAKE_VERBOSE_MAKEFILE on)
#alter
set(tools /opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf)
#include_directories(../../tensorflow-2.6.3/tensorflow/lite)
include_directories(../include/flatbuffers)
include_directories(../include/tensorflow/lite)
include_directories(../include)
set(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-gnueabihf-g++)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "-O3 -static -pthread")
#alter
LINK_LIBRARIES("/mnt/toArm/test/lib/libtensorflow-lite.a")
add_executable(label_image
label_image.cc bitmap_helpers.cc
)
TARGET_LINK_LIBRARIES(label_image dl)
修改label_image.cc:
/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/examples/label_image/label_image.h"
#include <fcntl.h> // NOLINT(build/include_order)
#include <getopt.h> // NOLINT(build/include_order)
#include <sys/time.h> // NOLINT(build/include_order)
#include <sys/types.h> // NOLINT(build/include_order)
#include <sys/uio.h> // NOLINT(build/include_order)
#include <unistd.h> // NOLINT(build/include_order)/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/examples/label_image/label_image.h"
#include <fcntl.h> // NOLINT(build/include_order)
#include <getopt.h> // NOLINT(build/include_order)
#include <sys/time.h> // NOLINT(build/include_order)
#include <sys/types.h> // NOLINT(build/include_order)
#include <sys/uio.h> // NOLINT(build/include_order)
#include <unistd.h> // NOLINT(build/include_order)
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <unordered_set>
#include <vector>
#include "tensorflow/lite/tools/make/downloads/absl/absl/memory/memory.h"
#include "tensorflow/lite/examples/label_image/bitmap_helpers.h"
#include "tensorflow/lite/examples/label_image/get_top_n.h"
#include "tensorflow/lite/examples/label_image/log.h"
#include "tensorflow/lite/kernels/register.h"
#include "tensorflow/lite/optional_debug_tools.h"
#include "tensorflow/lite/profiling/profiler.h"
#include "tensorflow/lite/string_util.h"
#include "tensorflow/lite/tools/command_line_flags.h"
#include "tensorflow/lite/tools/delegates/delegate_provider.h"
namespace tflite {
namespace label_image {
double get_us(struct timeval t) {
return (t.tv_sec * 1000000 + t.tv_usec); }
using TfLiteDelegatePtr = tflite::Interpreter::TfLiteDelegatePtr;
using ProvidedDelegateList = tflite::tools::ProvidedDelegateList;
#if 0
template <class T>
void resize(T* out, uint8_t* in, int image_height, int image_width,
int image_channels, int wanted_height, int wanted_width,
int wanted_channels, Settings* s) {
cout<< "11111111111"<<endl
int number_of_pixels = image_height * image_width * image_channels;
std::unique_ptr<Interpreter> interpreter(new Interpreter);
int base_index = 0;
LOG(INFO)<< "11111111111"
// two inputs: input and new_sizes
interpreter->AddTensors(2, &base_index);
// one output
interpreter->AddTensors(1, &base_index);
// set input and output tensors
interpreter->SetInputs({
0, 1});
interpreter->SetOutputs({
2});
LOG(INFO)<< "11111111111"
// set parameters of tensors
TfLiteQuantizationParams quant;
interpreter->SetTensorParametersReadWrite(
0, kTfLiteFloat32, "input",
{
1, image_height, image_width, image_channels}, quant);
interpreter->SetTensorParametersReadWrite(1, kTfLiteInt32, "new_size", {
2},
quant);
LOG(INFO)<< "11111111111"
interpreter->SetTensorParametersReadWrite(
2, kTfLiteFloat32, "output",
{
1, wanted_height, wanted_width, wanted_channels}, quant);
LOG(INFO)<< "11111111111"
ops::builtin::BuiltinOpResolver resolver;
const TfLiteRegistration* resize_op =
resolver.FindOp(BuiltinOperator_RESIZE_BILINEAR, 1);
auto* params = reinterpret_cast<TfLiteResizeBilinearParams*>(
malloc(sizeof(TfLiteResizeBilinearParams)));
params->align_corners = false;
params->half_pixel_centers = false;
interpreter->AddNodeWithParameters({
0, 1}, {
2}, nullptr, 0, params, resize_op,
nullptr);
LOG(INFO)<< "interpreter->AllocateTensors()"
interpreter->AllocateTensors();
// fill input image
// in[] are integers, cannot do memcpy() directly
auto input = interpreter->typed_tensor<float>(0);
for (int i = 0; i < number_of_pixels; i++) {
input[i] = in[i];
}
// fill new_sizes
interpreter->typed_tensor<int>(1)[0] = wanted_height;
interpreter->typed_tensor<int>(1)[1] = wanted_width;
LOG(INFO)<< "interpreter->Invoke()"
interpreter->Invoke();
auto output = interpreter->typed_tensor<float>(2);
auto output_number_of_pixels = wanted_height * wanted_width * wanted_channels;
for (int i = 0; i < output_number_of_pixels; i++) {
switch (s->input_type) {
case kTfLiteFloat32:
out[i] = (output[i] - s->input_mean) / s->input_std;
break;
case kTfLiteInt8:
out[i] = static_cast<int8_t>(output[i] - 128);
break;
case kTfLiteUInt8:
out[i] = static_cast<uint8_t>(output[i]);
break;
default:
break;
}
}
}
#endif
// Takes a file name, and loads a list of labels from it, one per line, and
// returns a vector of the strings. It pads with empty strings so the length
// of the result is a multiple of 16, because our model expects that.
TfLiteStatus ReadLabelsFile(const string& file_name,
std::vector<string>* result,
size_t* found_label_count) {
std::ifstream file(file_name);
if (!file) {
LOG(ERROR) << "Labels file " << file_name << " not found";
return kTfLiteError;
}
result->clear();
string line;
while (std::getline(file, line)) {
result->push_back(line);
}
*found_label_count = result->size();
const int padding = 16;
while (result->size() % padding) {
result->emplace_back();
}
return kTfLiteOk;
}
void PrintProfilingInfo(const profiling::ProfileEvent* e,
uint32_t subgraph_index, uint32_t op_index,
TfLiteRegistration registration) {
// output something like
// time (ms) , Node xxx, OpCode xxx, symbolic name
// 5.352, Node 5, OpCode 4, DEPTHWISE_CONV_2D
LOG(INFO) << std::fixed << std::setw(10) << std::setprecision(3)
<< (e->end_timestamp_us - e->begin_timestamp_us) / 1000.0
<< ", Subgraph " << std::setw(3) << std::setprecision(3)
<< subgraph_index << ", Node " << std::setw(3)
<< std::setprecision(3) << op_index << ", OpCode " << std::setw(3)
<< std::setprecision(3) << registration.builtin_code << ", "
<< EnumNameBuiltinOperator(
static_cast<BuiltinOperator>(registration.builtin_code));
}
/// 使用的是mobilenet_v2_1.0_224_quant.tflite 量化后模型
void RunInference(Settings* settings)
{
std::unique_ptr<tflite::FlatBufferModel> model;
std::unique_ptr<tflite::Interpreter> interpreter;
model = tflite::FlatBufferModel::BuildFromFile(settings->model_name.c_str());
if (!model) {
LOG(ERROR) <<

本文详细介绍如何将TensorFlow Lite模型部署到ARM架构的开发板上,包括搭建环境、交叉编译、模型转换等关键步骤,并提供实际案例。

7509

被折叠的 条评论
为什么被折叠?



