diff --git a/mediapipe/examples/android/solutions/posetracking-camera/src/main/java/com/google/mediapipe/examples/posetracking_camera/MainActivity.java b/mediapipe/examples/android/solutions/posetracking-camera/src/main/java/com/google/mediapipe/examples/posetracking_camera/MainActivity.java index e4d196e86..7042386c3 100644 --- a/mediapipe/examples/android/solutions/posetracking-camera/src/main/java/com/google/mediapipe/examples/posetracking_camera/MainActivity.java +++ b/mediapipe/examples/android/solutions/posetracking-camera/src/main/java/com/google/mediapipe/examples/posetracking_camera/MainActivity.java @@ -123,9 +123,9 @@ public class MainActivity extends AppCompatActivity { glSurfaceView.post(this::startCamera); // Updates the preview layout. - FrameLayout frameLayout = findViewById(R.id.preview_display_layout); - frameLayout.removeAllViewsInLayout(); - frameLayout.addView(glSurfaceView); + FrameLayout frameLayout = findViewById(R.id.preview_display_layout); + frameLayout.removeAllViewsInLayout(); + frameLayout.addView(glSurfaceView); glSurfaceView.setVisibility(View.VISIBLE); frameLayout.requestLayout(); } diff --git a/mediapipe/examples/android/solutions/posetracking-lindera/build.gradle b/mediapipe/examples/android/solutions/posetracking-lindera/build.gradle new file mode 100644 index 000000000..3e2cefdf7 --- /dev/null +++ b/mediapipe/examples/android/solutions/posetracking-lindera/build.gradle @@ -0,0 +1,57 @@ +plugins { + id 'com.android.application' +} + +android { + compileSdkVersion 30 + buildToolsVersion "30.0.3" + + defaultConfig { + applicationId "com.google.mediapipe.apps.posetracking_camera" + minSdkVersion 21 + targetSdkVersion 30 + versionCode 1 + versionName "1.0" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } +} + +dependencies { + // Copper Labs AAR Files + implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) + + // App Dependencies + implementation 'androidx.appcompat:appcompat:1.3.0' + implementation 'com.google.android.material:material:1.3.0' + implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + implementation 'androidx.exifinterface:exifinterface:1.3.3' + testImplementation 'junit:junit:4.+' + androidTestImplementation 'androidx.test.ext:junit:1.1.2' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + + // Mediapipe dependencies + implementation 'com.google.protobuf:protobuf-javalite:3.19.1' + implementation 'com.google.flogger:flogger:latest.release' + implementation 'com.google.flogger:flogger-system-backend:latest.release' + implementation 'com.google.code.findbugs:jsr305:latest.release' + implementation 'com.google.guava:guava:27.0.1-android' + + // CameraX core library + def camerax_version = "1.0.0-beta10" + implementation "androidx.camera:camera-core:$camerax_version" + implementation "androidx.camera:camera-camera2:$camerax_version" + implementation "androidx.camera:camera-lifecycle:$camerax_version" + // We cannot use official solution as it is missing dependencies for pose tracking. +// implementation 'com.google.mediapipe:solution-core:latest.release' + +} diff --git a/mediapipe/examples/android/solutions/posetracking-lindera/build_aar.sh b/mediapipe/examples/android/solutions/posetracking-lindera/build_aar.sh new file mode 100644 index 000000000..23d19d081 --- /dev/null +++ b/mediapipe/examples/android/solutions/posetracking-lindera/build_aar.sh @@ -0,0 +1,32 @@ +POSE_TRACKING_OUTPUT_DIR=bazel-bin/mediapipe/java/com/google/mediapipe/solutions/posetracking +GRADLE_LIBS_DIR=mediapipe/examples/android/solutions/posetracking-camera/libs +# +bazel build -c opt --strip=ALWAYS\ + --host_crosstool_top=@bazel_tools//tools/cpp:toolchain \ + --fat_apk_cpu=arm64-v8a,armeabi-v7a \ + --legacy_whole_archive=0 \ + --features=-legacy_whole_archive \ + --copt=-fvisibility=hidden \ + --copt=-ffunction-sections \ + --copt=-fdata-sections \ + --copt=-fstack-protector \ + --copt=-Oz \ + --copt=-fomit-frame-pointer \ + --copt=-DABSL_MIN_LOG_LEVEL=2 \ + --linkopt=-Wl,--gc-sections,--strip-all \ + //mediapipe/java/com/google/mediapipe/solutions/posetracking:copperlabs-pose-api.aar \ + //mediapipe/java/com/google/mediapipe/solutions/posetracking:copperlabs-pose-landmark.aar \ + //mediapipe/java/com/google/mediapipe/solutions/posetracking:copperlabs-pose-detection.aar \ + //mediapipe/java/com/google/mediapipe/solutions/posetracking:copperlabs-pose-graph.aar \ + //mediapipe/java/com/google/mediapipe/solutioncore:copperlabs-mediapipe + + +mkdir $GRADLE_LIBS_DIR +rm -f $GRADLE_LIBS_DIR/copperlabs-*.aar + +\cp $POSE_TRACKING_OUTPUT_DIR/copperlabs-pose-api.aar $GRADLE_LIBS_DIR +\cp $POSE_TRACKING_OUTPUT_DIR/copperlabs-pose-detection.aar $GRADLE_LIBS_DIR +\cp $POSE_TRACKING_OUTPUT_DIR/copperlabs-pose-graph.aar $GRADLE_LIBS_DIR +\cp $POSE_TRACKING_OUTPUT_DIR/copperlabs-pose-landmark.aar $GRADLE_LIBS_DIR +\cp bazel-bin/mediapipe/java/com/google/mediapipe/solutioncore/copperlabs-mediapipe.aar $GRADLE_LIBS_DIR + diff --git a/mediapipe/examples/android/solutions/posetracking-lindera/proguard-rules.pro b/mediapipe/examples/android/solutions/posetracking-lindera/proguard-rules.pro new file mode 100644 index 000000000..f1b424510 --- /dev/null +++ b/mediapipe/examples/android/solutions/posetracking-lindera/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/mediapipe/examples/android/solutions/posetracking-lindera/src/main/AndroidManifest.xml b/mediapipe/examples/android/solutions/posetracking-lindera/src/main/AndroidManifest.xml new file mode 100644 index 000000000..4ce4f88c1 --- /dev/null +++ b/mediapipe/examples/android/solutions/posetracking-lindera/src/main/AndroidManifest.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mediapipe/examples/android/solutions/posetracking-lindera/src/main/BUILD b/mediapipe/examples/android/solutions/posetracking-lindera/src/main/BUILD new file mode 100644 index 000000000..3a4971b35 --- /dev/null +++ b/mediapipe/examples/android/solutions/posetracking-lindera/src/main/BUILD @@ -0,0 +1,51 @@ +# Copyright 2021 The MediaPipe Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +licenses(["notice"]) + +package(default_visibility = ["//visibility:private"]) + +android_binary( + name = "posetracking-lindera", + srcs = glob(["**/*.java"]), + custom_package = "com.google.mediapipe.examples.posetracking_lindera", + manifest = "AndroidManifest.xml", + manifest_values = { + "applicationId": "com.google.mediapipe.examples.posetracking_lindera", + }, + multidex = "native", + resource_files = ["//mediapipe/examples/android/solutions:resource_files"], + deps = [ + "//mediapipe/framework/formats:detection_java_proto_lite", + "//mediapipe/framework/formats:landmark_java_proto_lite", + "//mediapipe/framework/formats:location_data_java_proto_lite", + "//mediapipe/java/com/google/mediapipe/solutioncore:camera_input", + "//mediapipe/java/com/google/mediapipe/solutioncore:mediapipe_jni_lib", + "//mediapipe/java/com/google/mediapipe/solutioncore:solution_rendering", + "//mediapipe/java/com/google/mediapipe/solutioncore:video_input", + # "//mediapipe/java/com/google/mediapipe/solutions/posetracking:copperlabs-lindera", + "//mediapipe/java/com/google/mediapipe/solutions/posetracking:copperlabs-lindera-dummpy-interface", + "//mediapipe/java/com/google/mediapipe/solutions/posetracking:copperlabs-pose-api", + "//mediapipe/java/com/google/mediapipe/solutions/posetracking:copperlabs-pose-detection", + "//mediapipe/java/com/google/mediapipe/solutions/posetracking:copperlabs-pose-graph", + "//third_party:androidx_appcompat", + "//third_party:androidx_constraint_layout", + "//third_party:opencv", + "@maven//:androidx_activity_activity", + "@maven//:androidx_concurrent_concurrent_futures", + "@maven//:androidx_exifinterface_exifinterface", + "@maven//:androidx_fragment_fragment", + "@maven//:com_google_guava_guava", + ], +) diff --git a/mediapipe/examples/android/solutions/posetracking-lindera/src/main/java/com/google/mediapipe/examples/posetracking_lindera/ComputerVisionPluginImpl.java b/mediapipe/examples/android/solutions/posetracking-lindera/src/main/java/com/google/mediapipe/examples/posetracking_lindera/ComputerVisionPluginImpl.java new file mode 100644 index 000000000..bd85a70bd --- /dev/null +++ b/mediapipe/examples/android/solutions/posetracking-lindera/src/main/java/com/google/mediapipe/examples/posetracking_lindera/ComputerVisionPluginImpl.java @@ -0,0 +1,7 @@ +package com.google.mediapipe.examples.posetracking_lindera; + +import com.google.mediapipe.solutions.posetracking.ComputerVisionPlugin; + +public class ComputerVisionPluginImpl implements ComputerVisionPlugin { + +} diff --git a/mediapipe/examples/android/solutions/posetracking-lindera/src/main/java/com/google/mediapipe/examples/posetracking_lindera/MainActivity.java b/mediapipe/examples/android/solutions/posetracking-lindera/src/main/java/com/google/mediapipe/examples/posetracking_lindera/MainActivity.java new file mode 100644 index 000000000..731009336 --- /dev/null +++ b/mediapipe/examples/android/solutions/posetracking-lindera/src/main/java/com/google/mediapipe/examples/posetracking_lindera/MainActivity.java @@ -0,0 +1,105 @@ +// Copyright 2021 The MediaPipe Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.mediapipe.examples.posetracking_lindera; + +import android.content.Intent; + +import android.os.Bundle; + +import androidx.appcompat.app.AppCompatActivity; + +import android.os.Handler; +import android.os.Looper; +import android.view.Surface; +import android.view.View; +import android.widget.Button; +import android.widget.FrameLayout; + +import androidx.activity.result.ActivityResultLauncher; + +import com.google.mediapipe.solutions.posetracking.ComputerVisionPlugin; +import com.google.mediapipe.solutions.posetracking.Lindera; +import com.google.mediapipe.solutions.posetracking.PoseTrackingResultGlRenderer; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + + +/** Main activity of MediaPipe Face Detection app. */ +public class MainActivity extends AppCompatActivity { + private static final String TAG = "MainActivity"; + + private Lindera lindera; + private ComputerVisionPlugin plugin; + // Live camera demo UI and camera components. + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + + + disableRedundantUI(); + + setupLiveDemoUiComponents(); + + plugin = new ComputerVisionPluginImpl(); + lindera = new Lindera(plugin); + new PoseTrackingResultGlRenderer(); + } + + + /** Sets up the UI components for the live demo with camera input. */ + private void setupLiveDemoUiComponents() { + + Button startCameraButton = findViewById(R.id.button_start_camera); + FrameLayout frameLayout = findViewById(R.id.preview_display_layout); + + startCameraButton.setOnClickListener( + v -> { + startCameraButton.setVisibility(View.GONE); + + lindera.initialize(frameLayout,MainActivity.this); + + ExecutorService executor = Executors.newSingleThreadExecutor(); + Handler handler = new Handler(Looper.getMainLooper()); + + executor.execute(new Runnable() { + @Override + public void run() { + + //Background work here + + handler.post(new Runnable() { + @Override + public void run() { + //UI Thread work here + } + }); + } + }); + }); + } + /**Disables unecesary UI buttons*/ + private void disableRedundantUI(){ + findViewById(R.id.button_load_picture).setVisibility(View.GONE); + findViewById(R.id.button_load_video).setVisibility(View.GONE); + + } + + +} diff --git a/mediapipe/examples/android/solutions/posetracking-lindera/src/main/res b/mediapipe/examples/android/solutions/posetracking-lindera/src/main/res new file mode 120000 index 000000000..fc8850136 --- /dev/null +++ b/mediapipe/examples/android/solutions/posetracking-lindera/src/main/res @@ -0,0 +1 @@ +../../../res \ No newline at end of file diff --git a/mediapipe/java/com/google/mediapipe/solutions/posetracking/BUILD b/mediapipe/java/com/google/mediapipe/solutions/posetracking/BUILD index b1ad2eb33..579f75310 100644 --- a/mediapipe/java/com/google/mediapipe/solutions/posetracking/BUILD +++ b/mediapipe/java/com/google/mediapipe/solutions/posetracking/BUILD @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. load("//mediapipe/java/com/google/mediapipe/solutions/posetracking:copperlabs_aar.bzl", "copperlabs_aar") +load("@io_bazel_rules_kotlin//kotlin:android.bzl", "kt_android_library") licenses(["notice"]) @@ -20,6 +21,8 @@ POSE_TRACKING_SRCS = [ "PoseTracking.java", "PoseTrackingOptions.java", "PoseTrackingResult.java", + "Lindera.java", + "PoseTrackingResultGlRenderer.java", ] android_library( @@ -29,14 +32,23 @@ android_library( manifest = ":AndroidManifest.xml", visibility = ["//visibility:public"], deps = [ + ":copperlabs-lindera-dummpy-interface", "//mediapipe/framework/formats:detection_java_proto_lite", "//mediapipe/framework/formats:landmark_java_proto_lite", + "//mediapipe/framework/formats:location_data_java_proto_lite", "//mediapipe/java/com/google/mediapipe/framework:android_framework", "//mediapipe/java/com/google/mediapipe/solutioncore:camera_input", "//mediapipe/java/com/google/mediapipe/solutioncore:solution_base", + "//mediapipe/java/com/google/mediapipe/solutioncore:solution_rendering", + "//third_party:androidx_appcompat", + "//third_party:androidx_constraint_layout", "//third_party:autovalue", "@com_google_protobuf//:protobuf_javalite", + "@maven//:androidx_activity_activity", "@maven//:androidx_annotation_annotation", + "@maven//:androidx_concurrent_concurrent_futures", + "@maven//:androidx_exifinterface_exifinterface", + "@maven//:androidx_fragment_fragment", "@maven//:com_google_code_findbugs_jsr305", "@maven//:com_google_guava_guava", ], @@ -80,6 +92,36 @@ android_library( deps = [], ) +#android_library( +# name = "copperlabs-lindera", +# srcs = ["Lindera.java"], +# manifest = "AndroidManifest.xml", +# visibility = ["//visibility:public"], +# deps = [ +# "copperlabs-lindera-dummpy-interface", +# "copperlabs-pose-api", +# "//mediapipe/framework/formats:detection_java_proto_lite", +# "//mediapipe/framework/formats:landmark_java_proto_lite", +# "//mediapipe/java/com/google/mediapipe/framework:android_framework", +# "//mediapipe/java/com/google/mediapipe/solutioncore:camera_input", +# "//mediapipe/java/com/google/mediapipe/solutioncore:solution_base", +# "//mediapipe/java/com/google/mediapipe/solutioncore:solution_rendering", +# "//third_party:androidx_appcompat", +# "//third_party:autovalue", +# "@com_google_protobuf//:protobuf_javalite", +# "@maven//:androidx_annotation_annotation", +# "@maven//:com_google_code_findbugs_jsr305", +# "@maven//:com_google_guava_guava", +# ], +#) + +android_library( + name = "copperlabs-lindera-dummpy-interface", + srcs = ["ComputerVisionPlugin.java"], + manifest = "AndroidManifest.xml", + visibility = ["//visibility:public"], + deps = [], +) #mediapipe_aar( # name = "copperlabs-mediapipe", # calculators = ["//mediapipe/graphs/pose_tracking:pose_tracking_gpu_deps"], diff --git a/mediapipe/java/com/google/mediapipe/solutions/posetracking/ComputerVisionPlugin.java b/mediapipe/java/com/google/mediapipe/solutions/posetracking/ComputerVisionPlugin.java new file mode 100644 index 000000000..48d193adb --- /dev/null +++ b/mediapipe/java/com/google/mediapipe/solutions/posetracking/ComputerVisionPlugin.java @@ -0,0 +1,4 @@ +package com.google.mediapipe.solutions.posetracking; + +public interface ComputerVisionPlugin { +} diff --git a/mediapipe/java/com/google/mediapipe/solutions/posetracking/Lindera.java b/mediapipe/java/com/google/mediapipe/solutions/posetracking/Lindera.java new file mode 100644 index 000000000..b7db95482 --- /dev/null +++ b/mediapipe/java/com/google/mediapipe/solutions/posetracking/Lindera.java @@ -0,0 +1,82 @@ +package com.google.mediapipe.solutions.posetracking; + +import android.util.Log; +import android.view.Surface; +import android.view.View; +import android.view.ViewGroup; + +import androidx.appcompat.app.AppCompatActivity; + +import com.google.mediapipe.solutioncore.CameraInput; +import com.google.mediapipe.solutioncore.SolutionGlSurfaceView; + +public class Lindera { + private ComputerVisionPlugin plugin; + private static final int rotation = Surface.ROTATION_0; + private PoseTracking poseTracking; + + // Live camera demo UI and camera components. + private CameraInput cameraInput; + private SolutionGlSurfaceView glSurfaceView; + + public Lindera(ComputerVisionPlugin plugin){ + this.plugin = plugin; + } + + public void initialize (ViewGroup computerVisionContainerView , AppCompatActivity appCompatActivity){ + setupStreamingModePipeline(computerVisionContainerView,appCompatActivity); + } + /** Sets up core workflow for streaming mode. */ + private void setupStreamingModePipeline(ViewGroup computerVisionContainerView,AppCompatActivity appCompatActivity) { + // Initializes a new MediaPipe Face Detection solution instance in the streaming mode. + poseTracking = + new PoseTracking( + appCompatActivity, + PoseTrackingOptions.builder() + .setStaticImageMode(false) + .setLandmarkVisibility(true) + .setModelComplexity(0) + .setSmoothLandmarks(true) + .build()); + poseTracking.setErrorListener( + (message, e) -> Log.e("Lindera", "MediaPipe Pose Tracking error:" + message)); + cameraInput = new CameraInput(appCompatActivity); + + cameraInput.setNewFrameListener(textureFrame -> poseTracking.send(textureFrame)); + + + // Initializes a new Gl surface view with a user-defined PoseTrackingResultGlRenderer. + glSurfaceView = + new SolutionGlSurfaceView<>( + appCompatActivity, poseTracking.getGlContext(), poseTracking.getGlMajorVersion()); + glSurfaceView.setSolutionResultRenderer(new PoseTrackingResultGlRenderer()); + glSurfaceView.setRenderInputImage(true); + poseTracking.setResultListener( + poseTrackingResult -> { +// logExampleKeypoint(poseTrackingResult); + glSurfaceView.setRenderData(poseTrackingResult); + glSurfaceView.requestRender(); + }); + + // The runnable to start camera after the gl surface view is attached. + // For video input source, videoInput.start() will be called when the video uri is available. + glSurfaceView.post(()->{this.startCamera(appCompatActivity);}); + // Updates the preview layout. + + computerVisionContainerView.removeAllViewsInLayout(); + computerVisionContainerView.addView(glSurfaceView); + glSurfaceView.setVisibility(View.VISIBLE); + computerVisionContainerView.requestLayout(); + } + + private void startCamera(AppCompatActivity appCompatActivity) { + cameraInput.getConverter(poseTracking.getGlContext()).setRotation(rotation); + cameraInput.start( + appCompatActivity, + poseTracking.getGlContext(), + CameraInput.CameraFacing.FRONT, + glSurfaceView.getWidth(), + glSurfaceView.getHeight()); + } + +} diff --git a/mediapipe/examples/android/solutions/posetracking-camera/src/main/java/com/google/mediapipe/examples/posetracking_camera/PoseTrackingResultGlRenderer.java b/mediapipe/java/com/google/mediapipe/solutions/posetracking/PoseTrackingResultGlRenderer.java similarity index 97% rename from mediapipe/examples/android/solutions/posetracking-camera/src/main/java/com/google/mediapipe/examples/posetracking_camera/PoseTrackingResultGlRenderer.java rename to mediapipe/java/com/google/mediapipe/solutions/posetracking/PoseTrackingResultGlRenderer.java index 3b4a788f4..23aaa0904 100644 --- a/mediapipe/examples/android/solutions/posetracking-camera/src/main/java/com/google/mediapipe/examples/posetracking_camera/PoseTrackingResultGlRenderer.java +++ b/mediapipe/java/com/google/mediapipe/solutions/posetracking/PoseTrackingResultGlRenderer.java @@ -12,18 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.mediapipe.examples.posetracking_camera; +package com.google.mediapipe.solutions.posetracking; import android.opengl.GLES20; import com.google.mediapipe.formats.proto.DetectionProto.Detection; import com.google.mediapipe.solutioncore.ResultGlRenderer; -import com.google.mediapipe.solutions.posetracking.PoseTrackingResult; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; +; + /** A custom implementation of {@link ResultGlRenderer} to render {@link PoseTrackingResult}. */ public class PoseTrackingResultGlRenderer implements ResultGlRenderer { private static final String TAG = "PoseTrackingResultGlRenderer";