文 / Lucia Li 实习生,TensorFlow Lite
Smart Photo Booth 应用实时运行图示
我们很高兴展示借助 TensorFlow Lite 在 Raspberry Pi 上构建 Smart Photo Booth 应用的经验(我们尚未开放源代码)。该应用可以捕捉笑脸并自动进行记录。此外,您还可以使用语音命令进行交互。简而言之,借助 Tensorflow Lite 框架,我们构建出可实时轻松处理笑脸检测和识别语音命令的应用。
为什么选择 Raspberry Pi?
Raspberry Pi 不仅是使用广泛的嵌入式平台,且有体积小、价格便宜的优势。我们选择 TensorFlow Lite 是因为它专为移动端和 IoT 设备而设计,因此非常适合 Raspberry Pi。
构建 Photo Booth 应用需准备什么?
我们已在 Raspberry Pi 3B+ 上实现 Photo Booth 应用,其搭载 1GB RAM,并装有 32 位 ARMv7 操作系统。我们的应用具有图像输入和音频输入功能,因此我们还需要摄像头和麦克风。除此之外,我们还需要显示器来显示内容。总成本不到 100 美元。详情如下所列:
Photo Booth 应用涉及到两个关键技术:
如何检测笑脸?
我们很难在使用单个模型检测人脸并预测笑脸得分结果的同时保证高精度和低延迟。因此,我们通过以下三个步骤来检测笑脸:
笑脸检测工作流
我们尝试了如下几种方法来降低笑脸检测的延迟时间:
下表显示我们所用策略所带来的效果。我们使用 Tensorflow Lite 模型性能测试工具对人脸检测模型在 Raspberry Pi 上的表现进行性能评估。
人脸检测延迟时间对比
检测笑脸的整个流程(包括我们之前提到的三个步骤)平均耗时 48.1ms 并只使用一个线程,这意味着我们能够实现实时笑脸检测。
人脸检测
我们的人脸检测模型由定制的 8 位 MobileNet v1 模型和深度乘数为 0.25 的 SSD-Lite 模型所构成。其大小略大于 200KB。为什么这个模型这么小?第一,基于 Flatbuffer 的 TensorFlow Lite 模型大小比基于 Protobuf 的 TensorFlow 模型小。第二,我们采用 8 位量化模型。第三,我们的 MobileNet v1 经过改良,通道比原来更少。
与大多数人脸检测模型类似,模型会输出边界框和 6 个面部关键特征点(包括左眼、右眼、鼻尖、嘴部中心、左耳屏点和右耳屏点)的坐标。我们还应用了非极大值抑制 (Non-Maximum Suppression) 来过滤重复的人脸。人脸检测 TensorFlow Lite 模型的推理时间约为 30 毫秒。这意味着模型可以在 Raspberry Pi 上实现实时检测人脸。
边界框和 6 个面部关键特征点示例
人脸裁剪工具
检测到的人脸朝向和尺寸大小各不相同,为了统一并更好地进行分类,我们会旋转、裁剪和缩放原始图像。我们将从人脸检测模型中获得的 6 个面部关键特征点的坐标输入函数。通过这 6 个面部关键特征点,我们便可以计算出旋转角度和缩放比例。经过上述流程后,我们便可得到 128x128 的标准人脸图片。下图示例展示我们面部裁剪工具的功能。蓝色边界框是人脸检测模型的输出结果,而红色边界框是我们经计算得出的裁剪边界框。我们会复制图像外部的像素边界线。
人脸裁剪工具图示
人脸属性分类
我们的人脸属性分类模型也是 8 位量化 MobileNet 模型。将 128x128 的标准人脸输入该模型,其会输出介于 0 到 1 的浮点型变量用于预测微笑的概率。该模型也会输出 90 维向量来预测年龄,范围在 0 到 90 之间。其在 Raspberry Pi 上的推理时间可以达到 30 毫秒左右。
如何识别语音命令?
实时语音命令识别也可以分为三个步骤:
我会在下文详细解释这三个步骤。
预处理
我们使用 PortAudio(一个开源代码库)获取来自麦克风的音频数据。下图展示我们如何储存音频数据。
音频流处理
由于我们的模型使用采样率为 16kHz 的 1 秒音频数据进行训练,因此数据缓冲区的大小为 16,000 字节。数据缓冲区亦作为循环缓冲区使用,我们每次会更新对应的 512 帧。此外,我们还会记录偏移量,用于指明上次更新的结束位置。当缓冲区尾部已满时,我们会从缓冲区的头部继续操作。在我们想要获取音频数据来展开推理时,我们会从偏移处开始读取,然后在偏移结束对应的帧结束。
语音命令识别
您可在许多公开的 TensorFlow 示例中找到我们使用的语音命令识别模型。该模型由 audio_spectrogram、MFCC、2 个卷积层和 1 个全连接层组成。这个模型的输入内容为采样率为 16kHz 的 1 秒音频数据。数据集支持公开访问,或者您也可自行训练。此数据集包含 30 种语音命令数据。由于我们只需要“是”和“否”类别,所以我们将其他标记归类为“未知”。
此外,我们也采用了其他方法来缩短延迟时间:
在训练中,我们将背景音量设置成 0.3,以提高模型的抗噪能力。我们还将“无声”和“未知”类别的比例各设置成 25%,以平衡训练集。
后期处理
音频流后期处理
由于我们获取的音频数据可能仅截取到一半命令,所以单个预测结果并不准确。我们储存先前结果(之前的记录时间不长于 1.5s),以取得平均预测结果。这可以大大提高关键字检测的实时性能。我们能够保存的先前结果的数量,在很大程度上取决于我们的推理时间。例如,我们模型在 Raspberry Pi 上的推理时间约为 160 毫秒,这意味着我们最多可以保存 9 个先前结果。
后续行动
我们希望在 TensorFlow Lite Github 代码库中尽快开放这个示例的源代码。如要了解关于如何上手使用 TensorFlow Lite 的更多详情,请参阅此处,并在此处查看其他参考示例。
欢迎留言分享您的 TensorFlow Lite 用例。
致谢
感谢 Lucia Li、Renjie Liu、Tiezhen Wang、Shuangfeng Li、Lawrence Chan、Daniel Situnayake、Pete Warden。