[Mediapipe]bazel编译与aar文件生成
为何我突然钟情于mediapipe?
因为mediapipe综合了很多新进技术的方向,实时人脸识别,实时物体识别,实时手部识别,每一个的应用都是非常前沿的,并且涉及到opencv检测,机器学习,C++编程,一个能够跨平台 Android ios 桌面,甚至web框架的应用,每一样的学习都是让人神往的。并且拥有这些必要只是技能和储备,将会在未来得以施展。
这次要说一下Mediapipe的打包,上一节提及的,mediapipe打包是使用bazel。
bazel是Google开源的一套编译构建工具,广泛应用于Google内部,包括TensorFlow项目。修改TensorFlow内部源码,需要使用bazel来编译,故有必要了解下bazel。bazel优点很多,主要有
1.构建快。支持增量编译。对依赖关系进行了优化,从而支持并发执行。
2.可构建多种语言。bazel可用来构建Java C++ Android ios等很多语言和框架,并支持mac windows linux等不同平台
3.可伸缩。可处理任意大小的代码库,可处理多个库,也可以处理单个库
4.可扩展。使用bazel扩展语言可支持新语言和新平台。
那么通过基本去读懂bazel对aar的配置来,来对构建一些理解。
如果不知道bazel怎么配置在AS,可以阅读[Mediapipe]Mediapipe的Android配置
根目录workspace文件
要进行构建的文件系统,根目录下必须包含一个文件名为WORKSPACE的文件,即使它内容为空。它指明了构建的根目录。文件系统中包括源文件,头文件,输出目录的符号链接等。WORKSPACE采用类似Python的语法。
//workspace名字
workspace(name = "mediapipe")
//从.bazel加载一些内容,
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
//下载bazel文件,然后解压它
skylib_version = "0.8.0"
http_archive(
name = "bazel_skylib",
type = "tar.gz",
url = "https://github.com/bazelbuild/bazel-skylib/releases/download/{}/bazel-skylib.{}.tar.gz".format (skylib_version, skylib_version),
sha256 = "2ef429f5d7ce7111263289644d233707dba35e39696377ebab8b0bc701f7818e",
)
//加载maven下载
maven_install(
artifacts = [
"androidx.annotation:annotation:aar:1.1.0",
"androidx.appcompat:appcompat:aar:1.1.0-rc01",
"androidx.camera:camera-core:aar:1.0.0-alpha06",
"androidx.camera:camera-camera2:aar:1.0.0-alpha06",
"androidx.constraintlayout:constraintlayout:aar:1.1.3",
"androidx.core:core:aar:1.1.0-rc03",
"androidx.legacy:legacy-support-v4:aar:1.0.0",
"androidx.recyclerview:recyclerview:aar:1.1.0-beta02",
"com.google.android.material:material:aar:1.0.0-rc01",
],
repositories = [
"https://dl.google.com/dl/android/maven2",
"https://repo1.maven.org/maven2",
],
)
//maven服务器
maven_server(
name = "google_server",
url = "https://dl.google.com/dl/android/maven2",
)
//单独下载maven jar包
maven_jar(
name = "androidx_lifecycle",
artifact = "androidx.lifecycle:lifecycle-common:2.0.0",
sha1 = "e070ffae07452331bc5684734fce6831d531785c",
server = "google_server",
)
//配置Android的sdk和ndk
# You may run setup_android.sh to install Android SDK and NDK.
android_ndk_repository(
name = "androidndk",
)
android_sdk_repository(
name = "androidsdk",
)
在每一个子工程里面,还需要配置自身的workspace文件。你可以理解和android的build.gradle配置类似。
以facedetectiongpu为例
package(default_visibility = ["//visibility:private"])
//编译并添加mediapipe_jni.so
cc_binary(
name = "libmediapipe_jni.so",
linkshared = 1,
linkstatic = 1,
//依赖于calculators文件
deps = [
"//mediapipe/graphs/face_detection:mobile_calculators",
"//mediapipe/java/com/google/mediapipe/framework/jni:mediapipe_framework_jni",
],
)
//添加mediapipe_jni
cc_library(
name = "mediapipe_jni_lib",
srcs = [":libmediapipe_jni.so"],
alwayslink = 1,
)
//添加mediapipe流程图
# Maps the binary graph to an alias (e.g., the app name) for convenience so that the alias can be
# easily incorporated into the app via, for example,
# MainActivity.BINARY_GRAPH_NAME = "appname.binarypb".
genrule(
name = "binary_graph",
srcs = ["//mediapipe/graphs/face_detection:mobile_gpu_binary_graph"],
outs = ["facedetectiongpu.binarypb"],
cmd = "cp $< $@",
)
//添加mediapipe_lib library
android_library(
name = "mediapipe_lib",
srcs = glob(["*.java"]),
//assets文件
assets = [
":binary_graph",
"//mediapipe/models:face_detection_front.tflite",
"//mediapipe/models:face_detection_front_labelmap.txt",
],
assets_dir = "",
//指定AndroidManifest
manifest = "AndroidManifest.xml",
resource_files = glob(["res/**"]),
//依赖的第三方库
deps = [
":mediapipe_jni_lib",
"//mediapipe/java/com/google/mediapipe/components:android_camerax_helper",
"//mediapipe/java/com/google/mediapipe/components:android_components",
"//mediapipe/java/com/google/mediapipe/framework:android_framework",
"//mediapipe/java/com/google/mediapipe/glutil",
"//third_party:androidx_appcompat",
"//third_party:androidx_constraint_layout",
"//third_party:androidx_legacy_support_v4",
"//third_party:androidx_recyclerview",
"//third_party:opencv",
"@androidx_concurrent_futures//jar",
"@androidx_lifecycle//jar",
"@com_google_code_findbugs//jar",
"@com_google_guava_android//jar",
],
)
//编译application
android_binary(
name = "facedetectiongpu",
manifest = "AndroidManifest.xml",
//applicationId
manifest_values = {"applicationId": "com.google.mediapipe.apps.facedetectiongpu"},
multidex = "native",
//依赖库
deps = [
":mediapipe_lib",
],
)
其实仔细看一下,很容易就可以看懂。
编写完这些之后,还需要配置编译命令,
Bazel Command.png
然后需要配置命令
Bazel Command.png
这里面facedetectiongpu:facedetectiongpu,[文件名:执行的编译命名],mobile-install是安装命令,有run和build等其他命令。编译成功后,可以在下面目录找到安装文件
apk.png
接下来,如何封装一个第三方库供外部使用,这里需要注意的mediapipe已经提供了aar生成的脚本命令mediapipe_aar的命令。
那么我新建一个简单的文件夹以及一个Workspace文件
load("//mediapipe/java/com/google/mediapipe:mediapipe_aar.bzl", "mediapipe_aar")
mediapipe_aar(
name = "mp_face_detection_aar",
calculators = ["//mediapipe/graphs/face_detection:mobile_calculators"],
assets = [
"//mediapipe/models:face_detection_front.tflite",
"//mediapipe/models:face_detection_front_labelmap.txt",
],
)
我们查看mediapipe_aar文件的定义,自己阅读其实不难发现也是声明一下文件编译的流程,有android开发的经验,基本是能读懂命令的涵盖文件的。
这里原来的命令是不带有assets编译进去的,这里我修改了一下mediapipe_aar将tflite文件加入到aar当中一起打包。
assest.png Opengl Android组件化