1. 介绍
原先识别人体骨骼,使用的Google的 MLKit 框架 。方便简单,直接通过Gradle添加相关依赖库。就可以使用了。
渐渐的接触到了Tensorflow框架。它是一个开源的可以创建生产级机器学习模型。也就是说我们可以扩展更多的使用场景,训练自己的框架,实现某些方面的专门的AI识别。
嗯,我个人理解就是类似百度的飞桨(PaddlePaddle),他们都是机器学习框架。
而由于Tensorflow 是Google 在2015年11月就进行了的开源项目。它的生态比百度的飞桨要完善不少。
而这里,我主要介绍下Tensorflow提供的Pose Estimation (姿态估计)框架Demo示例。
让我们了解Tensorflow能够实现的姿态估计效果。
Demo提供了17个骨骼坐标点返回。(我们可以自己训练框架提供更多的坐标点。)
2. Tensorflow Lite 示例
首先通过Git拉取代码:https://github.com/tensorflow/examples.git/
可以拉取到tensorflow的全部examples(示例)代码。
例如,我的本地目录就叫做examples,在该目录下有:
courses,lite,templates,tensorflow_examples等文件夹。
而我们需要的Android 或者ios 的示例在 lite/examples
目录下,在该目录你会发现很多的示例:
示例 | 介绍 |
---|---|
audio_classification | 音频分类 |
bert_qa | BERT问答 |
classification_by_retrieval | 按检索分类 |
digit_classifier | 数字分类 |
gesture_classification | 手势分类 |
image_classification | 图像分类 |
image_segmentation | 图像切割 |
model_personalization | 模型个性化 |
object_detection | 对象检测 |
optical_character_recognition | 光学字符识别 |
pose_estimation | 姿态估计 |
posenet | 姿态网络模型(2017年发布的上一代姿态估计) |
recommendation | 推荐示例(基本模型推荐) |
reinforcement_learning | 强化学习 |
smart_reply | 智能回复 |
sound_classification | 声音分类 |
speech_commands | 语音注解 |
speech_recognition | 语音识别 |
style_transfer | 风格转换 |
super_resolution | 超级决议 |
text_classification | 文本分类 |
text_searcher | 文本搜索 |
video_classification | 视频分类 |
这些示例中,有些是Android端代码和ios端代码都存在,有些只有Android,没有ios的。还有些有Python的,web的。等等。 没有示例代码,并不代表Tensorflow不支持。
3. PoseEstimation 导入
我们选择examplesliteexamplespose_estimationandroid
目录,导入到Android Studio之中。就可以打开关于人体姿态识别的Demo示例了。
Android Studio建议在4.2版本以上。否则会有很多编译错误需要我们进行修改。 最小API 21。
3.1 tflite 模型介绍
如果不导入该四种模型库,在运行时App会崩溃的。
在这个示例Demo中,展示了四种姿态模型。分别对应的模型文档为:
movenet_lightning.tflite:单姿势模型:该模型只能估计一个人的姿势。(最新的姿态识别模型,比thunder文件小,速度快,但是精度低。)
movenet_thunder.tflite:单姿势模型:该模型只能估计一个人的姿势。(最新的姿态识别模型,比lightning文件大,速度慢,但是精度高。)
movenet_multipose_fp16.tiflite:多姿势模型:该模型最多能够支持6人模型识别。
posenet.ftlite:单姿势模型:该模型只能估计一个人的姿势。(2017年,发布的上一代姿态识别)
(PS:这四个文档,在示例代码中并不存在,需要我们主动进行下载这四种模型)
总而言之:追求速度用:movenet_lightning.tflite。追求精度用:movenet_thunder.tflite。多人识别用:movenet_multipose_fp16.tiflite。 posenet精度要差不少,不建议使用。
Model | Size (MB) | mAP | Latency (ms) | ||
---|---|---|---|---|---|
Pixel 5 - CPU 4 threads | Pixel 5 - GPU | Raspberry Pi 4 - CPU 4 threads | |||
MoveNet.Thunder (FP16 quantized) | 12.6MB | 72.0 | 155ms | 45ms | 594ms |
MoveNet.Thunder (INT8 quantized) | 7.1MB | 68.9 | 100ms | 52ms | 251ms |
MoveNet.Lightning (FP16 quantized) | 4.8MB | 63.0 | 60ms | 25ms | 186ms |
MoveNet.Lightning (INT8 quantized) | 2.9MB | 57.4 | 52ms | 28ms | 95ms |
PoseNet(MobileNetV1 backbone, FP32) | 13.3MB | 45.6 | 80ms | 40ms | 338ms |
如果可以的话, 建议通过上面的表格中,选择类型进行下载。
如果你下载不知道,可以参考导入的Demo中的app/download.gradle
.
如果你能正确访问外网,在build 构造项目时Gradle会自动调用download.gradle里面的模型下载任务,从网络中下载相关模型文档,并进行重命令,
然后存储在assets目录下。
例如:
https://storage.googleapis.com/download.tensorflow.org/models/tflite/pose_classifier/yoga_classifier.tflite 下载的yoga_classifier.tflite 模型,重命名为 classifier.tflite
文件,存储在assets目录下。
https://tfhub.dev/google/lite-model/movenet/multipose/lightning/tflite/float16/1?lite-format=tflite 下载的tflite模型,重命名为 movenet_multipose_fp16.tflite
存储在assets目录下。
https://tfhub.dev/google/lite-model/movenet/singlepose/thunder/tflite/float16/4?lite-format=tflite 下载的tflite模型,重命名为movenet_thunder.tflite
存储在assets目录下。
https://tfhub.dev/google/lite-model/movenet/singlepose/lightning/tflite/float16/4?lite-format=tflite 下载的tflite模型,重命名为movenet_lightning.tflite
存储在assets目录下。
https://storage.googleapis.com/download.tensorflow.org/models/tflite/posenet_mobilenet_v1_100_257x257_multi_kpt_stripped.tflite 下载的tflite模型,重命名为posenet.tflite
存储在assets目录下。
如果你的网络,能够访问国外网络。就能够正常的下载。如果不能访问,你在Gradle build项目时就会有链接超时的错误提示。 如果无法下载,你可以通过搜索关注我的公众号:
zinyan
或者在首页扫码关注公众号,留言:tflite
获取我下载好的模型文件。
在代码中ml/MoveNet.kt文件第53行代码中,标注了movenet_lightning.tflite的文件名称:
代码语言:javascript复制 // TFLite file names.
private const val LIGHTNING_FILENAME = "movenet_lightning.tflite"
private const val THUNDER_FILENAME = "movenet_thunder.tflite"
在MoveNoetMultiPose.kt文件的第93行代码中,标注了movenet_multipose_fp16.tflite的文件名称:
代码语言:javascript复制return MoveNetMultiPose(
Interpreter(
FileUtil.loadMappedFile(
context,
if (type == Type.Dynamic)
"movenet_multipose_fp16.tflite" else ""
//@TODO: (khanhlvg) Add support for fixed shape model if it's released.
), options
), type, gpuDelegate
)
在PoseClassifier.kt文件中第32行代码,标注了classifier.tflite文件名称:
代码语言:javascript复制 private val output = interpreter.getOutputTensor(0).shape()
companion object {
private const val MODEL_FILENAME = "classifier.tflite"
private const val LABELS_FILENAME = "labels.txt"
private const val CPU_NUM_THREADS = 4
在PoseNet.kt文件中第46行代码,标注了posenet.tflite文件名称:
代码语言:javascript复制 companion object {
private const val CPU_NUM_THREADS = 4
private const val MEAN = 127.5f
private const val STD = 127.5f
private const val TAG = "Posenet"
private const val MODEL_FILENAME = "posenet.tflite"
3.2 编译
当我们的gradle版本正确,tflite模型导入正确。就可以直接进行编译了。编译将会打包一个TFL Pose Estimation
的app安装到手机上。
识别效果如下所示: