Mediapipe 안드로이드용 App 빌드하기

2022. 8. 21. 22:16안드로이드 개발

https://github.com/google/mediapipe

 

GitHub - google/mediapipe: Cross-platform, customizable ML solutions for live and streaming media.

Cross-platform, customizable ML solutions for live and streaming media. - GitHub - google/mediapipe: Cross-platform, customizable ML solutions for live and streaming media.

github.com

MediaPipe는 Pose Detection을 PC 뿐만 아니라 모바일 (Android, iOS)도 지원이 된다고 하기에, 큰 차이 없이 쉽게 구현이 가능할 것이라고 생각했었으나, Python으로 구현한 것을 Android로 변환하는 것은 시작부터 큰 난관에 봉착하여 여기에 기록을 남겨놓는다. 하도 많은 삽질을 해서 그새 까먹은 것도 있지만, 일단 기억나는대로...

https://google.github.io/mediapipe/solutions/pose.html

 

Pose

Cross-platform, customizable ML solutions for live and streaming media.

google.github.io

 

처음에 기술 검토할때에는 Solution APIs를 이용한 예제만 확인했기에, Pose Detection도 이처럼 쉬울수 있을 것이라고 짐작을 했다.그러나, 나중에 살펴보니 Face Detection, Face Mesh, Hands만 Solution APIs를 지원하고 Pose Detection은 bazel을 이용하여 console에서 빌드를 해야했다.

https://google.github.io/mediapipe/getting_started/android_solutions.html

 

MediaPipe Android Solutions

Cross-platform, customizable ML solutions for live and streaming media.

google.github.io

그래서 처음부터 다시 Bazel에서 안드로이드용 App을 빌드할 수 있는 환경 설정 부터 다시 해야했다.

(1) 당연히 Xcode와 Homebrew는 기본이고 추가적으로 Bazel, OpenCV, Python3 를 설치하고, C++ 예제가 제대로 실행되는지 테스트 해본다.

$ export GLOG_logtostderr=1
# Need bazel flag 'MEDIAPIPE_DISABLE_GPU=1' as desktop GPU is currently not supported
$ bazel run --define MEDIAPIPE_DISABLE_GPU=1 \
    mediapipe/examples/desktop/hello_world:hello_world

https://google.github.io/mediapipe/getting_started/install.html#installing-on-macos

 

Installation

Cross-platform, customizable ML solutions for live and streaming media.

google.github.io

(2) 본인의 로컬 환경에 맞게 ANDROID_HOME과 ANDROID_NDK_HOME을 지정하고 Mediapipe 루트 폴더에 있는 WORKSPACE에 android_sdk_repository와 android_ndk_repository를 추가해준다.

export ANDROID_HOME=/Users/kumhojeong/Library/Android/sdk
export ANDROID_NDK_HOME=/Users/kumhojeong/Library/Android/sdk/ndk/21.4.7075529
echo $ANDROID_HOME
/Users/kumhojeong/Library/Android/sdk

echo $ANDROID_NDK_HOME
/Users/kumhojeong/Library/Android/sdk/ndk/21.4.7075529
echo "android_sdk_repository(name = \"androidsdk\")" >> WORKSPACE
echo "android_ndk_repository(name = \"androidndk\", api_level=21)" >> WORKSPACE

생각보다 App 빌드는 어렵지 않게 성공한다.

bazel build -c opt --config=android_arm64 mediapipe/examples/android/src/java/com/google/mediapipe/apps/handtrackinggpu:handtrackinggpu

빌드한 APK 파일을 adb 유틸을 이용하여 단말기에 설치해서 테스트해보면 된다.

/Users/kumhojeong/Library/Android/sdk/platform-tools/adb install bazel-bin/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackinggpu/posetrackinggpu.apk

https://google.github.io/mediapipe/getting_started/android.html

 

MediaPipe on Android

Cross-platform, customizable ML solutions for live and streaming media.

google.github.io

(3) 기본 프로젝트를 다음 문서를 따라서 빌드하고 실행하면 된다.

bazel build -c opt --config=android_arm64 mediapipe/examples/android/src/java/com/google/mediapipe/apps/basic:helloworld

https://google.github.io/mediapipe/getting_started/hello_world_android.html

 

Hello World! on Android

Cross-platform, customizable ML solutions for live and streaming media.

google.github.io

