树莓派上使用 TensorFlow Lite 的 PhotoBooth Lite
2020 年 1 月 30 日
作者:Lucia Li,TensorFlow Lite 实习生

智能照相亭应用程序实时运行的示例。
我们很高兴展示在树莓派上使用 TensorFlow 构建智能照相亭应用程序的体验(我们目前尚未开源代码)。它可以捕捉微笑的脸庞并自动记录。此外,您还可以使用语音命令与它进行交互。得益于 Tensorflow Lite 框架,我们构建了该应用程序,使其能够轻松地在实时处理微笑面部检测和语音命令识别。

为什么要在树莓派上构建应用程序?

树莓派不仅是一个广泛使用的嵌入式平台,而且体积小巧,价格便宜。我们决定使用 TensorFlow Lite,因为它专门为移动设备和物联网设备设计,非常适合树莓派。

构建照相亭应用程序演示需要什么?

我们在配备 1GB RAM 和安装了 32 位 ARMv7 操作系统的树莓派 3B+ 上实现了我们的照相亭应用程序。我们的应用程序具有图像输入和音频输入,因此我们还需要一台摄像头和一个麦克风。此外,我们需要一个显示器进行显示。总成本低于 **$100 美元**。以下是详细列表:
  • 树莓派($35)
    ‣ 参数
    » 四核 64 位处理器,主频为 1.4GHz。
    » 1GB LPDDR2 SRAM。
  • 摄像头,用于捕捉图像(约 $15 以上)
  • 麦克风,用于采样音频数据(约 $5 以上)
  • 7 英寸显示器(约 $20 以上)
在我们的照相亭应用程序中,涉及两项关键技术。从摄像头图像输入中,我们需要能够检测是否存在微笑的面部。从麦克风音频输入中,我们需要能够识别是否存在“是”或“否”的语音命令。

如何检测微笑的面部?

使用单个模型来检测面部并预测生成的微笑分数,同时兼顾高精度和低延迟,是困难的。因此,我们通过三个步骤来检测微笑的面部:
微笑面部检测工作流程
  1. 应用面部检测模型来检测给定图像中是否存在面部。
  2. 如果存在面部,则将其从原始图像中裁剪出来。
  3. 使用裁剪后的面部图像,应用面部属性分类模型来测量它是否是一个微笑的面部。
我们尝试了各种选项来减少检测微笑面部的延迟:
  1. 为了减少内存并加快执行速度,我们利用了 TensorFlow 模型优化工具箱的 训练后量化。在这个 教程 中,您可以看到在自己的 TensorFlow Lite 模型中使用它有多么容易。
  2. 我们调整了从摄像头捕捉到的原始图像的大小,使其长宽比固定。压缩比可以是 4 或 2,具体取决于其原始大小。我们试图使图像大小小于 160x160(原始设计大小为 320x320)。较小的输入会显着减少推理时间,如下表所示。在我们的应用程序中,从摄像头捕捉到的原始图像大小为 640x480,因此我们将其调整为 160x120。
  3. 我们没有使用原始图像进行面部属性分类,而是裁剪了标准面部并放弃了背景。它减少了输入大小,同时保留了有用信息。
  4. 我们使用多线程进行推理。

下表显示了我们应用的策略的影响。我们使用 Tensorflow Lite benchmark_model 来评估面部检测模型在树莓派上的性能:
面部检测延迟比较
整个检测微笑面部的流程,包括我们之前提到的三个步骤,在单线程上的平均耗时为 **48.1ms**,这意味着我们实现了实时微笑面部检测。

面部检测

我们的面部检测模型由一个 8 位修改版的 MobileNet v1 主体和一个深度乘数为 0.25 的 SSD-Lite 头组成。它的大小仅略大于 200kB。为什么这个模型如此小?首先,TensorFlow Lite 模型基于 Flatbuffer,它比基于 protobuf 的 TensorFlow 模型更小。其次,我们应用了 8 位量化模型。第三,我们修改后的 MobileNet v1 比原始模型具有更少的通道。
与大多数面部检测模型类似,我们的模型输出边界框的位置和 6 个地标,包括左眼、右眼、鼻尖、嘴巴中心、左耳耳屏和右耳耳屏。我们还应用非极大值抑制来过滤重复的面部。我们的面部检测 TensorFlow Lite 模型的推理时间约为 30ms。这意味着我们的模型可以在树莓派上实时检测面部。
边界框和 6 个地标的示例。

面部裁剪器

