From 6417c0abe0818d9f0fc9afaab994804a103b12dd Mon Sep 17 00:00:00 2001 From: Mautisim Munir Date: Sun, 25 Sep 2022 18:29:58 +0500 Subject: [PATCH] added posetracking solution api - wip --- .../AndroidManifest.xml | 40 +++++ .../apps/posetrackingsolutiongpu/BUILD | 95 +++++++++++ .../FaceDetectionResultImageView.java | 110 +++++++++++++ .../posetrackingsolutiongpu/MainActivity.java | 151 ++++++++++++++++++ .../PoseTrackingResultGlRenderer.java | 147 +++++++++++++++++ .../drawable-v24/ic_launcher_foreground.xml | 34 ++++ .../res/drawable/ic_launcher_background.xml | 74 +++++++++ .../res/layout/activity_main.xml | 20 +++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1354 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 2257 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 3246 bytes .../res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 959 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 900 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 1955 bytes .../res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 1971 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 1845 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 4658 bytes .../res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 3562 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 5655 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 7745 bytes .../res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 5004 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 8278 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 11062 bytes .../res/values/colors.xml | 6 + .../res/values/strings.xml | 3 + .../res/values/styles.xml | 11 ++ .../pose_tracking/pose_tracking_gpu.pbtxt | 15 +- .../posetracking/AndroidManifest.xml | 8 + .../mediapipe/solutions/posetracking/BUILD | 50 ++++++ .../posetracking/PersonKeypoint.java | 42 +++++ .../solutions/posetracking/PoseTracking.java | 106 ++++++++++++ .../posetracking/PoseTrackingOptions.java | 61 +++++++ .../posetracking/PoseTrackingResult.java | 65 ++++++++ 35 files changed, 1047 insertions(+), 1 deletion(-) create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/AndroidManifest.xml create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/BUILD create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/FaceDetectionResultImageView.java create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/MainActivity.java create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/PoseTrackingResultGlRenderer.java create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/drawable/ic_launcher_background.xml create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/layout/activity_main.xml create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-hdpi/ic_launcher.png create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-mdpi/ic_launcher.png create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xhdpi/ic_launcher.png create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/values/colors.xml create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/values/strings.xml create mode 100644 mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/values/styles.xml create mode 100644 mediapipe/java/com/google/mediapipe/solutions/posetracking/AndroidManifest.xml create mode 100644 mediapipe/java/com/google/mediapipe/solutions/posetracking/BUILD create mode 100644 mediapipe/java/com/google/mediapipe/solutions/posetracking/PersonKeypoint.java create mode 100644 mediapipe/java/com/google/mediapipe/solutions/posetracking/PoseTracking.java create mode 100644 mediapipe/java/com/google/mediapipe/solutions/posetracking/PoseTrackingOptions.java create mode 100644 mediapipe/java/com/google/mediapipe/solutions/posetracking/PoseTrackingResult.java diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/AndroidManifest.xml b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/AndroidManifest.xml new file mode 100644 index 000000000..b61304f0d --- /dev/null +++ b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/AndroidManifest.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/BUILD b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/BUILD new file mode 100644 index 000000000..689e8babe --- /dev/null +++ b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/BUILD @@ -0,0 +1,95 @@ +# Copyright 2019 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"]) + +# Basic library common across example apps. +android_library( + name = "basic_lib", + srcs = glob(["*.java"]), + manifest = "AndroidManifest.xml", + resource_files = glob(["res/**"]), + visibility = ["//visibility:public"], + deps = [ + "//mediapipe/framework/formats:detection_java_proto_lite", + "//mediapipe/framework/formats:location_data_java_proto_lite", + "//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", + "//mediapipe/java/com/google/mediapipe/solutioncore:camera_input", + "//mediapipe/java/com/google/mediapipe/solutioncore:solution_rendering", + "//mediapipe/java/com/google/mediapipe/solutions/facedetection", + "//mediapipe/java/com/google/mediapipe/solutions/posetracking", + "//third_party:androidx_appcompat", + "//third_party:androidx_constraint_layout", + "//third_party:opencv", + "@maven//:androidx_concurrent_concurrent_futures", + "@maven//:com_google_guava_guava", + ], +) + +# Manifest common across example apps. +exports_files( + srcs = ["AndroidManifest.xml"], +) + +# Native dependencies to perform edge detection in the Hello World example. +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", + #facedetection deps + "//mediapipe/graphs/face_detection:face_detection_full_range_mobile_gpu_deps", + "//mediapipe/graphs/face_detection:mobile_calculators", + #pose tracking deps + "//mediapipe/graphs/pose_tracking:pose_tracking_gpu_deps", + ], +) + +# Converts the .so cc_binary into a cc_library, to be consumed in an android_binary. +cc_library( + name = "mediapipe_jni_lib", + srcs = [":libmediapipe_jni.so"], + alwayslink = 1, +) + +# Hello World example app. +android_binary( + name = "helloworld", + # assets = [ + # "//mediapipe/graphs/edge_detection:mobile_gpu.binarypb", + # ], + # assets_dir = "", + manifest = "AndroidManifest.xml", + manifest_values = { + "applicationId": "com.google.mediapipe.apps.posetrackingsolutiongpu", + "appName": "Hello World", + "mainActivity": ".MainActivity", + # "cameraFacingFront": "False", + # "binaryGraphName": "mobile_gpu.binarypb", + # "inputVideoStreamName": "input_video", + # "outputVideoStreamName": "output_video", + # "flipFramesVertically": "True", + # "converterNumBuffers": "2", + }, + multidex = "native", + deps = [ + ":basic_lib", + ":mediapipe_jni_lib", + ], +) diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/FaceDetectionResultImageView.java b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/FaceDetectionResultImageView.java new file mode 100644 index 000000000..c22c732b2 --- /dev/null +++ b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/FaceDetectionResultImageView.java @@ -0,0 +1,110 @@ +// 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.apps.posetrackingsolutiongpu; + +import static java.lang.Math.min; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; + +import androidx.appcompat.widget.AppCompatImageView; + +import com.google.mediapipe.formats.proto.DetectionProto.Detection; +import com.google.mediapipe.solutions.facedetection.FaceDetectionResult; +import com.google.mediapipe.solutions.facedetection.FaceKeypoint; + +/** An ImageView implementation for displaying {@link FaceDetectionResult}. */ +public class FaceDetectionResultImageView extends AppCompatImageView { + private static final String TAG = "FaceDetectionResultImageView"; + + private static final int KEYPOINT_COLOR = Color.RED; + private static final int KEYPOINT_RADIUS = 8; // Pixels + private static final int BBOX_COLOR = Color.GREEN; + private static final int BBOX_THICKNESS = 5; // Pixels + private Bitmap latest; + + public FaceDetectionResultImageView(Context context) { + super(context); + setScaleType(ScaleType.FIT_CENTER); + } + + /** + * Sets a {@link FaceDetectionResult} to render. + * + * @param result a {@link FaceDetectionResult} object that contains the solution outputs and the + * input {@link Bitmap}. + */ + public void setFaceDetectionResult(FaceDetectionResult result) { + if (result == null) { + return; + } + Bitmap bmInput = result.inputBitmap(); + int width = bmInput.getWidth(); + int height = bmInput.getHeight(); + latest = Bitmap.createBitmap(width, height, bmInput.getConfig()); + Canvas canvas = new Canvas(latest); + + canvas.drawBitmap(bmInput, new Matrix(), null); + int numDetectedFaces = result.multiFaceDetections().size(); + for (int i = 0; i < numDetectedFaces; ++i) { + drawDetectionOnCanvas(result.multiFaceDetections().get(i), canvas, width, height); + } + } + + /** Updates the image view with the latest {@link FaceDetectionResult}. */ + public void update() { + postInvalidate(); + if (latest != null) { + setImageBitmap(latest); + } + } + + private void drawDetectionOnCanvas(Detection detection, Canvas canvas, int width, int height) { + if (!detection.hasLocationData()) { + return; + } + // Draw keypoints. + Paint keypointPaint = new Paint(); + keypointPaint.setColor(KEYPOINT_COLOR); + for (int i = 0; i < FaceKeypoint.NUM_KEY_POINTS; ++i) { + int xPixel = + min( + (int) (detection.getLocationData().getRelativeKeypoints(i).getX() * width), + width - 1); + int yPixel = + min( + (int) (detection.getLocationData().getRelativeKeypoints(i).getY() * height), + height - 1); + canvas.drawCircle(xPixel, yPixel, KEYPOINT_RADIUS, keypointPaint); + } + if (!detection.getLocationData().hasRelativeBoundingBox()) { + return; + } + // Draw bounding box. + Paint bboxPaint = new Paint(); + bboxPaint.setColor(BBOX_COLOR); + bboxPaint.setStyle(Paint.Style.STROKE); + bboxPaint.setStrokeWidth(BBOX_THICKNESS); + float left = detection.getLocationData().getRelativeBoundingBox().getXmin() * width; + float top = detection.getLocationData().getRelativeBoundingBox().getYmin() * height; + float right = left + detection.getLocationData().getRelativeBoundingBox().getWidth() * width; + float bottom = top + detection.getLocationData().getRelativeBoundingBox().getHeight() * height; + canvas.drawRect(left, top, right, bottom, bboxPaint); + } +} diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/MainActivity.java b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/MainActivity.java new file mode 100644 index 000000000..5c3545283 --- /dev/null +++ b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/MainActivity.java @@ -0,0 +1,151 @@ +// Copyright 2019 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.apps.posetrackingsolutiongpu; + +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.graphics.SurfaceTexture; +import android.os.Bundle; +import androidx.appcompat.app.AppCompatActivity; +import android.util.Log; +import android.util.Size; +import android.view.SurfaceHolder; +import android.view.SurfaceView; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import com.google.mediapipe.components.CameraHelper; +import com.google.mediapipe.components.CameraXPreviewHelper; +import com.google.mediapipe.components.ExternalTextureConverter; +import com.google.mediapipe.components.FrameProcessor; +import com.google.mediapipe.components.PermissionHelper; +import com.google.mediapipe.formats.proto.LocationDataProto; +import com.google.mediapipe.framework.AndroidAssetUtil; +import com.google.mediapipe.glutil.EglManager; +import com.google.mediapipe.solutioncore.CameraInput; +import com.google.mediapipe.solutioncore.SolutionGlSurfaceView; +import com.google.mediapipe.solutions.facedetection.FaceDetection; +import com.google.mediapipe.solutions.facedetection.FaceDetectionOptions; +import com.google.mediapipe.solutions.posetracking.PoseTracking; +import com.google.mediapipe.solutions.posetracking.PoseTrackingOptions; +import com.google.mediapipe.solutions.posetracking.PoseTrackingResult; + +import java.util.ArrayList; + + +/** Main activity of MediaPipe basic app. */ +public class MainActivity extends AppCompatActivity { + private static final String TAG = "MainActivity"; + + // Flips the camera-preview frames vertically by default, before sending them into FrameProcessor + // to be processed in a MediaPipe graph, and flips the processed frames back when they are + // displayed. This maybe needed because OpenGL represents images assuming the image origin is at + // the bottom-left corner, whereas MediaPipe in general assumes the image origin is at the + // top-left corner. + // NOTE: use "flipFramesVertically" in manifest metadata to override this behavior. + private static final boolean FLIP_FRAMES_VERTICALLY = true; + + // Number of output frames allocated in ExternalTextureConverter. + // NOTE: use "converterNumBuffers" in manifest metadata to override number of buffers. For + // example, when there is a FlowLimiterCalculator in the graph, number of buffers should be at + // least `max_in_flight + max_in_queue + 1` (where max_in_flight and max_in_queue are used in + // FlowLimiterCalculator options). That's because we need buffers for all the frames that are in + // flight/queue plus one for the next frame from the camera. + private static final int NUM_BUFFERS = 2; + + static { + // Load all native libraries needed by the app. + System.loadLibrary("mediapipe_jni"); + try { + System.loadLibrary("opencv_java3"); + } catch (java.lang.UnsatisfiedLinkError e) { + // Some example apps (e.g. template matching) require OpenCV 4. + System.loadLibrary("opencv_java4"); + } + } + + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(getContentViewLayoutResId()); + + PoseTrackingOptions poseTrackingOptions = PoseTrackingOptions.builder() + .setStaticImageMode(false).build(); + PoseTracking poseTracking = new PoseTracking(this,poseTrackingOptions); + + poseTracking.setErrorListener( + (message, e) -> Log.e(TAG, "MediaPipe Face Detection error:" + message)); + CameraInput cameraInput = new CameraInput(this); + + + cameraInput.setNewFrameListener( + textureFrame -> poseTracking.send(textureFrame)); + SolutionGlSurfaceView glSurfaceView = + new SolutionGlSurfaceView<>( + this, poseTracking.getGlContext(), poseTracking.getGlMajorVersion()); + glSurfaceView.setSolutionResultRenderer(new PoseTrackingResultGlRenderer()); + glSurfaceView.setRenderInputImage(true); + + poseTracking.setResultListener( + faceDetectionResult -> { + if (faceDetectionResult.multiPoseTrackings().isEmpty()) { + return; + } + LocationDataProto.LocationData locationData = faceDetectionResult + .multiPoseTrackings() + .get(0) + .getLocationData(); +// .getRelativeKeypoints(FaceKeypoint.NOSE_TIP); + Log.i( + TAG, locationData.toString()); +// String.format( +// "MediaPipe Face Detection nose tip normalized coordinates (value range: [0, 1]): x=%f, y=%f", +// noseTip.getX(), noseTip.getY())); + // Request GL rendering. + glSurfaceView.setRenderData(faceDetectionResult); + glSurfaceView.requestRender(); + }); + // The runnable to start camera after the GLSurfaceView is attached. + glSurfaceView.post( + () -> + cameraInput.start( + this, + poseTracking.getGlContext(), + CameraInput.CameraFacing.FRONT, + glSurfaceView.getWidth(), + glSurfaceView.getHeight())); + glSurfaceView.setVisibility(View.VISIBLE); + FrameLayout frameLayout = findViewById(R.id.preview_display_layout); + frameLayout.removeAllViewsInLayout(); + frameLayout.addView(glSurfaceView); + glSurfaceView.setVisibility(View.VISIBLE); + frameLayout.requestLayout(); + } + + + // Used to obtain the content view for this application. If you are extending this class, and + // have a custom layout, override this method and return the custom layout. + protected int getContentViewLayoutResId() { + return R.layout.activity_main; + } + + + + +} diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/PoseTrackingResultGlRenderer.java b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/PoseTrackingResultGlRenderer.java new file mode 100644 index 000000000..e0a4cb25a --- /dev/null +++ b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/PoseTrackingResultGlRenderer.java @@ -0,0 +1,147 @@ +// 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.apps.posetrackingsolutiongpu; + +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"; + + private static final float[] KEYPOINT_COLOR = new float[] {1f, 0f, 0f, 1f}; + private static final float KEYPOINT_SIZE = 16f; + private static final float[] BBOX_COLOR = new float[] {0f, 1f, 0f, 1f}; + private static final int BBOX_THICKNESS = 8; + private static final String VERTEX_SHADER = + "uniform mat4 uProjectionMatrix;\n" + + "uniform float uPointSize;\n" + + "attribute vec4 vPosition;\n" + + "void main() {\n" + + " gl_Position = uProjectionMatrix * vPosition;\n" + + " gl_PointSize = uPointSize;" + + "}"; + private static final String FRAGMENT_SHADER = + "precision mediump float;\n" + + "uniform vec4 uColor;\n" + + "void main() {\n" + + " gl_FragColor = uColor;\n" + + "}"; + private int program; + private int positionHandle; + private int pointSizeHandle; + private int projectionMatrixHandle; + private int colorHandle; + + private int loadShader(int type, String shaderCode) { + int shader = GLES20.glCreateShader(type); + GLES20.glShaderSource(shader, shaderCode); + GLES20.glCompileShader(shader); + return shader; + } + + @Override + public void setupRendering() { + program = GLES20.glCreateProgram(); + int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER); + int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER); + GLES20.glAttachShader(program, vertexShader); + GLES20.glAttachShader(program, fragmentShader); + GLES20.glLinkProgram(program); + positionHandle = GLES20.glGetAttribLocation(program, "vPosition"); + pointSizeHandle = GLES20.glGetUniformLocation(program, "uPointSize"); + projectionMatrixHandle = GLES20.glGetUniformLocation(program, "uProjectionMatrix"); + colorHandle = GLES20.glGetUniformLocation(program, "uColor"); + } + + @Override + public void renderResult(PoseTrackingResult result, float[] projectionMatrix) { + if (result == null) { + return; + } + GLES20.glUseProgram(program); + GLES20.glUniformMatrix4fv(projectionMatrixHandle, 1, false, projectionMatrix, 0); + GLES20.glUniform1f(pointSizeHandle, KEYPOINT_SIZE); + int numDetectedFaces = result.multiPoseTrackings().size(); + for (int i = 0; i < numDetectedFaces; ++i) { + drawDetection(result.multiPoseTrackings().get(i)); + } + } + + /** + * Deletes the shader program. + * + *