(4) Bazel 빌드가 아닌, Android Studio에서 직접 빌드하고 실행하도록 시도를 해보았다. Mediapipe의 개발 문서에서는 Android Studio 상의 빌드 및 실행에 대한 레퍼런스는 없지만 기본 프로젝트의 경우에는 동일한 결과를 만들어낼 수 있었다.

Solution APIs를 사용하도록 만들어진 facedetection 예제를 Basic BUILD 프로젝트를 참조해서 수정해서 Android Studio에서 빌드할 수 있도록 만들었다. Console에서 Bazel로 빌드한 mobile_gpu.binarypb 파일은 assets 폴더에, libmediapipe_jni.so 파일은 jniLibs 폴더에 복사해넣었다.

bazel build -c opt --strip=ALWAYS --host_crosstool_top=@bazel_tools//tools/cpp:toolchain     --fat_apk_cpu=arm64-v8a,armeabi-v7a mediapipe/graphs/edge_detection:mobile_gpu_binary_graph
bazel build mediapipe/examples/android/src/java/com/google/mediapipe/apps/basic:mediapipe_jni_lib -c opt --config=android_arm64

Build.gradle의 externalNativeBuild 관련 항목은 다음 프로젝트의 build.gradle의 내용을 참조하였다.

https://github.com/jnfran92/NativeTongue/blob/master/app/build.gradle

https://github.com/jnfran92/NativeTongue/tree/master/app/src/main/cpp

libopenvc_java3.so 파일은 다음에서 다운 받았다.

https://github.com/joaopedronardari/OpenCV-AndroidSamples/blob/master/app/src/main/jniLibs/arm64-v8a/libopencv_java3.so

* 남은 이슈

Basic 프로젝트의 libmediapipe_jni.so 파일을 Console에서 Bazel로 빌드를 하면 생성된 so 파일을 Android Studio 프로젝트에 포함시킨 다음, App 실행시 동적으로 로딩이 가능해서 오류 없이 동일하게 실행이 가능하다.

cc_binary(
    name = "libmediapipe_jni.so",
    linkshared = 1,
    linkstatic = 1,
    deps = [
        "//mediapipe/graphs/edge_detection:mobile_calculators",
        "//mediapipe/java/com/google/mediapipe/framework/jni:mediapipe_framework_jni",
    ],
)

그러나, posetrackinggpu 프로젝트의 BUILD에 있는대로 libmediapipe.jni.so 파일을 빌드하면 300메가가 넘는 큰 so 파일이 생성되는데, 이 파일의 경우에는 동적 로딩시에 에러가 발생한다!

cc_binary(
    name = "libmediapipe_jni.so",
    linkshared = 1,
    linkstatic = 1,
    deps = [
        "//mediapipe/graphs/pose_tracking:pose_tracking_gpu_deps",
        "//mediapipe/java/com/google/mediapipe/framework/jni:mediapipe_framework_jni",
    ],
)

그래서 참조하고 있는 pose_tracking BUILD 파일을 열어보니 다음과 같이 4개의 폴더를 참고하도록 되어 있다. 이들 참조 폴더를 하나씩 나눠서 빌드하고 로딩하도록 테스트를 해봤는데, 앞에 3개는 문제 없이 로딩이 되지만 가장 마지막에 있는 "pose_landmark_gpu"만이 Android Studio에서 동적 로딩이 불가능했다.

cc_library(
    name = "pose_tracking_gpu_deps",
    deps = [
        "//mediapipe/calculators/core:constant_side_packet_calculator",
        "//mediapipe/calculators/core:flow_limiter_calculator",
        "//mediapipe/graphs/pose_tracking/subgraphs:pose_renderer_gpu",
        "//mediapipe/modules/pose_landmark:pose_landmark_gpu",
    ],
)

https://github.com/google/mediapipe/blob/master/mediapipe/graphs/pose_tracking/BUILD

당연히, Console에서 Bazel을 이용하여 Pose tracker 프로젝트를 빌드하여 APK를 생성하고 실행하는 것은 정상적으로 가능하다. 따라서 현재로서는 Pose Detection 응용 프로그램은 Bazel로만 빌드가 가능하다고 판단되며, Android Studio를 이용한 빌드는 불가능하다고 본다. 개발은 Android Studio로 하지만, 빌드는 Console에서 해야하는 상황인것이다.

bazel build -c opt --config=android_arm64 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackinggpu:posetrackinggpu

/Users/kumhojeong/Library/Android/sdk/platform-tools/adb install bazel-bin/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackinggpu/posetrackinggpu.apk

 

<기타 참고 자료>

https://codechacha.com/ko/how-to-add-so-libraries-in-android-studio/

 

안드로이드 스튜디오에서 so 라이브러리를 추가하는 방법

Android Studio 프로젝트에 네이티브 라이브러리인 so 라이브러리를 추가하는 방법과, Apk에 라이브러리가 포함되었는지 확인하는 방법을 알아보겠습니다. 프로젝트에 포함시키려면 jniLibs 폴더 아래

codechacha.com

https://docs.bazel.build/versions/main/tutorial/cpp.html

 

Build Tutorial - C++ - Bazel main

Bazel Tutorial: Build a C++ Project This tutorial covers the basics of building C++ applications with Bazel. You will set up your workspace and build a simple C++ project that illustrates key Bazel concepts, such as targets and BUILD files. After completin

docs.bazel.build

https://developer.android.com/training/articles/perf-jni

 

JNI 도움말  |  Android NDK  |  Android Developers

JNI 도움말 JNI는 Java Native Interface(자바 네이티브 인터페이스)의 약어입니다. JNI는 Android가 관리 코드에서 컴파일하는 바이트 코드(자바 또는 Kotlin 프로그래밍 언어로 작성됨)와 네이티브 코드(C/C+

developer.android.com

https://docs.bazel.build/versions/0.19.1/android-ndk.html

 

Using the Android Native Development Kit with Bazel - Bazel 0.19.1

Using the Android Native Development Kit with Bazel If you’re new to Bazel, please start with the Building Android with Bazel tutorial. Table of contents Overview Bazel can run in many different build configurations, including several that use the Androi

docs.bazel.build

https://bazel.build/reference/be/c-cpp

 

C / C++ 규칙  |  Bazel

이 페이지는 Cloud Translation API를 통해 번역되었습니다. Switch to English C / C++ 규칙 규칙 cc_binary cc_binary(name, deps, srcs, data, additional_linker_inputs, args, compatible_with, copts, defines, deprecation, distribs, env, exec_co

bazel.build

 

<오류 관련 참고자료>

https://github.com/google/mediapipe/issues/1450

 

Not found: ValidatedGraphConfig Initialization failed.When I use handtrackinggpu.aar for Android,print:No registered calcula

I build hand tracking aar or handTrackingGpu.aar,use it in Android error,print: MediaPipeException: not found: ValidatedGraphConfig Initialization failed. No registered object with name: HandLandma...

github.com

https://github.com/google/mediapipe/issues/2788

 

[Android] Custom / Build pose_tracking have no effect · Issue #2788 · google/mediapipe

System information Linux Ubuntu 18.04 Bazel version: Bazelisk version: v1.10.1 Build label: 3.7.2 Solution : Pose Programming Language and version : Java Gradle Archetype used : https://github.com/...

github.com

https://github.com/ezored/ezored/issues/23

 

Android: dlopen failed: library "libc++_shared.so" not found · Issue #23 · ezored/ezored

Describe the bug After building the aar file and import it into a project I get the error: dlopen failed: library "libc++_shared.so" not found To Reproduce Do exactly like on the HOW-TO-U...

github.com

https://github.com/google/mediapipe/issues/1779

 

Bazel Build Error · Issue #1779 · google/mediapipe

while building the bazel project i got this error, can someone help us in this Error:/home/laukik/IntelliJIDEAProjects/mediapipe/WORKSPACE:247:23: //external:android/sdk depends on @androidsdk//:sd...

github.com

https://www.reddit.com/r/androiddev/comments/am4hpc/fatal_error_jnih_file_not_found/

 

fatal error: 'jni.h' file not found

I am trying to build this share library for I can use my methods in Java. I am sorry if this is the wrong forum, but since this is basically a...

www.reddit.com

https://stackoverflow.com/questions/46160790/bazel-for-jni-jni-h-file-not-found

 

bazel for jni: jni.h file not found

I'm trying to use bazel to build my JNI library (written in C). No luck after about 4 hours: "jni.h file not found". How can I put the JDK include directories on the search path? Tried using abs...

stackoverflow.com

https://stackoverflow.com/questions/53514630/bazel-c-create-and-link-with-shared-library

 

bazel c++ create and link with shared library

I will base my question on stage 2 from the bazel tutorial for c++. Normally this example will create hello-world linked statically with libhello-greet.a. However I would like to create hello-world

stackoverflow.com