added android demo

This commit is contained in:
Mautisim Munir 2022-10-19 19:12:59 +05:00
parent 4e7bcb8124
commit f899deaafd
30 changed files with 350 additions and 32 deletions

View File

@ -415,6 +415,7 @@ maven_install(
"com.google.guava:listenablefuture:1.0",
"junit:junit:4.12",
"org.hamcrest:hamcrest-library:1.3",
"com.afollestad.material-dialogs:core:0.9.6.0",
],
fetch_sources = True,
repositories = [

View File

@ -25,7 +25,7 @@ android_binary(
"applicationId": "com.google.mediapipe.examples.posetracking_lindera",
},
multidex = "native",
resource_files = ["//mediapipe/examples/android/solutions:resource_files"],
resource_files = [":resource_files"],
deps = [
"//mediapipe/framework/formats:detection_java_proto_lite",
"//mediapipe/framework/formats:landmark_java_proto_lite",
@ -48,5 +48,12 @@ android_binary(
"@maven//:androidx_exifinterface_exifinterface",
"@maven//:androidx_fragment_fragment",
"@maven//:com_google_guava_guava",
"@maven//:com_afollestad_material_dialogs_core",
],
)
filegroup(
name = "resource_files",
srcs = glob(["res/**"]),
# visibility = ["//mediapipe/examples/android/solutions:__subpackages__"],
)

View File

@ -15,17 +15,24 @@
package com.google.mediapipe.examples.posetracking_lindera;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import androidx.appcompat.app.AppCompatActivity;
import com.afollestad.materialdialogs.MaterialDialog;
import com.google.mediapipe.solutions.lindera.CameraRotation;
import com.google.mediapipe.solutions.lindera.ComputerVisionPlugin;
import com.google.mediapipe.solutions.lindera.Lindera;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
@ -47,8 +54,8 @@ public class MainActivity extends AppCompatActivity {
setContentView(R.layout.activity_main);
disableRedundantUI();
findViewById(R.id.button_set_model).setVisibility(View.GONE);
findViewById(R.id.button_toggle_landmarks).setVisibility(View.GONE);
setupLiveDemoUiComponents();
plugin = new ComputerVisionPluginImpl();
lindera = new Lindera(plugin);
@ -65,45 +72,125 @@ public class MainActivity extends AppCompatActivity {
*/
private void setupLiveDemoUiComponents() {
Button startCameraButton = findViewById(R.id.button_start_camera);
Button startDetectionButton = findViewById(R.id.button_start_detection);
Button toggleLandmarks = findViewById(R.id.button_toggle_landmarks);
Button modelComplexity = findViewById(R.id.button_set_model);
FrameLayout frameLayout = findViewById(R.id.preview_display_layout);
startCameraButton.setOnClickListener(
startDetectionButton.setOnClickListener(
v -> {
// startCameraButton.setVisibility(View.GONE);
if (!isLinderaInitialized) {
lindera.initialize(frameLayout, MainActivity.this);
isLinderaInitialized = true;
startCameraButton.setText("STOP CAMERA");
modelLoadAsyncDialogue(()->{
lindera.initialize(frameLayout, MainActivity.this);
isLinderaInitialized = true;
startDetectionButton.setVisibility(View.GONE);
findViewById(R.id.button_set_model).setVisibility(View.VISIBLE);
findViewById(R.id.button_toggle_landmarks).setVisibility(View.VISIBLE);
updateLandmarkButtonText();
updateModelComplexityButtonText();
});
} else {
if (isDetectionStarted) {
startCameraButton.setText(R.string.start_camera);
lindera.stopDetection();
} else {
lindera.startDetection();
startCameraButton.setText("STOP CAMERA");
}
}
isDetectionStarted = !isDetectionStarted;
});
}
/**
* 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);
toggleLandmarks.setOnClickListener(
v ->{
this.lindera.setLandmarksVisibility(!this.lindera.getLandmarkVisibility());
updateLandmarkButtonText();
}
);
modelComplexity.setOnClickListener(v->{
int modelComplexityVal = lindera.getModelComplexity();
new MaterialDialog.Builder(this)
.title("Choose Model Complexity")
.items(Arrays.asList("Lite","Full","Heavy"))
.itemsCallbackSingleChoice(modelComplexityVal, new MaterialDialog.ListCallbackSingleChoice() {
@Override
public boolean onSelection(MaterialDialog dialog, View view, int which, CharSequence text) {
/**
* If you use alwaysCallSingleChoiceCallback(), which is discussed below,
* returning false here won't allow the newly selected radio button to actually be selected.
**/
if (which != modelComplexityVal){
modelLoadAsyncDialogue(()-> {
lindera.setModelComplexity(which);
lindera.restartDetection();
updateModelComplexityButtonText();
});
}
return true;
}
})
.positiveText("choose")
.show();
// listItemsSingleChoice(R.array.my_items, initialSelection = 1);
});
}
void updateLandmarkButtonText(){
Button toggleLandmarks = findViewById(R.id.button_toggle_landmarks);
if (this.lindera.getLandmarkVisibility()) {
toggleLandmarks.setText("Show Landmarks (On)");
}else{
toggleLandmarks.setText("Show Landmarks (Off)");
}
}
void updateModelComplexityButtonText(){
String text = "Select Model ";
switch (this.lindera.getModelComplexity()){
case 0:
text += "(lite)";
break;
case 1:
text += "(full)";
break;
case 2:
text += "(heavy)";
break;
}
Button setModel = findViewById(R.id.button_set_model);
setModel.setText(text);
}
void modelLoadAsyncDialogue(Runnable loader){
ProgressBar pbar = new ProgressBar(this);
MaterialDialog dialog = new MaterialDialog.Builder(this)
.title("Loading Model")
.customView(pbar, false)
.build();
dialog.show();
ExecutorService executor = Executors.newSingleThreadExecutor();
Handler handler = new Handler(Looper.getMainLooper());
executor.execute(new Runnable() {
@Override
public void run() {
//Background work here
handler.post(loader);
dialog.dismiss();
}
});
}
}