This is only necessary if one wants to release the program while keeping the context around. + */ + public void release() { + GLES20.glDeleteProgram(program); + } + + private void drawDetection(Detection detection) { + if (!detection.hasLocationData()) { + return; + } + // Draw keypoints. +// float[] points = new float[FaceKeypoint.NUM_KEY_POINTS * 2]; +// for (int i = 0; i < FaceKeypoint.NUM_KEY_POINTS; ++i) { +// points[2 * i] = detection.getLocationData().getRelativeKeypoints(i).getX(); +// points[2 * i + 1] = detection.getLocationData().getRelativeKeypoints(i).getY(); +// } + GLES20.glUniform4fv(colorHandle, 1, KEYPOINT_COLOR, 0); +// FloatBuffer vertexBuffer = +// ByteBuffer.allocateDirect(points.length * 4) +// .order(ByteOrder.nativeOrder()) +// .asFloatBuffer() +// .put(points); +// vertexBuffer.position(0); + GLES20.glEnableVertexAttribArray(positionHandle); +// GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer); +// GLES20.glDrawArrays(GLES20.GL_POINTS, 0, FaceKeypoint.NUM_KEY_POINTS); + if (!detection.getLocationData().hasRelativeBoundingBox()) { + return; + } + // Draw bounding box. + float left = detection.getLocationData().getRelativeBoundingBox().getXmin(); + float top = detection.getLocationData().getRelativeBoundingBox().getYmin(); + float right = left + detection.getLocationData().getRelativeBoundingBox().getWidth(); + float bottom = top + detection.getLocationData().getRelativeBoundingBox().getHeight(); + drawLine(top, left, top, right); + drawLine(bottom, left, bottom, right); + drawLine(top, left, bottom, left); + drawLine(top, right, bottom, right); + } + + private void drawLine(float y1, float x1, float y2, float x2) { + GLES20.glUniform4fv(colorHandle, 1, BBOX_COLOR, 0); + GLES20.glLineWidth(BBOX_THICKNESS); + float[] vertex = {x1, y1, x2, y2}; + FloatBuffer vertexBuffer = + ByteBuffer.allocateDirect(vertex.length * 4) + .order(ByteOrder.nativeOrder()) + .asFloatBuffer() + .put(vertex); + vertexBuffer.position(0); + GLES20.glEnableVertexAttribArray(positionHandle); + GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer); + GLES20.glDrawArrays(GLES20.GL_LINES, 0, 2); + } +} diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/drawable-v24/ic_launcher_foreground.xml b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 000000000..c7bd21dbd --- /dev/null +++ b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/drawable/ic_launcher_background.xml b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/drawable/ic_launcher_background.xml new file mode 100644 index 000000000..01f0af0ad --- /dev/null +++ b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/drawable/ic_launcher_background.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/layout/activity_main.xml b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/layout/activity_main.xml new file mode 100644 index 000000000..c19d7e628 --- /dev/null +++ b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/layout/activity_main.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-anydpi-v26/ic_launcher.xml b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 000000000..d372a4fca --- /dev/null +++ b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-anydpi-v26/ic_launcher_round.xml b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 000000000..d372a4fca --- /dev/null +++ b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-hdpi/ic_launcher.png b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..920cbf3f197f79b0e6a6013d17b855e916be7d66 GIT binary patch literal 1354 zcmV-Q1-1H#P)SX=nl{G?cQ? zeRQ$4u-(44TamU%t9GIF5ut4;=~_%(-Zn8nq1*b256Al-cBa$WrTb{n&fR;HlbOt% z`#8V7Gjq4=h$4z8q8Pgnk%>trXJVQ!IA)H2c=Nn9;QBrEdQp2|`_qjbdso)C z?^)^nw!%=t#{4WBJ8Xb0bB3f;91DlDUp?9rkQ@!flN2$V{ump}P6?9s`Yby7;|aOZ zs)pNK3A3r7siT*fXx7`D2%t=CtImwPp~B&821$;_+tU6+w5`4C9j(pD05ZMeJGPr! zKz0VGs-9kQ*4bcdDuB$ZYMPzg0)kEUdRno^Q43pB0hIZKv);w^3}S$meYyW@*qRz3 zm#3P4K(@Nn0XYx5`3JP`kN_kA2|)Y+DrozjJi$>q9=b%X zQFXJb^NhEhf`4D5a6|{&lb8OYhim<+4)$?OtAjeItLUIjw2eNL{?K>Akp2%q_!X7G zDl&F+g4VZnt2(8>4624Jax*+dC0%{0&SticV_F^5L0v^>y}w&-Ti+jM?}7!?bKz># zfXBm=RNQ$&)u|pDiPC{=={>FLd>r^K3L?Zd7*uu8Cfe5PU_)eRmcqns}jW(H|ZV<)}Y(L*ozzN0Kx(~R?J4=A1pKmyS0fF7*z(T6?1(gF75!V_*;-8TY| zqVvGP7HT~gqFWIs5YAv9a~zjyAf+{+;?4kFpP1?60MeG;Q^p4L!}%*w1IA%Xm14+yhD^)IhkPU1*0O ztSHt%Olv?0I1zX%kPwg}FhzhW07V2#7g)l;QU;bZu(Y8)pZ0*_i2x)3%?=0)@K}h) zf;?ORv(A}JYe0B)V;cy{uX5l5z)wQNul2ao8W3Lo-O#-eg~yGsgnK}Vyn4p#W4#W% zZ^UlXzEW&J)fzyCeD#dPftbk){`koYn>EP`C5a?2wB03nVR%%ezZf?CMNOa@o;`ue zq9jnAPdtHYZM+1kpaBx7L<*h&BmfCO0?>a6$dLx$YJ4$=Z#ABBH}E@yBA-J&S#D2# z2EFWQ+sFF{b$JzbcgldadVTLtPe(6DaJ+Xu$*ioU56UY)g021i{aML=)SJQNv2_Q% zgP4kPgLY2Dap(S%SLqyLHZF&)N&nG6OG^s?EqQIzrh*r%z8aGD){u0-LozHQ3%jgf zOJ0TZ?1qgSH^9cSva(Dml~Pz(cpuv=W%As+pOsplFWcpPymXg8$GX#(^ZAa}8DiD# zTVtF{MCV?#DIeeITh7J~8(<4;f^GTv`HSZA=L@FX+}y=%o5N%klhsVt7+h9IYG4~kp(tHY{`=DK{0V6qKG1jD26Ei0;e{GZ^QhPyZ`_I M07*qoM6N<$f+3TIaR2}S literal 0 HcmV?d00001 diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-hdpi/ic_launcher_foreground.png b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..7dfa35f78604c7e583f43af36ec3005bc19561f9 GIT binary patch literal 2257 zcmZ`*2{_c<8lM^4kYz;3lKHd~nUsm-4n|oAWmj{{#1~m&2-&6SFEgktW4khvWyX@- zm9$KwED6J88H$i)COf6_{q=p%y|;Ux`#fiT&vVZEzURE>_j?m;ai=B36vZGAh=jQr z_6*q5wklj0Y@aX6DM27`syWukK6H?mYw5GYL7^3zD5^wbVc9otSGvb)Ilqc)2*^Jq zC}U!5rOmKT5n^1}hPs0gC&{&&goTF5R%+I;y}c~+&D`1wq(l$eUXE3>9dx_!a^c5* zuR}ZoT%%5~=lb`1n-80pI&;26h44G{rcUU1Z8wJh7LWL)k$og?EC<610&u7r3>y!T zhN>CI01)ZlFxVJ407pn8VW32kgF%JyBk&%3jowmJCEjj z_vFQx8d4&i8{usbq~||s>pNa|ZiCXE1bb^IBo_t8!pGYbt{{R{X?c+CyZmR6HJ_a1WD1*_9j_llHpZV%4PUI5PjgIGwGM?WD5GuabnCe<2<3GgPZ7~NeEiz>YP0nHMxTR-nHsnV^dE!_#|{d zpEM{5prCf>g}Q_*d>(PrtD?9%36;|1+W9Ul)QXG_j8>{_xGS--EjdjqE3oyll8KZ@ zjDidzQR|y;Zo}&Ej&@C!Qw!R;HDz>QWr(WazZtk^-Z1z<34vuX4+V6&ihCq zVeTWyHsYECwdM0j2$#>t^dBnIpB~zU5oFq8Qj6qOk7~?jcP!A+)^EP!giB}n$9f|trD1BwNr|zHv=zr8|HaHFLO=`^4JaBt8u(#! z?LbJEGYp7PFa#?64hKN0Dfy*_7%OQ&ol|3-!-_0`*+nbai1TC+X9a2Aw|r%a%;BJw zcbsp|-AF&X+*0Nb!(zyj@m>x>J8DGsS`!7Ezs^IX5hirsRSh2wW4du8Da=m_RFGBM z_PmtjSybojky~2a`-wDTcJ$_`zZ+=q+p=znJ_Y*Y-fP{v!Kt&tFYfnlRvx)=YX|1r z=s*4I_#ypT$^((arDrD9jkPZxo32S9S@|YSv-p-TPYFM_UnQ-J@ks0XJI4f=X8TVn z7uVo3uI|0J3xX<@sq<9seOgKt76z=yLRbqSn1#?$-%(vs8x%i;|MMEuFIAPH?P62i z#6eRY8>QZuxpS-Rt{pgeg|Y7rKmXLNK#x0_AW$Fbh|+*Pp+KZ(UjJx`8kj1IEpN7P2h1Ira46sc!gf*27wSk|$5F zY+3B*8J2X#98PMOrVEXe4OK&)5~JbS?^Lx%7=@OP9VuW$b|_&f)SRYZjyfq_8wx&y zAhww~q)Q@g43`Rk0kk9>@Ot6;tb)3wZHYP(Hl{OjSufJkZ-z&tESQ?+28*YadfzGP zM%i1IZ4R)y4Y^5$dLiUGlx|&(fcrVjIS`@r176A>Zemdzo7noKnTK4@51;&1(w(Y( z-sqeh;hu|_u3C9i%-i~04!se)sOSql!bB%}vPG%Ecq+cpFYTMd{_K;4;-{nge*Sn6 z3#OcJxEFU;_?&9my+=&fD5;s3qx%#uQ~gdnLBq$e@tGH2{M|Q z-}5bQVD=Tcng2CZ$vwXZeQ_kS-DL(dr}!!>jwUXO1Gb6j;I`|cw(RUUKsO(#<*It{M7q|dcVx)4cqrgGCzc$;>ym7mfcS&&lUYlJJ@!7 z3NLlX#=5~m7T6tYpO>a@+m~IDzn4NBn=b>Ym;oh4d=)(_s%DY*3zGu~q#6eMZ#Lgz ic#!D-CmZ-ki-ywJbH*KvQ@6lW1!8WB!qQJ5c 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 literal 0 HcmV?d00001 diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-mdpi/ic_launcher.png b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..3813caa21c6cb224a8da4a76c31cfeb1f93b9833 GIT binary patch literal 959 zcmV;w13>(VP)d;34&B$e+bL|;F2^UtSQ1G z|0OKl)VXOkQ=`^XC0HTa=A89VD5vus@0GjZolDSrZ|uUy*}i+v`F-EL_x#Q|_o!5n zL&gUoL_?vK7@Cy`j{;AJR!!mv2PRkUHzWS z_8yNx0w8X_bzq|9%U2^bEo*{5`Dbpf`h4FI(N#ARmC+VazXsF-xTwzs;ANbv6%)F(cXPBbiLy*|c$pPpeRBsFlK=51l%+)hVG0~dPV1n}hpqtY1wFeveP z9oYpPG?W39LLS#iY5+knI3d3yMXEVoF$TmCc><9>u)-{q$7La87a@=ABTEBf;{ftI z@;o@?eLXklQH%kMurPrU7b7n(MllA&pcn&~Wn#98StmNST4@F_&&Pb9&rV3OvNRC9 zA}iolWLRkld5ja_i-Qbc%7ZKy4#bv50NCLIj$oeQND;A20i zC%V!b&#AVUaQ4VFsi~=nCm+{0Yb$EJsylTvs)|}4E7uZy%v+DVx{~siO-V_3eKg_j zRK`$j->287?=&3Ej!(;w1{sFzEhz^NL(8&vKiEW0PL7WLjHTEhF=C-*MH}zvEH0NT hT1tp^*vKK1<1c=9ZjnA(;xqsN002ovPDHLkV1oC5!>|AV literal 0 HcmV?d00001 diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-mdpi/ic_launcher_foreground.png b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..d492327788b3137fb5a42decebcb7c796d082b91 GIT binary patch literal 900 zcmV-~1AF|5P)gR1iW4A%qY@2$_;Yr3zpGLjXen z0~i7r0vN#P!bpJq{`1$hdVB8Sr?2i#_j44ceQhWEtbGp#m^SwI&aS)i=$WhBZA59> z_gkIaQ-LcL*x=_cclG(}XhHe5lJtf8#3V2sO)J2fF&)4sInzo5rXc`8>82223Yd?GOE_aCSHwLH&X z?M)^QibYwzH?}{Vx@~|J08FL?BF%3&+IP$KCcvx#Q`YAv5`zTR_06|4+X65Hz>c#& zB@~KL8U~je&D3oHm=R!k4PXER7{DTmVYTBJRwsr9l_d_z62rR=Q)=&LivVM$Bfh!B zHE+J}B%Nw0p^0|39$;e>Gv7<*V2?nXmxN05IJW(XEj*UnMG5?`B5}Os1QULl2q~6hEs3m=R!yXIi~^ zI6NxGt-jit$tD423|MFn_y7!G00UT&F|2VE!}JJ&F0P4T#RO1&vCGD6~|KmP77Jps5t3(xMTtm_Teh&Trna^S0YP+P7`klNSQd79Wf?-0AkL2M1jh~#c3lB?(kqvOkXf_FrJ zPN!MBml`J#yL%Yl)A7`8uD#rf>GpJxJFy~17nq^#jTehqsC{EU?tZ^-Z`d&J7y8ZwBz zp-&TTbM+0wY=#2UrvZ^=WQ-hyPI>ZNojDp$&az2yNg2Uf>DdkfApxz90HXjzlnZF@DcJdioDN zfbW&0LCU%9-x+=&(MSIoiv9jKaKsbu4-riIQ5g#I!dy4uh!|T%gIaY4*RqH zkpck0-eFR>ie?!y09B_v=Mi-;aNV^cB+oIM8CmkzDgeyh6)39Q z>+AQ8+Qj*SifpTj|-^$r^w+($c0r zRGT=@*|BKZvT0&I7spWjI9xXhmk8IWbCt|>stKFn0CtqMGMy)=xlj!Esk!#5;RZ4U zB?KoiSRr^tDZmW{fIzl6ub$~_=DI7XL=@R#T_>ax1K|KrD=UCNx?nwdo~IAQSO5cZ zDp5Q_~DJWJ@w7@$hR2peQF4=ranE9k; z!hB+MNBdfNmYh73rPWu$Eh%9#C=pR z@>?5uKVYe5k*pnGDJvl_Y2=UBWwU|IkGCIWIy}jB8Pe_pzu<_2b0wME8c0cv3_^Y_ z6oD5UF8KwAd~~AD{8L;9izQ}wZ)xO#0Fh)$-C$)I>wWEb!!RJ4;xe!Nz4uLP*5^Uy z$dnh&DJ3PA+u_SgUniD=Q+zc zz+BV2A8aQ%C0F=T%RrPp;tJt4tCEzd`4V_AUZ&OQ*^KwITn1!C2g9TuB@^Q3 znO3E3BA?{8kWcsA;WLN`?mb1*lXsI+9#t`Bv$ciuV7xfbko>$6t04;+&uBWMXUP18 zubAFmyM=9b4~v+sWS7)V@*Fowe)(UVaGz^y=WVPH@5{!pv2zq2<2lcWe`?_WV-J9t ztSEwwH#Z?6asIpo3toD0@!~}w+~XPAls?myG3L?#*u&4~HYhCG+S+0p8yjO4Kv*4o p|L}-H6P0IX^g$(sF-ClD^FN+2BkgDNGH?I@002ovPDHLkV1nt`tv>(& literal 0 HcmV?d00001 diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xhdpi/ic_launcher.png b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..b79cc77a0a1e54f90787a8231da0b669689b9ad0 GIT binary patch literal 1971 zcmV;k2Tb^hP)F7{~j90*af{xlPa^%hX6z+;F}Q#s}huEz@jBSfbfJZ8L1i5|^1cXU1HNF|seb zm4fnOY$*lN7_CDxGVAN2M3H48if`z22&JXC1azLA|81+~wzn3%7qxv(@}y1s^qzD7 zzw^@joO{kysVGsRM2Qk5N|Y#3dVUgPOv6n}CYWXiVD)^0xn-=COmJ>42zYG$e;Bbk>)msGQC>#5e;Hrs4jTY`tC!{M0lmG#tx zh~g?_*sm%u-s7+L$+)?+=!Z66)LYxER_i3$T7u^wHEmaa7HWRst^uCe1FH2t_CQr= z7>L#xSn=WG+hhUY`FmxtSRxnH)Sq!>WVlaaOPNcXx3`;Gva_>eyfu8H+F$=ibAqTEd`>u8L{4m2~G8mnA-ND{%iPrK|2CK00;m9AOHk_01yBI z@YDfldEw%B?qy4N*Ry%m7WUGPTBZ)*ui^f26?@pinqOJ6`5=3xd^c0;r2X+7eCBgs z{06_pF(m!DP2gpCi} z1!Y3nP{x?yhTET201yW!=Hw?Swzkf0p*4tW=ITR71rf#mH+$@C*}mU=^1x>|dmKLg zIL7KjM|@fu@__1(I?=m4zDSwm|U1i7sK>yk+ak4OU17k|6ANo(Os1v#!DSy=57q-_t^v8Rt z+6?RE$HFnaXRnZ_q(3)|Qy~K&weFDQ$-;iWdV`HEdDQPtsoWFL|I!^BAHW|0h|-&c zS}x_^<#4j`UcitS@(h#*%1i))1OUrD-6Gk_%&qN%`g8)I008va4VSO`Ksd`=#w_Fh zLB0e)0RW!geSfTp9pnQtU~D~gj!if0^YJ493IXs~Bp(x^^wpBz699z)JkAIJ0SH|H z2s=#NQ7goRMu{%I2!O%>aPd^%eqD&|ARctQ;}-j1e^?0>)Dkqn~!fdharYQ z02BaVKHo0se}cCJ@9u~I$P57C0-!7a4}|0H+s!e}i0MXu_iPdXg#dWEBa8_X%WD1J=T86>1`v!900I!&0C1aO zWPsQa0Z<44Zmh)(wg^|?VhvZ!;;;n)PzV5SDL?ynr{CC-covNS$P56HQ!J{GiX9<} zN&plDfaOG3RupK_o%ehK0eFlp4PudAv}loDuZ)ZI9HK>fV}e+uwBSFYnd-SA zE>pDxSf<)6TBfQFw`HmU7i!;;TBvSe{B+LP$f5iqF6Na!^$NV8|){*SltfTVrn{{Br5VQu2 zQ}Lm^SqE)bLjVW>0U!VbfB+Bx0zd!=fa05X%L?GTlJa>3U}!Di(~X-J%LX8?Y*(VD z$k%tg-@{xwTWt0U#zLBV+z&wFj<8 z6d7C)3ajo3O|Br!P0&DijMV_N$tpMANKa4406Z=yCug)uhNRBS%)}Fc;=WnCHfz<+ znj2Ah6)x%+aL8O+Vdhn`tnG%IYqGOfL96A)0G-$ z|5AKOyE)&k+ER2^wWYAn^%_p*I%m!10>>P##kzc5RcdPLGHApT9^@wLGbKSXa^}pL zvB-ei+}POIrSE^3k&*V%%1;)pSdkTumcq{+8gMP%g(lF(tx=?$wcnHQk0>f3A>mb? z68QV++-7l040D49)1e8pfktkv6iJ|pL3wOkT-?NI)26)^A0Iz?>eQ*R;b=H_XaFss ziCY`BY6KE8(YpJ&QDJToZY@SccuJHgQKCeN5~a{c{{!V{pPMtdXLSGo002ovPDHLk FV1j*zq|N{U literal 0 HcmV?d00001 diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xhdpi/ic_launcher_foreground.png b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..811b17ceed93cebf145b331bbaab3a8f69fb67b1 GIT binary patch literal 1845 zcmah~dpMM76#qWcj?0>ql5vS8mnSns^Ds!+36bn*Q!_5bw=C@_YDyHTPup%Gv$+hT zT(;a|T$5`}=1F&r3d5vDW+Ec87>$+LZ)UbXx;^_n=R430|4lSt*)eiF!g<*tpHx*jbb{UU4ENk93|qGZKz4%dr_q8upXvyd-EwBvsJHt z(_TJgXflw_k+v>gJ&=F)tKZI4lMW$Zro>W#;KVOTETn{mj1d!>g^&ue1kDgq61aB0 zug;6a$8<=PlWAdtfsQsYxcK-`Qb1QaZ!RiqFtYjWK^tDnNFno&F?guGwt+qRDA#@T ze$g0hASSEsGTC-uy0gKs$h_)0{KJA4TQYh?yeNt~D8BF$`-XB@Rqz$xd8hsrNHOFl z>jXXUSH<@SdB+7@LD`XwnzP$w3UV-pv9z;M1uXy)+p6hB_n(Ydr{EsZ^^~huYtA{U zpJQ|oc;i5QYg13g#ruxIBJlLlhsxCkiSEJbNsLa(&{Bw_`8Zccb9KqoaSLdprbdh| zvbJ%7XFZ%q5gt)Fcg=CYSn500DWj)!UBVJ9q$Z~_7%WzhVvq1IsH8s7KP@e3H|IyQ zq89$gY zq;If;w7`p!S@L|r^=6yzIlX?zvdDcmM1mFeGD|Wj+4m-XfYiHxp#|%7&)_{0cL}~< zc-woBgr?O_`NW@Z*uud0&T@rL!7K!plVvY{dk)2h~7U~GEj-KXC9&yu!D3Y>OqsbVjLH2gA(9MdZXJ zkRp@=)O=}jfIVbdAp;mEFt5r1=wUNE2q_9l^;1R>%U#7=4y%6Tdl_cd%YEk?Jrz;0 zkg5DwW0=`2xBQnEk|pvu_yKD_Rb?!sbLN4kJyNWb7v&a+_8ktg`Poz-f`dt}^B@dTZd-qv+J|%_(3EL;%-Dh^u?(9T$|^sN)aTWzh`rF5 zBv;cuRx6HtB)iGBo*Xt`U$6Rg!qD!DVF4@|($Jx@9gs^2mG8k!dfkN(6x#PLKb(O< zs`$uQT(K5{6;!H(W+}+xbCuDLT);<8&(l^MZctBT@Y8wfVD}orw=tMRMgz4d+lU+c za^Y7um&+luw_4q}v7slLLOi0%+gnC}Zd{*+VQ1>L9!wIWt28W{vZ)f)y>4%$^Lo7F z4sT*DVf5Nkfvo?%7`H_gxXg0L`7Kl%qso6OHeusZx z$wj~HnI_HxKD#!Z^LhCH=k=g%f9HIoLYK1lf#G41^Ez rlffVxB&v#8@&U*C>hw9Ak$Ms=?RY7OsBXVM|CzlqAF$fuI4yrV-H@apIW~1P4TsgB#$HC5W;aKr$rQECCY8LiVsE zVd*3U+|L{ZkD#N1AghStAfl)k7Qq2$eu$x_zIydKulLuTbf>etbLw>R`c=KE@2k4^ z*1c8LgtT34m#d3Xs$)qKN$(;l&*|Eb^BiyhXb?%?fO7Pza-=q79V4Y1TT`Q-df-3+ zJ{>(~JaC}XE1w(3N87K>7T9MA* z?S$}_d)aGvepM7HsTxO$t4kPYhZ%rZS)!zyTVFdk5ZSuOqaI9UIiHNW5 zfUW|#@_HkTfa?|n*?iCIVB~dbaYQI`R=G;6V_9SKnTWZp0v-VU-iUx}Bn0nNy-%)F zKCh!%R5n{>tp>ix6v~GCGS^Z&)w zPq0RvG6U~SHaBfjI)p;RDN<7TWc}!6ZSwokU^Gf**}1MVg2~tF`W|l z?yL=Hi`iN-O8%>8m8--wLfGr-UQe4*Egw*Zw!U~yZQfu zEsIzSb^fInl!~BN6qz=e!7pfrz1~q$x216NW+sLV{y~DGY%!TBs@frgZ=M*@mX%cP zDlqLND@#KxFle%#pHtq2Rq9g?e$$(kzA{@W$=|e(7_-BgW+W&t%-DdQzn6pGl0=SH zk+f#hr)0LVi*HF#EC4R^E8lH(;9HZBTfUP_of_a9>qu<_7gcU-C1S^kg;aHoS$&jb zZP-$89eHz}pfFruO08G8trC0{36*usJf$R~*y!C+plJKT%@3*Ud`;Glj-`%kx6<~d z)owMA=PTVxJFw(#KIG}>W}6-P+W8VA zD$evaU9{&g-G1T}t^D#EI`5+cG_w3Prwv5Do}1sKsh=F8HD8^g)n9!>7kqq>-n{X3 zsw;K^Jo^sMq_Ag^XDiFQkd=Y5BqzZg)CF~#&+1mi>bQ;76?I14B~3vglkD5dUjGA` zZ;WnSr3?p@?1a*>7gcFhx~TZrcRr-2E?%NnfBUaRI&}6N{mW}R9p)YN&)xLI`HMFB zj@4eEL*IPgVLp6!?C0|~`A`yf z^Pvu?i=%vK1KOfV9{`^<6_hN=n$S3-Kv5`|^%Yf}v>0wKWH5%XqedZJ{LfW7{=JWF z^3M5izteobUj2UTZz{Wo@0{gD+18@(nVlc=x;V?XXzyW-IzeEwdi^OfHTlMd zD`h#ej^uA%BCH-wetak~$WdpFLdw|xIW?$;H!_dwkxSu==dA=T;;1^ zWvdMVyn7|9gR6YdUucuI1pt+Quvs!Ci*qwMb{-R;WXvh+$qK$C%egI@te(KNHS~>t zpLW@>?1Nv>fRZW;;!MX+y3AL4^eYP>QAQ3c%T>O$M^9J~hkV%@@}VtglQuUt!w8*f z^}5Sserg{vH!yfA`_cPz-Rb>JK>*T3CeAKjaV~ay5rOtdVwj`E9|)|LfP;7?nip>_8m6QdyN1&idM%bXU0{_-O~k%FJrnf zhyj0GtL5Vl1R#a1-$tK!_g^%9-%+|^|55tX&X4E~8@Ahh)~f_4m}L~5Aj8InY4;N; zvOlMMv^#dczYw4#J*&IH#RSUB1jzG(oH9yYPJc?9E~uZqNhEL67EeQq{y>11==$ZW6m~)sov%6*r=?bH)ck%0)BK?`L+?@z$DEmIZK{>w!5-K-XQ^4JI{y8>UEEM zDt`Qh0DSN28Ltzd7DLI4Cj#5C*30CrH!yJVvu0zVr@gAOqE%(U*5L>+Z{bNu2p|QUKWmNzB)aBr2+tY~|Y_0sE-9_*t48$5^}E+z9Ae_9~xjIm&aq_JYkw@EHLRLz$(& zk}0zX0^MZc-W&)BD5<7-hg^F@%dEViz9E3e3FKMvg7js;*k~%A@Gb#=dujeXz}hYWV^(Izds74%+Cg3BZ0N`L`;qY6B10a zH@w#v1T4_virCT0ToGxRa7ADyEE&}+BtU>sUOpE@GE2(aoN+XaHHJVR0^8&jBUPWd!iJ@O6?~LCK5-Sg_m4Za_xd>_Czi zKWVf5#zzDoA!y<(4}vZTzE}s~{g?pR0?OV%$@pngfN_nzz`Tgkv?F6DCXfQtFHI4W zR5nZ;ccQ!zc0~BG*$|+Zpvwy{lfOPZ1Q@T6?6amK00{wf1k$aaKg>*8 z1m5i}LGfz>@R^!B!h?CPVy?w_E z`yWRcaPgD&2E#N$VC&)1NV!gP-5 z@EMv2(DMmdNO&w+z22uAG_2QnKDFZ`zR3bJW~`vF_8s{(0gC@8E#qqvbVDDGX=0+r zyT~!FL1)o;@$B{}Eu47h_@aHDzWV$5O^r z<0XrsU~=z}yGd@D+wp;h5P*$z&enKhMTK=d!S4uAl<$(9^Q7M$_j4?V4{z_zK1m&k zPYhz8Q6yz~2|oj&(Bu;Wu$9!QE8@y;JgDQh1ju@`j;{rMe(pw&p^T-Q=SIkkg_1${ z|A}O6IOmIv+6Y@>GqtOHId+_Q{zHK1{l@GIBtGE*j$vYA2T%6O>quN2j&_eGb6?5g z8;>=P0yJ{FhNB8r+BvGA!iz^0l-oI~AVb4Z1>3Y9RiN~K$o@$)ia2&Mh8~`p5+C1= z2M|I-`;rw!C$!EB_+cG;H5}Hl^JANQo*veb0|^dB7%i5(oc<~oMa8a9KX-Ou6AnkZ-;)EI82Cfqa&cgj9apxN z1Dg(=ZNPy|O4JJ-^o99vbF5^{8s*e19Z5)l4I4>r?m37o%m0?Y5PM+VII;|K6vu(h zcjL%195=RA99fp)#*t+U#F1qB&HvJ&>)74e&Sh@x%QenR*`aOUk4BN_9}<=={$%_cl01%dv_1*Q>>n) zdDqB;k0f!7WULzf^uz!X5gQJ7os={ulWTep4)SPGNs;>*B~+S_lnZPGMqW8jT1TRz zJCeXatZV5_W~Wy3$p)s}n0mK50))E(zW%9mUgeko8+j|L*M4b3B4J^{BDB_z%v-XP zNBg-_ZcQWreAZ@kz!zTL#jxnlF_E$H`Y&wgNlc8a4*~)Pk_G8|S{Df_@Mov)V;CgJ zazDl^a^Jovf_W9$t1J8L&MPo~>0XsMs%zmgU-t9NO5M-eemBQJ#=_uD(PNJUMJe}S z=?;>d_MTZW!!oE3=ClOh)raxH)`!@+i?_XA>H7Q^mUMg_QFssh!VrFiZUB>qH6*iC zkRWX176CqMi@e8+lF756a0l`>%WZGh6yRHu5E8UBX-1tCS(Pb<>8GU!M`Dr{&)bN$Hj&tIPC{sC21{ zWu+K*Vfd5D%IYG!Rq7S(%ger&9)5hTu<>sdZ3+}^^y{BAl=v#^@bCx{5`teQy*(f} z_#Wxm7YayPW-Ygr^-8=iM$k8g2I*_2Ct|TM^3OWu$+R&rdP-*_bA_#PPbK&T_BUH%IVo zXU>qHfq@YuBBG}tqF(@;NlGKe%wme}b&|UBdkzSK8p_B}5(kc%gM6`*Dsf=9)LGo) zBBk;V3$T@*4x%wnNzM2U@5H-V9R`aYAIIy4I?A%%(A?W2KA&HL#XM$niZ zW|PPC>HA=>L4!ud4SC=ZB>atgq20O-!8797fkLMD6=n58*?32gJc|ty@7A|8QR4{_ zl90IoBrqf-B(!_??vb&vu{X2N?(F}bJkTwRtT+K^Z$3GyPrb!=cqSHkkXMuui86(V zX)oR-wRYgO5Ymos7-7JLvRQU?baYr$RMd?+wTGYKT1mYx6z$CMgRZ+07*qoM6N<$f`TONdjJ3c literal 0 HcmV?d00001 diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xxhdpi/ic_launcher.png b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..05585e4c62ae1099cbcd555a43d69d30072efcc7 GIT binary patch literal 3562 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

88$d`)(65g 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 Hu0mjfWoL}u literal 0 HcmV?d00001 diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xxxhdpi/ic_launcher.png b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..8ccd6c8402537f23642281c83ae8581b9a39e0d2 GIT binary patch literal 5004 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 literal 0 HcmV?d00001 diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..06b982e31241cc23c950a6a5eff483f05689ff9a GIT binary patch literal 8278 zcmdT~2~bm6mk!d3vUZ~aih=$`T#!vrKv~i@+B8Oq0$~?WSp?YwvLp~(01<%}WtY&X zfCgk$AVLxZB%(l2b_m3f24u@3kg#W7z~|rdSN&B}Q#DgFRKa_7?tSN;d+yopcZff4 zVJ0QMTO0y`NSXhB$`S$*DHHx~-2zbFS!k<4AU{LRPo1<58<-hF`wY)VYH?!W@I1x2 zpgz~l;yaP(g9G-4FLrun514mfcw5!be4*E3xBJX(>(_T*JsEh~iG3Dv_2i?HPZL=Z z=|2ROLkG)qn&MH_Oxm77!jFcbVw7^IVG@)sds2cvi&2K||IJhuMyAiAM;7MOh6O)w z$~B6LqNii|{5rE!|EoU*h?{rroUQGUaNWBXBARjM4nz`o+oT;G|F^fT^^pA=wDq^Y zP5eLdN!!zVBwj>ci1)rOCBvU^-fYR_W3OVxZ2YBNo?TRCIab*qwHljeX7gglI9HkN zoL1Iq-s_?R)6m`9u9OPIT_Lp&=R5s674?9n3}2@>)jkJGF{PjjU1)YI$@9kt9EZhc310{NT3XpZ@ajhjN3U8 z5(DYc57)!^&e+JiKbzdFwX`rfpuuQrvX2%io{J~LU*+zW&b5C%umz7#@1i1Kw9tQ> z-Cqx}Ia8Olw52geV#?noBCb%mTc}njD@?0fXZ7l4tG(ddW zv~1v{R*HXH(_}JiCaxX5b7q^OpQTOr<>6_g99-YYQm-HEFnjJLo<%0~FDRUd7E$kR z5(|n*sl&_Fa(CgmCqF|(?bPB+Pu)SJRs}xymP_<6&yX&?oY#94qE70i9KK+Etf+Z@ zKgsMzR|x#kLeL4tRJ=$3f~*t3>cU7{46Y^*Z?8{!6Zv`iIG_`bwUV(?Ngy{C??DUu zXxGp16B3Q;-Y`s&8t0T-Uci9$PVPdl+5$%&p_qbCdz!1}xa&6;G!!_f2%dD}Z5i^H z7Dc?n>jS9i_b*H#qJ0mohPs)AIK0EBag`n=LlN!hbH>!^VSg3N?iAj0o^-T`&t&+^ zz(T3tk?;XZmIGi9&&Ts(Jrw`Ir@fRZ9+nh-fWtn+=leOuLAI0~8Yj75^Zfv5DCP`O_6>@V1GHyDMam=_xkZ*(c9?NF0ek{D`y za_Q?dA#~2~xX^ozKQGwH|*50zS_D?F45-sBz=m)6y)J@TKpEtT?4 zf3)|C7Fxuy^;nYn#x9wQxRG1)iFt%V?0XdAuYqBhf>Qg*>!!_Ux4`77`yqqBI?`RE zlAgCh1vtkbEL|)J%P!{o__eNLm`az%KTjOOnvKx7%R9-Qw&|R7sBlT!^UOzVLu({&T zQD0*4oCZ>3ynKGOJ_|{+B^EqGQD#vgX0NTXkLxK(ul_Z%^K_2k8edbTzjFD91&aSZKudr&y9n~dAaJFV5agtgQTlM+G1hP@&XF~ouL%mlh zXRdbp)w^hC_H@$l0|xmiru@w@)cdbrk`TDV1GH;NIlr&cELYgag6DVmj#X>l$wg$L zD7o~i?FSO{LTTHVKPC}%mmUHB1bDa}?sw(a?~wjpbNy9G*7Aj9Aoz0$PvC?a73Z6| zW8e@ul^iOp=4b^pEil508EeVV2ihE~z@f}U9! zTKw>Jytg8wmfvdU9Vg3nunYa@DErB~4*yj}s{nP7o2;hT(6Ml8KZ?R;o+UmL1^l>g z$8I)dm)1yLW2l~UV0yFhWp32-_!d-V+iGV|1&mUFIIlfjW7rdv% z2XLf&eC72((6^cTwki8er9;N>3F`ehHNwJRc- z-TP1!Gl!fOg_~g(6EbQk(5lrqsX<*qQd48`TM`r^+{IBpjNZi_39IRwNsaMiYqhT& z;X0vpmbxu87_F*y9}26>(2}GQgPsAe&;5+o^_N5DiWKGBWsIyM%*Ub%d|k}PN{qtP zKhj3UYR~9|ViW>W2-Wi3Pm2=AObm7dt0>gB4=z09SgN1pmbs@8KX6arIM>_ID( zYL3wFo(vHa&1!xl_vgt z8*o14`YuRM*2lkHLds#cG@H{929>!IVzu2eihM`TpC3vjX39Bxo$TAOP+F0>NU)n zmHMl%?}Q}Z+aEO}0d7U!SXqwW^y$Q-Fiuy%!h^k-@1>R-PZkB9MhH1rB}w;69ucd}r`9%9>%Y2PE7vnBV=9N<52~)f z9TW-F^S7lz&fm2EKTmD5t2bEzvJ!Lh6@y#QvqHT(@#e}R8MSz$gj30D=e&>_Y#cAz z-EfX-3##76q26OOLYQ~4Y>ev5d6`%SSK`T$qb5I9@F|8VTyAmUN0^4%XmJ3ScvcGe~?E;d1DoCieMw9OyZ?HAA> zT)s?k40)Tk_U3W>ZrBrkn}*o8kJO>{Bi%P)zC*Ti_GSmDvFxK&--VHOCA&B)FPTwv zGeZTRCjtiH$3Qbz6`Q7C5Ao3RuWMR!sj3qFc1mfIW%Nw4dT@?XOYj(!D7v`Z3W{*J zMh2+fpKSNk%~|Z~JGJ2CE(%&}40ZLdB%*5O@?f^Z_vskcq-klI8!MMR`F(>N0<$p` zek2rgcOwJ=&b3*8ZPBt73e#G*tJ=p)K&@jgS8(HFAZTdf?Cp*N1*$)6h+ei!y6@Kf zIaT|Nv^@qJRU1&SRvdUtS-xH2oI#?~K>M>}5Tl$=+YNO;n0UOyg|;wJ5dpGHng5t* zSg^8td0(QdvvDnGqGfK0rGNTQDYp8srw-32#(Qo7l`M$DoAvmAaJ!E`PJ<4^N;hqI z*_N`o_85%;?8|2fAB!428;IMekzl~!DH55Z10BJ2~oY;myn`FSQ2!ODCuE-W`*Y)ZDc)w{rC)e{9&B3 zkC(7i+pJ;K$b67D;%d8A=5}NZ^u_6$#A}x>E^yn4jE)Y@Y58)Xa>@hp;8Z0jQqqmc|Bj`NDM&`Yxkf!FA+&)AdO$bG1vvA8K_!lX{77`SaO z;CcmWZ6hRGfrK63=6s9P3iaO!!crPMob^|ba29m4?@YjX-wEHDfXjHyE!UIkFjvBY zD7f?C9J{`+N&FkDxq!QePF2Ms)E%V3R57vqG2OcX;lPi1QfSujPL*_@F#U_|g7OFb z+tT*?o%Zu+*X;tXMhmX{y;bNA`10X{|;)M`~g_p}Zu@F%t}!ML=U8F||N&X(UO zjV`6$;*}oX9q+P#hV4&sKuYa;dr-+@r4()h#;P<6=Hm0XUSFvz4?Gh{KX>nmI_9Kb z{oMlpB8Hqica^Q&>UQ#O`T!;21gJYW&HpbRX}^xsL!iEnE!ytf0bI<4TghfbUxbzJ zJ-TPACHTT!yZy%U-%bS>7y`oHqutr>FqiJ?n}fpH1h8Go%lAoG{XHw!A&yq3x?LK` z{&CaB7W*W{ru%tGDL}q&_5gP+?&tLLnR4y7n|}gLXP1~A5SUY1i8D>+-)H461JMWw z7L&K-bH9Zz4+B^FaF=BY0ozp}4}RP*zUJg^I>s+ew0I;1#G~)Z=MelcB%SHs7m4oj z*Lo-Ja|~zG!DCDF;bHp+a1*+Fu%segZYvlAM_uX(SWfW%SzdBd3?lsn7^Zx5QWwdc zeX_slh9&nS9QmX4Y|w1&)Mm;4e&Np!e?8a6z39bF>}Cs{dOr|?9HQS2SGd~u4Wla# zqLg;;mJZb@hWpxpTU@hZJHIsYf!)`<3(9 zWeo=)#N~a#NPgX%=;wEOfzq7TkvWLYnpEX+=`fw6vTMCnLqLeWdqf%ZEcSrCKya>; z?(f$I!-QU4X+TUX0N9G}>MaJv&}Cb$U7b;Ckre1}@UHA2v}JCo_g4BqnX&LrD%i1H zlc8lCrY;D@Vo=xCb84fOwY!cCxI$+Is6SA@pmP4zy}{jq1_{Qd{~S2}`&5s8uC{HO z5`dm1085cgn`Vp8tlr9Fx7w`6tHM@a(|D(0%z3~UN6NS{_#hPr+`XF~7(Z@qU~*`~t`fjD%xT-~qs;?P$yIgT`Lp-U?cloS%J} zdYz8;!--a+XLAEZz8gGMn*|!yrdIQwTv%mLULs;XENtkzF^lIe1BDh)eJ2=;fy{w2 z-GyarmqM7Tjrbc4zg`6NkWPZuAf9We`7S@haMKSPDyWrQ0zi>7720o?tAVHxCin>a z%`b#~q_q)XE_Vsc@l-cfF{>Kw30@Q02ibZv>Mac~SDRW+p6cl`e)OEHEZ~}dsD);( zCCH@*)&SR|f5a57hoIVD(Nj0w^Uwy%ji!RKOX$Z0!Jn6r2FFj}7Q<_SYEeEdbq8m70|MRe5bv+=Jh0XxT%tP$^Q#KNv zH``U78}+Z2pVPQ>S*LdMJjIY-@HJepuhG+>nK}*>HL}z_Smy+tx`6#r%H+Ds%zHE? zp|hXM<5tghUo_5CKWoa|&Zvaj=IijyoQs7HlL?>#l?C$_WyvJ#2iTI!HvAVuM&uKz z1S}bY^hocdC^loKzM%luxy`mQJC+|=V*Golp&?^*W@-=3#j*1dw%fdXd=0>&tYK^b zx6)Wbx9-)$)_TAJU?SI1&K4`3c<$-f$#t#hJ`D_9y6|E6F>bu?`iNW2;@e5RBxBGYrV@1can8@g=gpGk-A@jEH2i}cou`1Jn8v@YA*-?aU%ZP{ zGS@O7bmTQ9z3DuCoIUR(J@i!mkg7n?4E06m}8kv6hOsTto%4pnZA6nHG@39qW^jMGrA zwuO=W{oo4@xWVlQdvLvm=qrB7%yhKOzGi)#;ayu=e#pn>w-Jth2p{0~6)!^v5Dx)q z{1=a{G^;9|u23j-=D2F(VH`TL!rgyuYxE2Nm;;FLc+*JyTsI{`{B;uv#R*<0YPr8=^G{7Eu)D;L`H7*;Meg` zkJJEGa-AJ?ZG5s#cn|$Te%GB^7=+FW{6``m{ubU2KgKU!$?M4CB<^wJHr%(8?-ykm z>dJX12gj9`dTCDNRfi?_QRI4JD7ziM#+hpIp570G|5_JrGK@9oq=pKE(1)wk{U$vJ zOtLjiT#uQk8j&VPJZEwkF4Zh?Y-h(FmUG=og`s5d5bbWjGSGa0hbT5M3C0bDgS^r4 zr1V>`@_Y@W8vG$zrX!|unECqQfy5>Pi@N%ibBZN@)4>0cVY{-{o8;t|uV?ZHI3z-P z?*p|FqGPC*15V(?+3Q%lNms`@5D#>a2BNKBJ&k-Bc%UAlH^1_f*eIMoqg%@d zDncv7O!;GyER&Nx8kr0y#UCop6b)Gsy8=G&>TD8J>pVV zJ{d+2wv!Xly9h~GoXpbD(?)7|lSzJ4!S=EudO46OrQA6;X{3e&b4j*$7a-Qb%+A23 z*`JWF4pNODb%wj0(1?R%`$ZFZQ~C|PJ$|p=Jom=03VTt#ou7f5-MK6Emm`4tIjq>H z?BjE9wNNR7EO$?!*Jb=Vtt=jcf-Am;*=1k zXFcm6*Ed6WHY3~m!gk(=Pb24lO@B`*%0M5WI&b@+R9~{A{_==w8PHCv>9w5(| z5#V&b)`I_?Gz>|=SOdng|{{VHML~)b1wlZ- zP^3wb7J5hVr)2)Qv$M(O@e=m+Hv4_^1>?)!w>#&|oO|ca9fbJBFMjchU;N@1zxc&3 ze({T6{NfkC^tmv`0%!*4@_ zf5Y$S|0AD)&(gmke+&0`o*nh?#Yw?0!(0&&DztpL1B%$@SnOvqGCWX9R&|uJtSw5( z?uq6soq$qv7NFFn>&VYtq#Y&gBKiGo^7A2Sk4Sq;T0Uu*wS4xwNAxq|XD_n9-No*; zfZiKyP+P<%*e>?FlkZHwdxVO2B)_x+y#yZhD?Qy6B`>W@fcOysWCTjdSxUfpi2VC1 z128VJrDQ8_CEx3*Xp`8c-+_FW)SS*JExQi=j_Q|0VonBrl|0g`0R;XVK$VjHIRRTT z8_{o-0L*;ySpv@NC$y!gx2&hinufm>@25U~$8NR!wXW}yhzY0c1^^rd9 z2X~aZtR<5&TS&XE8EgQ^oX6r%3fg?uu#p?HBN0XV4jN~T>+~7uvyf+kXM5iB^ULPF zS%Jy{xuckt=7i>Cw?K1pq6lF2koKPjFo|G;QP?y<*MS&>6v^4e5#m4kZ19Zmtnkbw zy%T=fsLYXH)OpSRngHe(4WNHoAUiA*@X82LD4o>EK%N<%9p1q+{sNarwkvaBluONi zlYk(dIj_Zy^4PW-NG2wiiazsI@m-L2BA)@cJhG8!j$GS=V>l;!>$8rlt%Ck}WKeUc z;oVT@S>`M7=#iC6orFwpl)7{f>EPUFMte~n-qgvUJ}bbxBkxeY;KrS03)T5jr@+sY%+E;2?c=~V6cNa~ zoRj@&k$24f0}CAW=PYZD=HzTt1O5{Zd>x4(N~1y|z`KQa%x42j(E2jqC+1XOE4BZV zf&VcFv7s8B5v2F}Kl-lWoong~ewldGPs-{+I^}E;;PVmRn9@jk&u8ho=d*!{wSFP+ ztCCJwRy2lhPoYdRhER(}jh4~A(9}o#GLqy;&FV&8d>)rO79)%DXrFLNWF*NWjVchA zPRU8-a>r6-(b72uYX|bk9KQ@9d9quOmwb?q`W8PMM5fU* zT<_aTIt7zN2^nWmOlot!XjW2~Gb!^e^0KZm@IT@JvYGaX_Gx0qH58rt4iA$S8Tna` zdCHPbWaNLq!EfUvNLca!&7AX5L6F04Nl-ZQ3uNT)%!)?wNRK^4h!Qg%l9`|j?R&eO z2}I2=pyce19Q<}jf`r8n(X`Z$DF*D$F)jdq)*D3@xHv%Uiv+V4JwQ_u-?1+eNZ^lO z*o?e{D;)fGOak~Bx9}<&7xRjJkf2DMKj##8c)4RtQ~*Y?^Ut8MQ|s9FI)N1GoR;E; zQnP>O;ODIf31+4pKtsj`*k%GKcL(2Q|#tK)AC2 z{MplG<-Pd|FK_Y{iX9tpdQ-A{7pc3+JDs;@(y7VM_=Oln&KhhR zPO$|3S?Mnk(BI)%oxGJSg|eTB{=nS3Xk7Gb)=dJ*k%>s~CZONXbw6*4!=s5yFq)Qf z5cLi7FIX+MI^8eoH(2aSH5K@s=PbpQ7JrKyqWGrz~a^H*S%w#O4`VXxw% zLVGohZ7*#puCQozfxTK;KVZKFE3tzSpRZhcp}jg_k365T>=hxwtaOk<=@dhSc(Rg9 zJbXbwNlUsITlWj30q8od+lJ>KI*xz4kcW?4xsH!ry@B^%x{BAII)}&nx)0aQUQ0XF z5H`VH`yaMad%vE~!-tu@19?~Rrqk!Cy@omK3}(-V*lW9H3$?f7+@%70e-L{c&z#5M zyAI&S1fWg^um|tcYu<9)j@V1hJ&L!>?B#+z@_doIb8(ZUKN{@$iuDI(&ckT@^j;K8 z@&i4rK>7$MW?m)o5a*3K`ol;Yw0u2YbMh>{dG9{H|KOiu8+7299s95+>0F(`LF_dq z9l!d-8GPgJy%O!6ynYjp+qoZm>tm0!CQH}hoTI1k_2<|-d*c?dcL4j789|?S+KAX& zbmSzlSMvKjfAcmTPl#7$;VR?J0!f)f3ME}aVPmR`{y>DI9O+Kt}!C zylePg2^}SGH%OXVq+RqfsC5qPuqyd8LcJ1&2-$ zd)n#rT3O#yd38@qd$-B^1d@BtTVbs83ox277o+f)-j*E|lBCa+d1c9$K4Hw!-*5g( z{5_F9+IE)I@^0V7!RvofY|n*&ckN$)>um2DkuTjgY$p;*nLStH?83-;Uq^c|f`7Vk zyJBbDeeN=xe)xpW_HGki8FS*zvJ3%&(-|T zYd`;e2|FqnC1JLC>$}Z#q|?XVma`XV#74>Ufx~<0)*Zd#eM~X>+XDeg5l2~<@UEsd zjdzayBx1Pep+u^;6(S{ywlbQ zAV!4fED(1Dz4w_P#h_WDLS`8K?STLgOCR#{9=c$sk1cpdkk(*x1d#gzqawei7&LiA zNE-dy^m0WhS-+Vw)!Ehw0If>KcY4d9xP3?H0+$UEK*So%0uyE)K($+XnSK@!SK>?- z`LQvjylJ=jT+OptaY7-t$YA*zk z7R91==i0J=Jyh0&CRM<{gkJEn^WiCW76C1fO- zV~?*r5kN}CfD!%2Q|F3JSGaupE=}`>O+UIMq**5cvPJB{rkT-Eizz0J?gvQPe_U*3 z!oYJP0kSy(j7R`^QeK0cb-2%#op{>bgE)Tw5jR;geN)8DpfKdrx%x1L&kgyk>ic#2vkrbOobB4vxCp0JG z{H`}wl?P4$P5_P0@VMx01e25jfD=H&EbtUfPs3>V#Ay_x26u)f`O~6>8%oODCK4d)2`2z2 zfMpPXIK#6RVf4+k-6$~7+wd|-l0T8NUNWcr;RN6WC~-{yWKi$WHw`a?#KkX16rVm! zmiCa(3BUo_o|k$hE|$z)UzCkZ4iK95-Q0}jLk#Ay&4)$ z21)WKX3i&ti(gq!IRQ*Z0LblWxoRW*zEED}(B*6N9YF5ScPG!{;oEXfS zKD7w~Kop3EL(?%DHDwpUtS7~;IDqRa|7pQ1M-(Qes*D%gP?ZL&gb zX9j>1W-?)?SRU&9d1Emeq=z5SU)29j^fYhrU^{HC@TWZy0GwSYiLPt4HmKFvb%XNS zpf*DQF&qkYM4zI*Uv;C{4Gz}X4-gmuoKfuj5teeeojnlX^>2TonqD7U8&027EQM@_ z08|DMj6!y3$ml5)yW$KW=pcV0RBc54jCVK98vAsUMMMJ2Pc4O2mr?+Z9Qw4+Mr{9-EW@+fQk{L zBln?7mEe#)oeAJbHB|4xmC21Q!U47i0zhq0Lp>ivgzU@*D0GCwWAf0uooWMy`|IKe zr=>CdKQ8)Ja^w5vUI3FCoK|?uKmbuvtk(3kL098*Hw{x8bcxN?2GwFgY*Oq4)V)u8 zz;JMc_6uS{dV0Dm`RRhDC3ZE}_Q&Fm@;P9j+L>^O9VdXT5r9R4U`2S~umOPKu(&uk zZ5?5W0Iq0yYM3btUp@DDqy;PSPiM{>q{BY?@n=o|TO)uN3CgFDpur;`Gt^Zl0t^{4 z#D!+n#m6n=sDP$xM?r_rR^R}00$42p#MJ2F6V?KT8J3k3AXwZ}=|uA>5;A_G1W3+$ zYAFPOSUKqTTRI+;2U(O#&IjWJuu305R4cGWa>S&a1jDdJ(kWP*eZnjR>g-p&x(`ZP zvR5QPro|8dn)mz_^n6-vNdOTfI6O}2k)@mfR!V?`42(ub9Y&s>WdO@sg+dttT-t?( zRzOLaM=g;6^uWAD-{M3fWv(fxq70o3XMJ_}VXIcPGdTgQkN}`oU~|kjQ%||HXcGun z)`kE=gcvt<`8YhhCb`i$OC^A`Sp*J+-hAdfO$UCqXzT-g=Eg00To8m%wY@(lfRz#e ze1Y(oOCIeyGyyCR(ZUgy2;ka1I<6tP(N#+(fD{>mh|a4kH{!7Ed+7oftb#`EIY`Oz z!jd)EC2grr_vQq!QUbuw2{UeZb^f#kV3}arRWSh)5)x<#wCBv(LF8t)Eu8?yY@7hr zNC1Y_iLrM*Kl!{3U|A;u^iE29ncV0>k(+V?Z~|Bh0Vc)$>(k|nwptT_eb~Ks^4wQZ zYW71;08Rj_BLJwDsQCZ9gL}OTSPp};td$ZVPFy;6|1u@L6}jOfP5@2-t0cgr_{ZMe z`o0HPCWE@WQUa(X0`y9m*NV&l|KkMU1h7g1M8-ez?$%RI07d%(R7?VSd@(!uHFCp$ zIRQ8UtaAp4d+7afj}CxkCV`X@fPL8Gi}<7#C^?He!JGir=>$g*C-}qeZv&S5_wVnn zH37O!j(L&X=oTjcCxBHFV8YBho*jeV)S3XjdiA0bsPp*ojmga}Tgy5CB+0?iqOh&7 zZ2Br(YQakEF?YF6Cns_O*uX;A`03ZZ-tG7rU^zHA*iCB!ygO)UZIqOG*3t<8z=sM5 zGxr_F+s|F1fc^W%ZM;A4D(#feZF_LFjPGcvK~4ZWN`)8~ebN23H-fY#K>POXVIj<; zX@?F~QR0$6EtLQ;vcukhWyenAOSkV9TS^2nM*kpW2>p2v_9Qa`Cx9IgAaMy)hWN|5 zL9@DmieieLDXr4azY-+1XdoSSz|r`=$a2?>-Y$8iE!;f^r6 zAtoK8u<)I95GPn>m{vppSS@oTjPaxdh@F>ZX*m>&Sc49kv+Qz78PEnBwqB0o!^X~{D!X;VD3x4zp<<%~X^wf@vOMNTm%fR%2F zkC}r}|FDIC;o2gWwIYB+_wLkA3MU5%Az|nQg>nJ}2M5En;fID#>W&KI=w>GYR6K@Iry)A*%PqS&0c^D}R@AI~ z)U|ggV7O(cPF`9Q;O)2HhA5CP>M`hb!m7KLQW_DeIUK%n-5?z{ZSO%&09!4MI4<9J<3JQ|aAQaaIQUwMEy0Drm_-Sd>Z&;^-ondBngiTEVXf-m|=yhfnEZBkm zhr{nU0gUVb!$3V@#v}Azm!1^6fq~xItO2O422=0ZAGLa`5lUQg+7cXLa}WU9m|yp6 zEWD+p9VOqlZuSp~>~I3;xdIGHa3doxpe8T9O0f$^eCbF4hf0+yxzSK4BoxIi*kB2c zu(=2TzChZ+WAq$eZEXB?{U-io{V$4Bu{iP-(C@fk|Vd2DV!z?=k-oZ@a9w$ogqD|hZ`(EI=3(S?zdE};5NT2jpF7y&Bc2vZH^V6zJsjW}bFnaZ_-3mA0kfk1chp7x6ga~4pu7sTN|T=z(5R@9MUsv< z0XP9HV+Ift;38*X)U8i6#cH|00E%559AI@v*cnx;29cn0=)-Pp$TV}!oHB?LfD@p& z{2yV=)LW?a8=WXtt5orm>3^LFQ0NB)1bDKoWz|r0>LzoBLpcFB0W^j`XU-$?XXGw| z(Ha!1B4%~g|3&=(I4-qZxd7@1jEwxIVAFvaWDq9+Cx8a|laC_fG5WO6Oo~wvt8V(} ze|0}VS`Vmz-u7&v?zlRss2%>aF#401|MJkxLMZ#XdXd!35%asp^s{v>KPMqdnCLNO^~)60&oCE+sS6{M*o=^`PT#CEzO+tn}7cbMa2yIg$I03XseE{co^yGV} z)mxuXOqMBA*3k0j*=UfjuP<_U2c`w0iLu|(Ss*#*F`JTXngBt|*W(@MF466cO70J{ zLey^UYLRjRD3w11bJLQs&_C=aibcRAVAFunAI*zm2zjD_fO2$EtXtn6Xx73frkn-L zMSzA&*WsP#^R%`BB!IH*P6|_^IRO-o{)7a=H&dRXcRv_Ru~@ovd5TQ~EPg$IQA~7( zE0ItSchU! zbbj58A%C9D4FX4_R3#`oT^;ob9f;x=nk*!04g$Qoaw8qd^|7_?ufMUk0)K!LK;h^g z9)r>QT}M(3`d6%^=KLCk07ac)FR#+n@c;%!#_ytgF-1^@%fj+kwuRz0~p}inXGnzoRL^uO1Q=&l2+~Tb=x@jY3An!|oh$ z!%UXJ9b%}+0IRF|b{Ld2fyxfgv*$?cjs11M-u6J(gPcEY2B zjgL8iW-T&WiUjxp=k;(D@3HAxY0VyRgy9@weeBIWcwA9!P-wLXQJ|unK7d?s=mhps zn1=+!JgBFv%sTp)VtZPrJiwyYz~O%)clRKQF*mnLEb?P=?XPJTkj@k?RWJ*D)U6kq zmi&lHAtN}%P-!iE=K-2@rb}o2e(4Hsn6pl+V_Co1xgTHGu{P+RSFY0oy|u9yMn+{_ zYmtJcua~`6t0cdHTYuBp9*q9YSFAUV^r5wWA|Ii49YVy>pJJ?(TI9zp1bB8`0CwZM zxYVFw(XYlXf;uhK7cjysP$qp9UViMf*0nkzi!*rrFIuN6gS`wL(jm^?xQ)N~=~t~Q z#DOymS*P0CgK~_Jg{rMR@O4shk7*qdf~wgAh&?AQ%0DWWK0ttpGqI{i|K$`@E-rx- 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 + + #008577 + #00574B + #D81B60 + diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/values/strings.xml b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/values/strings.xml new file mode 100644 index 000000000..e45fdb48f --- /dev/null +++ b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/values/strings.xml @@ -0,0 +1,3 @@ + + Please grant camera permissions. + diff --git a/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/values/styles.xml b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/values/styles.xml new file mode 100644 index 000000000..5885930df --- /dev/null +++ b/mediapipe/examples/android/src/java/com/google/mediapipe/apps/posetrackingsolutiongpu/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/mediapipe/graphs/pose_tracking/pose_tracking_gpu.pbtxt b/mediapipe/graphs/pose_tracking/pose_tracking_gpu.pbtxt index 35be3f0e0..6e25cedf8 100644 --- a/mediapipe/graphs/pose_tracking/pose_tracking_gpu.pbtxt +++ b/mediapipe/graphs/pose_tracking/pose_tracking_gpu.pbtxt @@ -19,6 +19,7 @@ node { } } + # Throttles the images flowing downstream for flow control. It passes through # the very first incoming image unaltered, and waits for downstream nodes # (calculators and subgraphs) in the graph to finish their tasks before it @@ -29,6 +30,9 @@ node { # real-time mobile applications. It also eliminates unnecessarily computation, # e.g., the output produced by a node may get dropped downstream if the # subsequent nodes are still busy processing previous inputs. + + + node { calculator: "FlowLimiterCalculator" input_stream: "input_video" @@ -37,9 +41,18 @@ node { tag_index: "FINISHED" back_edge: true } - output_stream: "throttled_input_video" + output_stream: "throttled_input_video_cpu" } +# Converts Image to GpuBuffer for PoseLandmarkGPU to consume. +node { + calculator: "FromImageCalculator" + input_stream: "IMAGE:throttled_input_video_cpu" + output_stream: "IMAGE_GPU:throttled_input_video" + output_stream: "SOURCE_ON_GPU:is_gpu_image" +} + + # Subgraph that detects poses and corresponding landmarks. node { calculator: "PoseLandmarkGpu" diff --git a/mediapipe/java/com/google/mediapipe/solutions/posetracking/AndroidManifest.xml b/mediapipe/java/com/google/mediapipe/solutions/posetracking/AndroidManifest.xml new file mode 100644 index 000000000..07da672e8 --- /dev/null +++ b/mediapipe/java/com/google/mediapipe/solutions/posetracking/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/mediapipe/java/com/google/mediapipe/solutions/posetracking/BUILD b/mediapipe/java/com/google/mediapipe/solutions/posetracking/BUILD new file mode 100644 index 000000000..a20dbc3b6 --- /dev/null +++ b/mediapipe/java/com/google/mediapipe/solutions/posetracking/BUILD @@ -0,0 +1,50 @@ +# 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"]) + +android_library( + name = "posetracking", + srcs = [ + "PersonKeypoint.java", + "PoseTracking.java", + "PoseTrackingOptions.java", + "PoseTrackingResult.java", + ], + assets = [ + "//mediapipe/modules/face_detection:face_detection_full_range_image.binarypb", + "//mediapipe/modules/face_detection:face_detection_full_range_sparse.tflite", + "//mediapipe/modules/face_detection:face_detection_short_range.tflite", + "//mediapipe/modules/face_detection:face_detection_short_range_image.binarypb", + "//mediapipe/graphs/pose_tracking:pose_tracking_gpu.binarypb", + "//mediapipe/modules/pose_landmark:pose_landmark_heavy.tflite", + "//mediapipe/modules/pose_landmark:pose_landmark_full.tflite", + "//mediapipe/modules/pose_landmark:pose_landmark_lite.tflite", + "//mediapipe/modules/pose_detection:pose_detection.tflite", + ], + assets_dir = "", + javacopts = ["-Acom.google.auto.value.AutoBuilderIsUnstable"], + manifest = ":AndroidManifest.xml", + visibility = ["//visibility:public"], + deps = [ + "//mediapipe/framework/formats:detection_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", + "//third_party:autovalue", + "@maven//:androidx_annotation_annotation", + "@maven//:com_google_code_findbugs_jsr305", + "@maven//:com_google_guava_guava", + ], +) diff --git a/mediapipe/java/com/google/mediapipe/solutions/posetracking/PersonKeypoint.java b/mediapipe/java/com/google/mediapipe/solutions/posetracking/PersonKeypoint.java new file mode 100644 index 000000000..8ba9f592c --- /dev/null +++ b/mediapipe/java/com/google/mediapipe/solutions/posetracking/PersonKeypoint.java @@ -0,0 +1,42 @@ +// 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.solutions.posetracking; + +import androidx.annotation.IntDef; + +/** The 6 face keypoints. */ +public final class PersonKeypoint { + public static final int NUM_KEY_POINTS = 6; + + public static final int RIGHT_EYE = 0; + public static final int LEFT_EYE = 1; + public static final int NOSE_TIP = 2; + public static final int MOUTH_CENTER = 3; + public static final int RIGHT_EAR_TRAGION = 4; + public static final int LEFT_EAR_TRAGION = 5; + + /** Represents a face keypoint type. */ + @IntDef({ + RIGHT_EYE, + LEFT_EYE, + NOSE_TIP, + MOUTH_CENTER, + RIGHT_EAR_TRAGION, + LEFT_EAR_TRAGION, + }) + public @interface FaceKeypointType {} + + private PersonKeypoint() {} +} diff --git a/mediapipe/java/com/google/mediapipe/solutions/posetracking/PoseTracking.java b/mediapipe/java/com/google/mediapipe/solutions/posetracking/PoseTracking.java new file mode 100644 index 000000000..423a26c5b --- /dev/null +++ b/mediapipe/java/com/google/mediapipe/solutions/posetracking/PoseTracking.java @@ -0,0 +1,106 @@ +// 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.solutions.posetracking; + +import android.content.Context; +import com.google.common.collect.ImmutableList; +import com.google.mediapipe.framework.MediaPipeException; +import com.google.mediapipe.framework.Packet; +import com.google.mediapipe.solutioncore.ErrorListener; +import com.google.mediapipe.solutioncore.ImageSolutionBase; +import com.google.mediapipe.solutioncore.OutputHandler; +import com.google.mediapipe.solutioncore.ResultListener; +import com.google.mediapipe.solutioncore.SolutionInfo; +import com.google.mediapipe.formats.proto.DetectionProto.Detection; +import java.util.HashMap; +import java.util.Map; +import javax.annotation.Nullable; + +/** + * MediaPipe Face Detection Solution API. + * + *

MediaPipe Face Detection processes a {@link TextureFrame} or a {@link Bitmap} and returns the + * {@link PoseTrackingResult} representing each detected face. Please refer to + * https://solutions.mediapipe.dev/face_detection#android-solution-api for usage examples. + */ +public class PoseTracking extends ImageSolutionBase { + private static final String TAG = "PoseTracking"; + + private static final String SHORT_RANGE_GRAPH_NAME = "pose_tracking_gpu.binarypb"; + private static final String FULL_RANGE_GRAPH_NAME = "face_detection_full_range_image.binarypb"; + private static final String IMAGE_INPUT_STREAM = "input_video"; + private static final ImmutableList OUTPUT_STREAMS = + ImmutableList.of("pose_detection", "throttled_input_video"); + private static final int DETECTIONS_INDEX = 0; + private static final int INPUT_IMAGE_INDEX = 1; + private final OutputHandler outputHandler; + + /** + * Initializes MediaPipe Face Detection solution. + * + * @param context an Android {@link Context}. + * @param options the configuration options defined in {@link PoseTrackingOptions}. + */ + public PoseTracking(Context context, PoseTrackingOptions options) { + outputHandler = new OutputHandler<>(); + outputHandler.setOutputConverter( + packets -> { + PoseTrackingResult.Builder poseTrackingResultBuilder = PoseTrackingResult.builder(); + try { + poseTrackingResultBuilder.setMultiPoseTrackings( + getProtoVector(packets.get(DETECTIONS_INDEX), Detection.parser())); + } catch (MediaPipeException e) { + reportError("Error occurs while getting MediaPipe pose tracking results.", e); + } + return poseTrackingResultBuilder + .setImagePacket(packets.get(INPUT_IMAGE_INDEX)) + .setTimestamp( + staticImageMode ? Long.MIN_VALUE : packets.get(INPUT_IMAGE_INDEX).getTimestamp()) + .build(); + }); + + SolutionInfo solutionInfo = + SolutionInfo.builder() + .setBinaryGraphPath( + options.modelSelection() == 0 ? SHORT_RANGE_GRAPH_NAME : FULL_RANGE_GRAPH_NAME) + .setImageInputStreamName(IMAGE_INPUT_STREAM) + .setOutputStreamNames(OUTPUT_STREAMS) + .setStaticImageMode(options.staticImageMode()) + .build(); + + initialize(context, solutionInfo, outputHandler); + Map emptyInputSidePackets = new HashMap<>(); + start(emptyInputSidePackets); + } + + /** + * Sets a callback to be invoked when a {@link PoseTrackingResult} becomes available. + * + * @param listener the {@link ResultListener} callback. + */ + public void setResultListener(ResultListener listener) { + this.outputHandler.setResultListener(listener); + } + + /** + * Sets a callback to be invoked when the Face Detection solution throws errors. + * + * @param listener the {@link ErrorListener} callback. + */ + public void setErrorListener(@Nullable ErrorListener listener) { + this.outputHandler.setErrorListener(listener); + this.errorListener = listener; + } +} diff --git a/mediapipe/java/com/google/mediapipe/solutions/posetracking/PoseTrackingOptions.java b/mediapipe/java/com/google/mediapipe/solutions/posetracking/PoseTrackingOptions.java new file mode 100644 index 000000000..908c4cc74 --- /dev/null +++ b/mediapipe/java/com/google/mediapipe/solutions/posetracking/PoseTrackingOptions.java @@ -0,0 +1,61 @@ +// 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.solutions.posetracking; + +import com.google.auto.value.AutoValue; + +/** + * MediaPipe Face Detection solution-specific options. + * + *

staticImageMode: Whether to treat the input images as a batch of static and possibly unrelated + * images, or a video stream. Default to false. See details in + * https://solutions.mediapipe.dev/face_detection#static_image_mode. + * + *

minDetectionConfidence: Minimum confidence value ([0.0, 1.0]) for face detection to be + * considered successful. See details in + * https://solutions.mediapipe.dev/face_detection#min_detection_confidence. + * + *

modelSelection: 0 or 1. 0 to select a short-range model that works best for faces within 2 + * meters from the camera, and 1 for a full-range model best for faces within 5 meters. See details + * in https://solutions.mediapipe.dev/face_detection#model_selection. + */ +@AutoValue +public abstract class PoseTrackingOptions { + public abstract boolean staticImageMode(); + + public abstract int modelSelection(); + + public abstract float minDetectionConfidence(); + + public static Builder builder() { + return new AutoValue_PoseTrackingOptions.Builder().withDefaultValues(); + } + + /** Builder for {@link PoseTrackingOptions}. */ + @AutoValue.Builder + public abstract static class Builder { + public Builder withDefaultValues() { + return setStaticImageMode(false).setModelSelection(0).setMinDetectionConfidence(0.5f); + } + + public abstract Builder setStaticImageMode(boolean value); + + public abstract Builder setModelSelection(int value); + + public abstract Builder setMinDetectionConfidence(float value); + + public abstract PoseTrackingOptions build(); + } +} diff --git a/mediapipe/java/com/google/mediapipe/solutions/posetracking/PoseTrackingResult.java b/mediapipe/java/com/google/mediapipe/solutions/posetracking/PoseTrackingResult.java new file mode 100644 index 000000000..b82989f73 --- /dev/null +++ b/mediapipe/java/com/google/mediapipe/solutions/posetracking/PoseTrackingResult.java @@ -0,0 +1,65 @@ +// 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.solutions.posetracking; + +import android.graphics.Bitmap; +import com.google.auto.value.AutoBuilder; +import com.google.common.collect.ImmutableList; +import com.google.mediapipe.framework.Packet; +import com.google.mediapipe.framework.TextureFrame; +import com.google.mediapipe.solutioncore.ImageSolutionResult; +import com.google.mediapipe.formats.proto.DetectionProto.Detection; +import java.util.List; + +/** + * FaceDetectionResult contains the detected faces, and the input {@link Bitmap} or {@link + * TextureFrame}. If not in static image mode, the timestamp field will be set to the timestamp of + * the corresponding input image. + */ +public class PoseTrackingResult extends ImageSolutionResult { + private final ImmutableList multiPoseTrackings; + + PoseTrackingResult( + ImmutableList multiPoseTrackings, Packet imagePacket, long timestamp) { + this.multiPoseTrackings = multiPoseTrackings; + this.timestamp = timestamp; + this.imagePacket = imagePacket; + } + + // Collection of detected faces, where each face is represented as a detection proto message that + // contains a bounding box and 6 {@link FaceKeypoint}s. The bounding box is composed of xmin and + // width (both normalized to [0.0, 1.0] by the image width) and ymin and height (both normalized + // to [0.0, 1.0] by the image height). Each keypoint is composed of x and y, which are normalized + // to [0.0, 1.0] by the image width and height respectively. + public ImmutableList multiPoseTrackings() { + return multiPoseTrackings; + } + + public static Builder builder() { + return new AutoBuilder_PoseTrackingResult_Builder(); + } + + /** Builder for {@link PoseTrackingResult}. */ + @AutoBuilder + public abstract static class Builder { + abstract Builder setMultiPoseTrackings(List value); + + abstract Builder setTimestamp(long value); + + abstract Builder setImagePacket(Packet value); + + abstract PoseTrackingResult build(); + } +}