检测到的面部可能具有不同的方向和不同的尺寸。为了统一它们以获得更好的分类效果,我们旋转、裁剪并调整了原始图像的大小。此函数的输入是我们从面部检测模型中获得的 6 个地标的位置。利用 6 个地标,我们可以计算旋转欧拉角和调整大小比率。通过这种方式,我们可以获得一个 128x128 的标准面部。下图显示了我们的面部裁剪器函数的一个示例。蓝色边界框是面部检测模型的输出,而红色边界框是我们计算出的裁剪边界框。我们将边界线复制到图像外部的像素上。
面部裁剪器插图

面部属性分类

我们的面部属性分类模型也是一个 8 位量化 MobileNet 模型。以 128x128 的标准面部作为输入,模型输出一个 0 到 1 之间的浮点变量来预测微笑概率。模型还输出一个 90 维向量来预测年龄,范围从 0 到 90。它在树莓派上的推理时间可以达到约 30ms。

如何识别语音命令?

实时语音命令识别也可以分为三个步骤:
  1. 预处理:我们使用滑动窗口来存储最新的 1 秒音频数据,与上次录制相比,有 512 帧不同。
  2. 推理:给定 1 秒的音频输入,我们可以应用语音命令识别模型来获取四个类别(“是”/“否”/“静音”/“未知”)的概率。
  3. 后处理:我们将当前推理结果与之前的结果平均。当某个单词的平均概率超过某个阈值时,我们判断检测到一个语音命令。
下面将详细解释这三个步骤。

预处理

我们使用 PortAudio,这是一个开源库,可以从麦克风获取音频数据。下图显示了我们如何存储音频数据。
音频流处理
由于我们的模型使用 1 秒的音频数据,采样率为 16kHz 进行训练,因此我们的数据缓冲区大小为 16,000 字节。数据缓冲区也充当循环缓冲区。我们每次更新 512 帧。此外,我们记录一个偏移量,它指示上次更新的结束位置。当缓冲区的尾部已满时,我们将从缓冲区的头部继续。当我们要获取音频数据进行推理时,我们将从偏移量开始读取,并一直读取到偏移量之前的帧。

语音命令识别

我们在许多 TensorFlow 示例中公开找到了我们使用的 语音命令识别模型。它由音频频谱图、MFCC、2 个卷积层和 1 个全连接层组成。该模型的输入是 1 秒的音频数据,采样率为 16kHz。数据集是公开的,或者您可以自己训练。该数据集包含 30 个类别的语音命令数据。由于我们只需要“是”和“否”,因此我们忽略了所有其他类别,标记为“未知”。
此外,我们还使用了其他方法来提高延迟性能:
  1. 我们剪掉了半数通道。TensorFlow Lite 模型压缩后的大小约为 1.9 MB。
  2. 我们使用了 4 个输出通道的最后一个全连接层,而不是通常的 12 个通道,因为我们只需要 4 个类别。
  3. 我们使用多线程进行推理。
在训练中,我们将背景音量设置为 0.3,以提高模型的噪声容忍度。我们还将静音百分比设置为 25%,将未知百分比设置为 25%,以平衡训练集。

后处理

音频流后处理
由于我们获取的音频数据可能只涵盖了半句话,因此单次预测结果并不精确。我们存储了不超过 1.5 秒之前的录音时间的前一次结果,以获得平均预测结果。它极大地提高了关键词检测的实时性能。我们保留的前一次结果的数量很大程度上取决于我们的推理时间。例如,我们的模型在树莓派上的推理时间约为 160ms,这意味着我们最多可以保留 9 个前一次结果。

下一步?

我们希望很快在 TensorFlow Lite Github 存储库中开源此示例的代码。有关如何开始使用 TensorFlow Lite 的更多信息,请参阅 此处 和其他参考示例 此处
请告诉我们您的想法或 与我们分享您的 TensorFlow Lite 使用案例

致谢

Lucia Li、Renjie Liu、Tiezhen Wang、Shuangfeng Li、Lawrence Chan、Daniel Situnayake、Pete Warden。
下一篇文章
PhotoBooth Lite on Raspberry Pi with TensorFlow Lite

作者:Lucia Li,TensorFlow Lite 实习生

我们很高兴展示使用 TensorFlow 在 Raspberry Pi 上构建智能照片亭应用程序的经验(我们目前尚未开源代码)。它可以捕捉微笑的脸部并自动录制。此外,您还可以使用语音命令与它进行交互。得益于 Tensorflow Lite 框架,我们构建的应用程序非常容易…