先简单介绍一下,总体我要做的任务是,在移动端实时地进行人体动作行为检测和自定义类别的物体检测。这块需求中间断续和改动比较多,时间跨度也比较大。由于一些历史原因,只能先把人体动作行为检测降级改成物体检测同自定义类别的物体检测一起做,比如通过使用物体检测嘴巴,再加上嘴巴宽高比例来判断“张嘴”动作。但是如果抛开各种负担,是应该分开两个模型分别做动作行为和物体检测,如此可以达到更精细的效果。
移动端部署有很多工具,我采用的是 Tensorflow 的 TFLite。虽然 TF 很多时候灵活性上不尽人意,比如 tf2 迟迟出来解决 eager 问题,个人做些小研究实验什么的使用不是很灵活,但是在部署方面还是很方便很给力的,从 PC 到 网页到移动端等。
本篇只重点记录 TensorFlow TFLite 移动端物体检测安卓 demo 流程,这是最开始的地方,demo 里用的是 MobileNetv2 SSD 在 COCO 数据集上的模型。关于 MobileNetv2 和 SSD 已经记录过了,本篇也不重点讲述,关于其他很多细节,可能会单独再写。
关于参考资料,就直接看 tensorflow 官方提供的资料就够了,分别是官方给的各种实例 examples 以及各种模型 models资料。这两份资料会在整个过程中经常用到,因为篇幅很长,分了若干篇,后面视情况可能还会用到 tensorflow 的官方代码。
还有一点对我产生较大影响的是,tensorflow 提供的部分文档可能会没有及时更新。这就很坑人了鸭,所以在没有正确地图的情况下,可能会自己会在项目里面去四处查找相关的信息。也就是说,现在路都走通了,从上帝视角看,会省去很多弯路;但是中间有一些我摸索的过程,觉得也很重要。后面我会用“上帝视角”和“地图探索”分别标记我的整个过程,想直接看流程的,只看“上帝视角”就可以,“地图探索”可以跳过。
我有点害怕已经啰啰嗦嗦让人看了好无聊被劝退了,所以我先把 demo 的实际运行样子插图到这里好了(/(ㄒoㄒ)/~~求生欲极强)。
好了,继续安心说回 examples 和 models。我们会先接触了解 examples(本篇),models 一开始还没用到,后面会再说(好嘛,我直接把它安排到下篇去了……)。
examples 中我们主要看的是 lite 子目录,lite 下内容也很丰富,基本涵盖了基础的图像、语音和自然语言等任务。其中图像方面有手写数字识别、图像分类、物体检测、姿势检测、风格迁移等,我们当前比较关注的就是其中的 object detection,其下有三种移动端实现,分别是安卓、IOS和树莓派。
最早我也没有什么前端经验,就选的最好操作的安卓版本,本文后面就只拿安卓的实现来说明。(后来 IOS 版本也都有看过,测试能跑通之后就交给前端(被搁置)了,核心代码介绍也有记录过。)
上帝视角,要进行后续的步骤,首先要先把 examples 项目下载下来:
cd /path/to/put/examples
https://github.com/tensorflow/examples.git
后面要讲的 demo 就仅仅在 /examples/lite/examples/object_detection/android/app
中,emmm 别的没用到的项目可以留着练练手吼~
OK,到这里已经马上进入到 demo 的核心了。给个链接直达~主要信息都可以在页面的 README 中获取,也不知道为啥后半部分排版有点乱,官方至少一年了一直也没怎么改。
简单介绍下这个 demo ,通过在安卓设备上 build 和 run 一个量化过的、用 COCO 数据集训练好的 MobileNet SSD 模型,实现连续的移动端物体检测。
首先,至少需要准备一个安卓手机和 Android Studio。
关于手机的话,去年最早我用小米 8 尝试的时候就可以勉强带得动(时间稍长就会软件崩溃强行退出),近两年上市的智能手机应该都是 OK 的。(今年再重启这个需求的时候,重新官网拿这部分下来用发现整体检测都慢了很多,这个目前还没细看具体为什么。)
Android Studio 是用来做安卓应用开发的,因为 tflite 给的这个 demo 几乎等于傻瓜式直接运行了,并不需要完全重头学习安卓开发,即使没做过跟着指引看一看也就可以理解的,千万别被吓跑鸭。需要安卓开发环境在 API 21 以上,Android Studio 在 3.2 及以上,直接官网下最新的版本就可以。(插播一句,自 4.1 版本开始 Android Studio 支持 tflite 模型文件的信息查看了,后面还会提到呦~)
下载安装 Android Studio 之后,打开我们之前下载好的项目 /examples/lite/examples/object_detection/android/app
。
打开之后,它会根据 demo 中自带的 gradle 文件自行 Gradle Sync 下载安装依赖等进行配置,很乖,如果失败就科学上网解决一下。
等这些处理好之后,上面菜单栏的绿色运行按钮就亮了,可以运行了。连接你的电脑和手机,调成传输文件开发模式,Android Studio 就可以检测到你的手机设备,点击运行就可以了。
第一次运行的时候,会根据 demo 中写好的下载模型的文件下载模型(下图最后一行就是在下载模型)。这个步骤也是不成功就科学上网解决。
当我时过很久回头写这个的时候,本来想把去年这里的模型直接放到对应位置下省得下了,但是我发现报错了。在很靠前的位置初始化 ObjectDetector 的时候就出错了,如下图。
它说,找不到 TFLite Model 的 Metadata,还没有细看具体哪里变了,可能是官方 demo 哪里改动过了(后面再说),所以我也是下载的最新的,demo 中的模型现在是这个,提取码 pp6h。
运行安装之后,你的手机中就会出现一个黄色的 TFLite 的 APP 图标,实际运行就像前面我插的那个动图。具体识别的类别,是根据这个模型被训练时的标签类别决定的,这里就是常见的一些东西,emmm 我的白色小耳机它不认得,误检了,还有杯子鼠标等这个准确率啥的哎就凑合看吧要什么自行车。
到这一步,真切地看到手机实现物体检测,应该不会因为我的讲述被劝退了吧(孩怕),整装再出发去看看完成这个小工作的中的很多细节吧。
上帝视角: tensorflow 在此方面进行了更新,模型必须包含 metadata 信息才可以用。心里知道这一点,就可以先跳过对 metadata 的纠结,进行下一项。
地图探索:到这里的时候,因为要照着 README 展开流程讲,我在其中发现了前面我提到的那个报错(没有模型的 Metadata 那里)的原因。是因为这个 demo 被更新过,应该是三四个月前 demo 更新提供了两种实现检测的方案,分别是 lib_task_api
和 lib_interpreter
,两种 inference solutions 之间可以切换(就是下面文件夹中选中的这俩)。而其相关的信息,我写在了下个小标题中。
其中 lib_task_api
是直接使用现成的 Task 库集成模型 API 进行 inference,而 lib_interpreter
可以使 用户自定义 inference pipeline。照着 README 文件找到 app 下的 build.gradle 可以找到下面几行。其中有两行注释,第二行注释也就是 taskApi 那里被标注了是 default
并且是 high-level API,所以更新后的 demo 是默认使用 taskApi 的方式使用高级 API 来运行的。
flavorDimensions "tfliteInference"
productFlavors {
// The TFLite inference is built using the TFLite Java interpreter.
interpreter {
dimension "tfliteInference"
}
// Default: The TFLite inference is built using the TFLite Task library (high-level API).
taskApi {
getIsDefault().set(true)
dimension "tfliteInference"
}
}
关于这个 TaskApi 的介绍链接在这里,往下翻一下就可以看到有这点说明如下图(稍微有点长,没有截全),其中就提到了这个 API 强制要求 TFLite 模型的 Metadata。
而去年我做的时候,还没有这两种选择,当时就是另外一种 lib_interpreter
的方式,介绍在这里。它使用的就是 TensorFlow Lite Interpreter Java API,当时用的模型也就适配这种用法,可以跑通。
README 也说了可以在两个 inference solutions 之间切换,切换方式如下:
(1)在 Android Studio 软件界面的左下角找到 Build Variants
。
(2)点击 Build Variants
打开它的工具栏,如下图。点击图中蓝色选中的 taskApiDebug
就可以弹出来其他选项,选择 InterpreterDebug
就切换到 lib_interpreter 方式了。
README 关于如何选择两个 inference API,也给出了建议。如果只是想简单地直接运行一下这个 app,推荐使用默认的 lib_task_api
做 inference 就好了;如果你希望自定义你的模型并且能够控制输入输出的细节信息,那么更建议使用 lib_interpreter
。
上帝视角:可以先乖乖地按照建议,选择 lib_interpreter
的方式。但是切换到 lib_interpreter
的方式,也拯救不了去年的模型,因为 lib_interpreter
也是被更新了的,这两种方式现在都需要写入 metadata 到 tflite 模型才可以。所以别费力气了,下一步就好了~
地图探索:如何得到上面这段上帝视角的呢?那就再甩个链接给你喽~因为我真的去看了 task_api
和 interpreter
在 Android Studio 的具体使用鸭,还对比了和一年前的旧版的异同。
上帝视角:这个模型是 tensorflow 已经写入过 metadata 的 tflite,所以直接就可以在这里用。
模型这里,demo 自己提供的可以在 Android Studio 第一次运行时自动下载解压到指定目录。负责下载模型并解压放置的文件在 app 文件夹下,文件名为 download_model.gradle
。内容如下:
task downloadModelFile(type: Download) {
src 'https://tfhub.dev/tensorflow/lite-model/ssd_mobilenet_v1/1/metadata/2?lite-format=tflite'
dest project.ext.ASSET_DIR + '/detect.tflite'
overwrite false
}
preBuild.dependsOn downloadModelFile
可以看到它下载模型的链接,还有存放的位置在 /examples/lite/examples/object_detection/android/app/src/main/assets/detect.tflite
,如果模型已存在就不会下载覆盖了。
说到这里,如果后面你想训练自己的模型,就可以把模型修改名字放到 assets
目录下。这个目录下还有另一个文件,是模型对应的标签 labelmap.txt
。对于 COCO 数据集训练出来的模型对应的 labelmap.txt
也就是 demo 中自带的 label 文件一共有 91 类,前几个 label 是这样的:
person
bicycle
car
motorcycle
airplane
bus
train
…
这一段路可能稍微长一点,整个过程可以分为以下几步。
(1)准备你自己的检测模型;
(2)将这个模型 freeze,得到固化后的 Tensorflow Lite graph;
(3)把上一步的 frozen graph 转格式生成 tflite 的模型,连同你的 labelmap 一起放到 assets
下。
(4) 上帝视角:把 labelmap 信息写入到 tflite 中,生成携带 metadata 的 tflite 模型。 地图探索:这一步 app 下面的 README 压根儿没讲啊!!!也就是最早我看到的时候,根本不知道还有这一步存在呀,很多文档没有及时更新呀!需要自己找资料一点点看呀!
其中第(1)步等同于平时 PC 端训练模型,而后面(2)(3)(4)步骤是在移动端实现检测的特有步骤。
粗略来讲,PC 端训练得到的模型,参数量大且精细,需要的运行资源相对也较多。而在移动端实现检测时,无论是存储还是运算,总是希望资源占用得少一些,那么这个时候就需要对模型进行改进。
改进模型使其更适合移动端大概可以从下面两个角度出发:
乍一开始了解可能还比较抽象,后面一步步走进去看一看就好了。
哎算了,有点长,我要重开一篇。跑了先,der~