点击我爱计算机视觉标星,更快获取CVML新技术


文 / Lucia Li 实习生,TensorFlow Lite

Smart Photo Booth 应用实时运行图示

我们很高兴展示借助 TensorFlow Lite 在 Raspberry Pi 上构建 Smart Photo Booth 应用的经验(我们尚未开放源代码)。该应用可以捕捉笑脸并自动进行记录。此外,您还可以使用语音命令进行交互。简而言之,借助 Tensorflow Lite 框架,我们构建出可实时轻松处理笑脸检测和识别语音命令的应用。

  • Tensorflow Lite
    https://tensorflow.google.cn/lite

为什么选择 Raspberry Pi?

Raspberry Pi 不仅是使用广泛的嵌入式平台,且有体积小、价格便宜的优势。我们选择 TensorFlow Lite 是因为它专为移动端和 IoT 设备而设计,因此非常适合 Raspberry Pi。

构建 Photo Booth 应用需准备什么?

我们已在 Raspberry Pi 3B+ 上实现 Photo Booth 应用,其搭载 1GB RAM,并装有 32 位 ARMv7 操作系统。我们的应用具有图像输入和音频输入功能,因此我们还需要摄像头和麦克风。除此之外,我们还需要显示器来显示内容。总成本不到 100 美元。详情如下所列:

  • 一台 Raspberry Pi(35 美元)

    • 配置:
      » 主频为 1.4GHz 的四核 64 位处理器
      » 1GB LPDDR2 SRAM

  • 一部用于捕获图像的摄像头(约 15 美元)

  • 一个采集音频数据的麦克风(约 5 美元)

  • 一台 7 英寸的显示器(约 20 美元)

Photo Booth 应用涉及到两个关键技术:

  1. 我们需要从相机的图像输入中检测是否有笑脸;

  2. 我们需要从麦克风的音频输入中识别出是否存在“是”或“否”的语音命令。

如何检测笑脸?

我们很难在使用单个模型检测人脸并预测笑脸得分结果的同时保证高精度和低延迟。因此,我们通过以下三个步骤来检测笑脸:

  1. 应用人脸检测模型来检测给定的图像中是否存在人脸。

  2. 如果存在,则将其从原始图像中裁剪出来。

  3. 对裁剪后的人脸图像应用人脸属性分类模型,以测量其是否为笑脸。

笑脸检测工作流

我们尝试了如下几种方法来降低笑脸检测的延迟时间:

  1. 为减少内存占用并加速执行进程,我们使用了 TensorFlow 模型优化工具包中的训练后量化 (Post Training Quantization) 技术。在本教程中,针对您自己的 TensorFlow Lite 模型,您会发现该技术将非常易于使用。

  2. 对从摄像头中捕获的原始图像进行大小调整,并固定其长宽比。压缩率根据原始图像大小采用 4 或 2。尽量让图像尺寸小于 160x160(原设计尺寸为 320x320)。输入尺寸较小的图像可以大大减少推理时间,如下表所示。在我们的应用中,从相机中捕获的原始图像尺寸为 640x480,所以我们将图像尺寸调整为 160x120。

  3. 我们并未使用原始图像进行面部属性分类,而是弃用背景并使用裁剪出的标准人脸。如此可在保留有用信息的同时减小输入图像的尺寸。

  4. 使用多线程开展推理

  • 训练后量化
    https://tensorflow.google.cn/model_optimization/guide/quantization

  • 教程
    https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/g3doc/performance/post_training_integer_quant.ipynb

下表显示我们所用策略所带来的效果。我们使用 Tensorflow Lite 模型性能测试工具对人脸检测模型在 Raspberry Pi 上的表现进行性能评估。

  • Tensorflow Lite 模型性能测试工具
    https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/tools/benchmark

人脸检测延迟时间对比

检测笑脸的整个流程(包括我们之前提到的三个步骤)平均耗时 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 毫秒左右。

如何识别语音命令?

实时语音命令识别也可以分为三个步骤:

  1. 预处理:我们使用滑动窗口来储存最新的 1 秒音频数据,以及音频所对应的 512 帧图像。

  2. 推理:通过输入的 1 秒音频,我们可以应用语音命令模型来获得出现以下四种类别的概率(“是”/“否”/“无声”/“未知”)。

  3. 后期处理:我们通过当前的推理结果与先前的结果计算出平均值。当一个词语的平均出现概率高于某个阈值时,我们便判断已检测到语音命令。

