原作者: Wezley Sherman

链接: https://towardsdatascience.com/tensorflow-meet-the-esp32-3ac36d7f32c7


如果我必须选择一个最喜欢的计算领域,我会选择嵌入式系统。我非常喜欢在资源受限的环境中优化代码所带来的挑战。
当我意识到TensorFlow Lite支持微控制器时,我兴奋地几乎掀翻了我的桌子。
我有几个ESP32-CAM模块,我想用于家庭安全系统。我的想法是部署一个能识别人的模型,一旦相机拍到人就开始录音。我不想在这里使用运动感应,因为我有一只狗会绊倒传感器。
我认为TensorFlow Lite是这个用例的一个很好的工具。我可以训练一个模型来识别桌面上的人,然后将其部署到我的ESP32-CAM模块中。
在阅读了TensorFlow Lite文档之后,很明显,使用PlatformIO并不像调用:

platformio lib install tfmicro

除非我想使用Adafruit库(spoiler:我不想)。
经过一些仔细的尝试和错误,我能够让TensorFlow Lite在ESP32上和PlatformIO玩得很好。
本指南将介绍如何编译“Hello World”示例,并使用支持Arduino-ESP32的PlatformIO将其上载到ESP32-CAM模块。

为PlatformIO部署设置TensorFlow Lite

你要做的第一件事就是安装PlatformIO。要打开终端并键入:

pip install -U platformio

现在,创建项目的根目录。此目录还应包含srclibinclude的子目录。
在项目的根目录中,创建一个名为platformio.ini的文件。此文件将包含PlatformIO初始化开发环境所需的所有信息。

参考这里

接下来,需要创建一个名为custom.csv的文件。这是ESP32闪存的分区信息。您可以根据应用程序的需要和ESP32的闪存大小格式化分区表。关于ESP32分区表的更多信息可以在这里找到。下面是custom.csv文件的格式:
参考这里

完成所有这些设置后,继续克隆TensorFlow存储库(包括TensorFlow Lite)。您可以将其下载为.zip并解压缩到您选择的目录,或者使用git克隆:

git clone https://github.com/tensorflow/tensorflow.git

下载TensorFlow存储库后,从TensorFlow Lite文件夹中生成一个示例ESP32项目。我们希望生成一个示例项目,以便可以获取生成的tfmicro库和示例模型。要生成示例项目,请导航到根“tensorflow”文件夹并运行:

sudo make -f tensorflow/lite/experimental/micro/tools/make/Makefile TARGET=esp generate_hello_world_esp_project

这将生成一个示例项目,该项目将位于:

tensorflow/lite/experimental/micro/tools/make/gen/esp_xtensa-esp32/prj/hello_world

导航到hello_world/esp-idf目录,并将tfmicro文件夹从components复制到前面创建的lib文件夹中。如果计划运行示例程序以确保正确设置环境,请将sin_model_data.ccsin_model_data.h从主文件夹复制到srcinclude文件夹。
您的文件结构现在应该类似于:
Project Directory Structure
项目目录结构
到目前为止还很容易,对吧?
你快完成了!您只需要调整tfmicro库文件夹中的一些内容,这样PlatformIO就可以看到TensorFlow Lite需要的所有第三方库。
导航到tfmicro文件夹。您应该看到两个文件夹:tensorflowthird_party
进入third_party/flatbuffers/include并将flatbuffers子目录复制到tfmicro根目录中。
接下来,进入third_party/gemmlowp并将fixedpoint和内部目录复制到tfmicro根目录中。
最后,将kissfft目录从third_party复制到tfmicro根目录。
此时,您可以继续并删除third_party目录。
通过将所有third_party库移动到tfmicro根目录中,PlatformIO可以识别并使用它们。
项目的最终结构应如下所示:
File structure for a TensorFlow Lite ESP32 Project
TensorFlow Lite ESP32项目的文件结构
文件结构完成后,导航到lib/tfmicro/flatbuffers并在base.h中打开base.h,将第34行从以下位置:

#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H)
  #include <utility.h>
#else
  #include <utility>
#endif

更改为:

#include <utility>

现在完成了!唯一要做的就是导入并在项目中使用TensorFlow Lite。

创建示例项目

为了测试TensorFlow Lite是否正常工作,我改编了“Hello World!“Arduino-ESP32草图中使用的正弦模型。
下面我将会引导你完成以下的工作!

包括

我做的第一件事是导入项目将使用的所有库

参考这里

这些库如下:

  • Arduino .h— Arduino支持! :)
  • math.h — 这里专门用于M_PI的定义(稍后讨论)。
  • all_ops_resolver.h — 定义用于运行模型的操作。
  • micro_error_reporter.h — 用于错误报告。
  • micro_interpreter.h — 运行模型。
  • sine_model_data.h — 我们正在使用的示例模型。

全局变量

接下来,我来设置变量:

参考这里

我定义的第一个全局变量是存储模型生成的数组的内存池。TensorFlow的文档说明,您可能必须根据不同模型的实验得出池大小。为此,我使用了TensorFlow为运行sine模型提供的示例代码。
然后我定义了模型、解释器和输入/输出节点。

设置设计

定义了全局变量后,就可以设置环境了。
在“setup()”函数中,我以115200波特的速度启动串行,并导入正弦模型。

参考这里

然后我实例化了TensorFlow Lite微解释器

参考这里

最后,我将模型的张量分配到定义为全局的内存池中,并将输入和输出变量设置为它们对应的节点。

参考这里

“setup()”函数结束。要点:我导入了模型,创建了解释器,并将模型加载到内存中。

控制回路设计

“setup()”函数完成后,我开始实现控制循环逻辑。
对于控制回路,我等待用户从串行输入并将其转换为浮点。然后我检查以确保用户输入在模型的参数(0–2*PI)内:

参考这里

然后,我将模型的输入节点设置为解析用户输入,调用解释器,然后输出结果:

参考这里

部署到ESP32

代码完成后,您可以使用PlatformIO部署到ESP32:

platformio run -t upload --upload-port /dev/ttyUSB0

Uploading to the ESP32
上传到ESP32
然后,您可以使用:

screen /dev/ttyUSB0 115200

Running Sine Model on ESP32
在ESP32上运行正弦模型
就这样!我真的很惊讶TensorFlow竟能如此容易地将模型部署到微控制器上。下一篇文章中我将介绍如何使用TensorFlow创建一个模型,以及如何将其转换为可以由TensorFlow Lite运行的东西!
GitHub项目地址: https://github.com/wezleysherman/ESP32-TensorFlow-Lite-Sample

PS:我是黑胡桃实验室社区的一名成员,最近经常在看一些老外做的有趣的人工智能项目,如果有兴趣或疑问可以在评论区或私信与我交流~。