View File

@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportHeight="108"
android:viewportWidth="108">
<path
android:fillType="evenOdd"
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
android:strokeColor="#00000000"
android:strokeWidth="1">
<aapt:attr name="android:fillColor">
<gradient
android:endX="78.5885"
android:endY="90.9159"
android:startX="48.7653"
android:startY="61.0927"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
android:strokeColor="#00000000"
android:strokeWidth="1" />
</vector>

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
android:height="108dp"
android:width="108dp"
android:viewportHeight="108"
android:viewportWidth="108"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#26A69A"
android:pathData="M0,0h108v108h-108z"/>
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
</vector>

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?android:attr/buttonBarStyle" android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/button_start_detection"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Detection" />
<Button
android:id="@+id/button_toggle_landmarks"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show Landmarks" />
<Button
android:id="@+id/button_set_model"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Set Model" />
</LinearLayout>
<FrameLayout
android:id="@+id/preview_display_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/no_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/instruction" />
</FrameLayout>
</LinearLayout>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 959 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
</resources>

View File

@ -0,0 +1,6 @@
<resources>
<string name="load_picture" translatable="false">Load Picture</string>
<string name="load_video" translatable="false">Load Video</string>
<string name="start_camera" translatable="false">Start Camera</string>
<string name="instruction" translatable="false">Please press any button above to start</string>
</resources>

View File

@ -0,0 +1,11 @@
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>

View File

@ -37,6 +37,33 @@ public class Lindera {
this.plugin = plugin;
}
public void setLandmarksVisibility(boolean visible){
this.poseTracking.options = PoseTrackingOptions.builder().withPoseTrackingOptions(this.poseTracking
.options).setLandmarkVisibility(visible).build();
}
public boolean getLandmarkVisibility(){
return this.poseTracking.options.landmarkVisibility();
}
public int getModelComplexity(){
return this.poseTracking.options.modelComplexity();
}
public void setModelComplexity(int complexity){
this.poseTracking.options = PoseTrackingOptions.builder().withPoseTrackingOptions(this.poseTracking
.options).setModelComplexity(complexity).build();
}
public void restartDetection(){
if (poseTracking!=null) {
stopDetection();
startDetection(poseTracking.options);
}else{
startDetection();
}
}
public void initialize (ViewGroup computerVisionContainerView , AppCompatActivity appCompatActivity){
this.computerVisionContainerView = computerVisionContainerView;
@ -101,6 +128,7 @@ public class Lindera {
);
}
public void startDetection(PoseTrackingOptions options){
// ensure that class is initalized
assert (appCompatActivity != null);

View File

@ -53,14 +53,15 @@ public class PoseTracking extends ImageSolutionBase {
private static final int OUTPUT_IMAGE_INDEX = 2;
private static final int LANDMARKS_INDEX = 3;
private final OutputHandler<PoseTrackingResult> outputHandler;
public PoseTrackingOptions options;
/**
* Initializes MediaPipe Face Detection solution.
*
* @param context an Android {@link Context}.
* @param options the configuration options defined in {@link PoseTrackingOptions}.
* @param poseTrackingOptions the configuration options defined in {@link PoseTrackingOptions}.
*/
public PoseTracking(Context context, PoseTrackingOptions options) {
public PoseTracking(Context context, PoseTrackingOptions poseTrackingOptions) {
options = poseTrackingOptions;
outputHandler = new OutputHandler<>();
outputHandler.setOutputConverter(
packets -> {

View File

@ -56,6 +56,13 @@ public abstract class PoseTrackingOptions {
.setMinDetectionConfidence(0.5f)
.setSmoothLandmarks(true);
}
public Builder withPoseTrackingOptions(PoseTrackingOptions options){
return setStaticImageMode(options.staticImageMode())
.setModelComplexity(options.modelComplexity())
.setMinDetectionConfidence(options.minDetectionConfidence())
.setSmoothLandmarks(options.smoothLandmarks())
.setLandmarkVisibility(options.landmarkVisibility());
}
public abstract Builder setStaticImageMode(boolean value);