我会在下文详细解释这三个步骤。

预处理

我们使用 PortAudio(一个开源代码库)获取来自麦克风的音频数据。下图展示我们如何储存音频数据。

  • PortAudio
    http://www.portaudio.com/

音频流处理

由于我们的模型使用采样率为 16kHz 的 1 秒音频数据进行训练,因此数据缓冲区的大小为 16,000 字节。数据缓冲区亦作为循环缓冲区使用,我们每次会更新对应的 512 帧。此外,我们还会记录偏移量,用于指明上次更新的结束位置。当缓冲区尾部已满时,我们会从缓冲区的头部继续操作。在我们想要获取音频数据来展开推理时,我们会从偏移处开始读取,然后在偏移结束对应的帧结束。

语音命令识别

您可在许多公开的 TensorFlow 示例中找到我们使用的语音命令识别模型。该模型由 audio_spectrogram、MFCC、2 个卷积层和 1 个全连接层组成。这个模型的输入内容为采样率为 16kHz 的 1 秒音频数据。数据集支持公开访问,或者您也可自行训练。此数据集包含 30 种语音命令数据。由于我们只需要“是”和“否”类别,所以我们将其他标记归类为“未知”。

  • 语音命令识别模型
    https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/speech_commands

此外,我们也采用了其他方法来缩短延迟时间:

  1. 我们去除半数通道。压缩后的TensorFlow Lite 模型大小约为 1.9 MB。

  2. 与通常情况下使用最后一个全连接层的 12 个输出通道有所不同,由于我们只需要 4 种类别,所以我们使用了其中 4 个输出通道。

  3. 我们使用多线程来进行推理。

在训练中,我们将背景音量设置成 0.3,以提高模型的抗噪能力。我们还将“无声”和“未知”类别的比例各设置成 25%,以平衡训练集。

后期处理

音频流后期处理

由于我们获取的音频数据可能仅截取到一半命令,所以单个预测结果并不准确。我们储存先前结果(之前的记录时间不长于 1.5s),以取得平均预测结果。这可以大大提高关键字检测的实时性能。我们能够保存的先前结果的数量,在很大程度上取决于我们的推理时间。例如,我们模型在 Raspberry Pi 上的推理时间约为 160 毫秒,这意味着我们最多可以保存 9 个先前结果。

后续行动

我们希望在 TensorFlow Lite Github 代码库中尽快开放这个示例的源代码。如要了解关于如何上手使用 TensorFlow Lite 的更多详情,请参阅此处,并在此处查看其他参考示例。

  • 参阅此处
    https://tensorflow.google.cn/lite/guide

  • 此处
    https://tensorflow.google.cn/lite/examples/

欢迎留言分享您的 TensorFlow Lite 用例。

致谢

感谢 Lucia Li、Renjie Liu、Tiezhen Wang、Shuangfeng Li、Lawrence Chan、Daniel Situnayake、Pete Warden。


模型压缩与应用部署交流群

关注最新最前沿的网络压缩、知识蒸馏、剪枝、量化、应用部署技术,扫码添加CV君拉你入群,(如已为CV君其他账号好友请直接私信)

(请务必注明:部署)

喜欢在QQ交流的童鞋,可以加52CV官方QQ群:805388940。

(不会时时在线,如果没能及时通过验证还请见谅)


长按关注我爱计算机视觉

实战|TF Lite 让树莓派记下你的美丽笑颜相关推荐

  1. 使用TF lite 优化 MobileDet 目标检测模型部署

    文 / Sayak Paul,Google Developer Expert 今年,来自威斯康星大学麦迪逊分校和 Google 的研究人员发表了他们在 MobileDet 上所做的研究工作.他们在 M ...

  2. 量化版——使用TF Lite将Mobilenet SSD目标检测移植至安卓客户端

    使用TF Lite将Mobilenet SSD移植至安卓客户端 1. 配置 2. 准备工作 2.1 下载 2.1.1 下载models-1.12.0 2.1.2 下载模型 2.1.3 下载tensor ...

  3. 树莓派java游戏机_学用树莓派(8)-实战案例:基于树莓派JAVA的微型激光雕刻机-控制器/处理器-与非网...

    大学之前就希望做一个激光雕刻机,我对 JAVA 也非常感兴趣,正好呢树莓派有 pi4j 作为支持,那么刚好这次 e 络盟举行这个比赛,就打算用树莓派和 java 做一个激光雕刻机.我也希望通过这次比赛 ...

  4. Java转gcode,学用树莓派(8)-实战案例:基于树莓派JAVA的微型激光雕刻机

    大学之前就希望做一个激光雕刻机,我对JAVA也非常感兴趣,正好呢树莓派有pi4j作为支持,那么刚好这次e络盟举行这个比赛,就打算用树莓派和java做一个激光雕刻机.我也希望通过这次比赛让更多的人知道p ...

  5. 自玩树莓派记录-关于树莓派LCD3.5英寸屏幕使用及raspios(raspbian)-lite简单GUI服务搭建记录

    自玩树莓派记录-关于树莓派LCD3.5英寸屏幕使用及raspios(raspbian)-lite简单GUI服务搭建记录 硬件准备 1.下载系统 2.树莓派安装系统 上脸 安装GUI服务 最后填个坑,慢 ...

  6. TensorFlow 2.7 正式版上线,改进 TF/Keras 调试,支持 Jax 模型到 TensorFlow Lite转换

    点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 转自 | 机器之心 TensorFlow2.7 正式发布,新版本包括对 tf.kera ...

  7. TensorFlow Lite指南实战,附48页ppt

    点击上方"AI遇见机器学习",选择"星标"公众号 重磅干货,第一时间送达 [导读]TensorFlow Lite是可帮助开发人员在移动端(mobile).嵌入式 ...

  8. 树莓派4支持多大tf卡_惊!自制树莓派投屏神器!

    最近打算买个LG的投影仪,发现投影仪有不同的型号,带WebOS(LG的操作系统,能够投屏)的居然要比不带WebOS的贵3000,惊慌之下,我拿出了我积灰已久的树莓派B3,打算看看能不能自己搞一个Web ...

  9. 玩转树莓派——安装系统

    纠结了很久,终于在今年生日的时候买了个树莓派 3.拿到以后少不了各种折腾,慢慢的把折腾过程写下来吧. 有关RaspBerry Pi 3,技术参数以及对应提升,就没必要在这里赘述了,官网介绍应有尽有:h ...

最新文章

  1. 在Ubuntu 16.04.3 LTS上玩转quic-go项目
  2. 简约之美Jodd-http--深入源码理解http协议
  3. mysql中case when then 的使用
  4. 输出目录文件被多个中间文件输出目录相同的工程包含
  5. Kafka集群部署搭建完美标准版
  6. memcache 缓存命中率   状态查询
  7. linux运行c程序a. out,无法运行已编译的文件 – bash:./ a.out:权限被拒绝. (我试过chmod)...
  8. java二叉树深度优先遍历会考不递归的吗_树的广度优先遍历和深度优先遍历(递归非递归、Java实现)...
  9. LeetCode力扣(27. 移除元素)----Java/JavaScript/C
  10. plus webview关闭事件监听
  11. C# 多线程同步和线程通信
  12. VTD-传感器使用小结
  13. 网络安全技术之虚拟专用网络
  14. 计算机软件性能测试的过程,软件性能测试过程研究与应用
  15. 依概率收敛与按分布收敛
  16. ESP8266制作天气预报海藻球微景观生态缸记录(六)-网页控制灯光颜色准备
  17. 制作可爱的小黄人插图
  18. mac pro M1(ARM)安装:centos8.0虚拟机
  19. python函数介绍(20804字的带图超详细说明)
  20. 安装与破解IntelliJ IDEA2017

热门文章

  1. Quaternion类之美
  2. 一学就会:springMVC获取请求参数有哪几种方式?
  3. IT员工眼中的加班猝死:无加班不IT
  4. 分位数回归损失函数代码实现解析
  5. OBS使用流程问题总结
  6. 星膜力隐形车衣的五大功能
  7. 百度地图SDK for iOS v2.1.0全新发布
  8. HIWORD和LOWORD
  9. html input 提示文字
  10. php蓝牙串口,打印机蓝牙模块(串口)使用说明及参考电路