Skip to content

Commit

Permalink
add readme
Browse files Browse the repository at this point in the history
  • Loading branch information
duy-maimanh committed Jan 5, 2024
1 parent bbe2914 commit a3531bf
Show file tree
Hide file tree
Showing 53 changed files with 147 additions and 106 deletions.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
.externalNativeBuild
.cxx
local.properties
/app/src/main/assets/tasks/holistic_landmarker.task
*.task
48 changes: 48 additions & 0 deletions examples/holistic_landmarker/android/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# MediaPipe Tasks Holistic Landmark Detection Android Demo

### Overview

This is a camera app that continuously detects the body, hand, and face
landmarks in the frames seen by your device's back camera, using a
custom **task** file.

The task file is downloaded by a Gradle script when you build and run the app.
You don't need to do any additional steps to download task files into the
project explicitly unless you wish to use your own landmark detection task. If
you do use your own task file, place it into the app's assets/tasks directory.

This application should be run on physical Android devices with a back camera.

![Holistic Landmarker Demo](screenshot.jpg?raw=true "Holistic Landmarker Demo")

## Build the demo using Android Studio

### Prerequisites

* The **[Android Studio](https://developer.android.com/studio/index.html)** IDE.
This sample has been tested on Android Studio Giraffe.

* A physical Android device with a minimum OS version of SDK 24 (Android 7.0 -
Nougat) with developer mode enabled. The process of enabling developer mode
may vary by device.

### Building

* Open Android Studio. From the Welcome screen, select Open an existing
Android Studio project.

* From the Open File or Project window that appears, navigate to and select
the mediapipe/examples/holistic_landmarker/android directory. Click OK. You
may
be asked if you trust the project. Select Trust.

* If it asks you to do a Gradle Sync, click OK.

* With your Android device connected to your computer and developer mode
enabled, click on the green Run arrow in Android Studio.

### Models used

Downloading, extraction, and placing the models into the *assets/tasks* folder
is
managed automatically by the **app/build.gradle.kts** file.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.google.mediapipe.examples.holisticlandmarker

/*
* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
* Copyright 2024 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -196,7 +196,9 @@ class HolisticLandmarkerHelper(
} catch (e: MediaPipeException) {
resultList.add(null);
}
}
} ?: kotlin.run {
resultList.add(null);
}
}

retriever.release()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.google.mediapipe.examples.holisticlandmarker

/*
* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
* Copyright 2024 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.google.mediapipe.examples.holisticlandmarker

/*
* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
* Copyright 2024 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.google.mediapipe.examples.holisticlandmarker

/*
* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
* Copyright 2024 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -93,8 +93,8 @@ class OverlayView(context: Context?, attrs: AttributeSet?) :
)
// convert bytebuffer to bitmap
val bitmap = Bitmap.createBitmap(
results?.segmentationMask()!!.get().width,
results?.segmentationMask()!!.get().height,
imageWidth,
imageHeight,
Bitmap.Config.ARGB_8888
)
bitmap.copyPixelsFromBuffer(buffer)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.google.mediapipe.examples.holisticlandmarker.fragments

/*
* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
* Copyright 2024 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -43,8 +43,9 @@ import com.google.mediapipe.examples.holisticlandmarker.R
import com.google.mediapipe.examples.holisticlandmarker.HelperState
import com.google.mediapipe.examples.holisticlandmarker.databinding.FragmentCameraBinding
import com.google.mediapipe.tasks.vision.core.RunningMode
import java.util.*
import java.util.concurrent.*
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit

class CameraFragment() : Fragment(),
HolisticLandmarkerHelper.LandmarkerListener {
Expand Down Expand Up @@ -219,19 +220,35 @@ class CameraFragment() : Fragment(),
}

private fun updateBottomSheetControlsUi(helperState: HelperState) {
val isFaceBlendShapes =
if (helperState.delegate == HolisticLandmarkerHelper.DELEGATE_CPU) helperState.isFaceBlendMode else false
val isPoseSegmentationMarks =
if (helperState.delegate == HolisticLandmarkerHelper.DELEGATE_CPU) helperState.isPoseSegmentationMarks else false

// update bottom sheet settings
with(fragmentCameraBinding.bottomSheetLayout){
faceLandmarksThresholdValue.text = helperState.minFaceLandmarkThreshold.toString()
poseLandmarksThresholdValue.text = helperState.minPoseLandmarkThreshold.toString()
handLandmarksThresholdValue.text = helperState.minHandLandmarkThreshold.toString()
faceDetectionThresholdValue.text = helperState.minFaceDetectionThreshold.toString()
poseDetectionThresholdValue.text = helperState.minPoseDetectionThreshold.toString()
faceSuppressionValue.text = helperState.minFaceSuppressionThreshold.toString()
poseSuppressionValue.text = helperState.minPoseSuppressionThreshold.toString()
switchFaceBlendShapes.isChecked = helperState.isFaceBlendMode
switchPoseSegmentationMarks.isChecked = helperState.isPoseSegmentationMarks
with(fragmentCameraBinding.bottomSheetLayout) {
faceLandmarksThresholdValue.text =
helperState.minFaceLandmarkThreshold.toString()
poseLandmarksThresholdValue.text =
helperState.minPoseLandmarkThreshold.toString()
handLandmarksThresholdValue.text =
helperState.minHandLandmarkThreshold.toString()
faceDetectionThresholdValue.text =
helperState.minFaceDetectionThreshold.toString()
poseDetectionThresholdValue.text =
helperState.minPoseDetectionThreshold.toString()
faceSuppressionValue.text =
helperState.minFaceSuppressionThreshold.toString()
poseSuppressionValue.text =
helperState.minPoseSuppressionThreshold.toString()
// enable with CPU delegate
switchFaceBlendShapes.isChecked = isFaceBlendShapes
switchPoseSegmentationMarks.isChecked = isPoseSegmentationMarks
switchFaceBlendShapes.isEnabled =
helperState.delegate == HolisticLandmarkerHelper.DELEGATE_CPU
switchPoseSegmentationMarks.isEnabled =
helperState.delegate == HolisticLandmarkerHelper.DELEGATE_CPU
}

// Create the HolisticLandmarkerHelper that will handle the inference
backgroundExecutor.execute {
// clear it and recreate with new settings
Expand All @@ -246,8 +263,8 @@ class CameraFragment() : Fragment(),
minPoseDetectionConfidence = helperState.minPoseDetectionThreshold,
minFaceSuppressionThreshold = helperState.minFaceSuppressionThreshold,
minPoseSuppressionThreshold = helperState.minPoseSuppressionThreshold,
isFaceBlendShapes = helperState.isFaceBlendMode,
isPoseSegmentationMark = helperState.isPoseSegmentationMarks,
isFaceBlendShapes = isFaceBlendShapes,
isPoseSegmentationMark = isPoseSegmentationMarks,
landmarkerHelperListener = this
)
_fragmentCameraBinding?.overlay?.clear()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
* Copyright 2024 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.google.mediapipe.examples.holisticlandmarker.fragments

/*
* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
* Copyright 2024 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -40,7 +40,9 @@ import com.google.mediapipe.examples.holisticlandmarker.MainViewModel
import com.google.mediapipe.examples.holisticlandmarker.R
import com.google.mediapipe.examples.holisticlandmarker.databinding.FragmentGalleryBinding
import com.google.mediapipe.tasks.vision.core.RunningMode
import java.util.concurrent.*
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit

class GalleryFragment : Fragment(),
HolisticLandmarkerHelper.LandmarkerListener {
Expand Down Expand Up @@ -182,26 +184,39 @@ class GalleryFragment : Fragment(),
}
}

private fun updateBottomSheetControlsUi(uiState: HelperState) {
private var isFaceBlendShapes = false
private var isPoseSegmentationMarks = false

private fun updateBottomSheetControlsUi(helperState: HelperState) {
isFaceBlendShapes =
if (helperState.delegate == HolisticLandmarkerHelper.DELEGATE_CPU) helperState.isFaceBlendMode else false
isPoseSegmentationMarks =
if (helperState.delegate == HolisticLandmarkerHelper.DELEGATE_CPU) helperState.isPoseSegmentationMarks else false


// init bottom sheet settings
with(fragmentGalleryBinding.bottomSheetLayout) {
faceLandmarksThresholdValue.text =
uiState.minFaceLandmarkThreshold.toString()
helperState.minFaceLandmarkThreshold.toString()
poseLandmarksThresholdValue.text =
uiState.minPoseLandmarkThreshold.toString()
helperState.minPoseLandmarkThreshold.toString()
handLandmarksThresholdValue.text =
uiState.minHandLandmarkThreshold.toString()
helperState.minHandLandmarkThreshold.toString()
faceDetectionThresholdValue.text =
uiState.minFaceDetectionThreshold.toString()
helperState.minFaceDetectionThreshold.toString()
poseDetectionThresholdValue.text =
uiState.minPoseDetectionThreshold.toString()
helperState.minPoseDetectionThreshold.toString()
faceSuppressionValue.text =
uiState.minFaceSuppressionThreshold.toString()
helperState.minFaceSuppressionThreshold.toString()
poseSuppressionValue.text =
uiState.minPoseSuppressionThreshold.toString()
switchFaceBlendShapes.isChecked = uiState.isFaceBlendMode
switchPoseSegmentationMarks.isChecked =
uiState.isPoseSegmentationMarks
helperState.minPoseSuppressionThreshold.toString()
// enable with CPU delegate
switchFaceBlendShapes.isChecked = isFaceBlendShapes
switchPoseSegmentationMarks.isChecked = isPoseSegmentationMarks
switchFaceBlendShapes.isEnabled =
helperState.delegate == HolisticLandmarkerHelper.DELEGATE_CPU
switchPoseSegmentationMarks.isEnabled =
helperState.delegate == HolisticLandmarkerHelper.DELEGATE_CPU
}
clearView()
}
Expand All @@ -223,7 +238,7 @@ class GalleryFragment : Fragment(),
}.copy(Bitmap.Config.ARGB_8888, true)?.let { bitmap ->
fragmentGalleryBinding.imageResult.setImageBitmap(bitmap)

// Run face landmarker on the input image
// Run holistic landmarker on the input image
backgroundExecutor.execute {
viewModel.helperState.value?.let {
holisticLandmarkerHelper = HolisticLandmarkerHelper(
Expand All @@ -237,8 +252,8 @@ class GalleryFragment : Fragment(),
minPoseDetectionConfidence = it.minPoseDetectionThreshold,
minFaceSuppressionThreshold = it.minFaceSuppressionThreshold,
minPoseSuppressionThreshold = it.minPoseSuppressionThreshold,
isFaceBlendShapes = it.isFaceBlendMode,
isPoseSegmentationMark = it.isPoseSegmentationMarks,
isFaceBlendShapes = isFaceBlendShapes,
isPoseSegmentationMark = isPoseSegmentationMarks,
landmarkerHelperListener = this
)
}
Expand Down Expand Up @@ -270,7 +285,7 @@ class GalleryFragment : Fragment(),
setUiEnabled(true)
}
Log.e(
TAG, "Error running face landmarker."
TAG, "Error running holistic landmarker."
)
}

Expand Down Expand Up @@ -322,8 +337,8 @@ class GalleryFragment : Fragment(),
minPoseDetectionConfidence = it.minPoseDetectionThreshold,
minFaceSuppressionThreshold = it.minFaceSuppressionThreshold,
minPoseSuppressionThreshold = it.minPoseSuppressionThreshold,
isFaceBlendShapes = it.isFaceBlendMode,
isPoseSegmentationMark = it.isPoseSegmentationMarks,
isFaceBlendShapes = isFaceBlendShapes,
isPoseSegmentationMark = isPoseSegmentationMarks,
landmarkerHelperListener = this
)
}
Expand All @@ -338,7 +353,7 @@ class GalleryFragment : Fragment(),
activity?.runOnUiThread { displayVideoResult(resultBundle) }
} ?: run {
setUiEnabled(true)
Log.e(TAG, "Error running face landmarker.")
Log.e(TAG, "Error running holistic landmarker.")
}

holisticLandmarkerHelper.clearHolisticLandmarker()
Expand Down Expand Up @@ -428,8 +443,11 @@ class GalleryFragment : Fragment(),
poseSuppressionMinus.isEnabled = enabled
poseSuppressionPlus.isEnabled = enabled
switchFaceBlendShapes.isEnabled = enabled
switchPoseSegmentationMarks.isEnabled = enabled
spinnerDelegate.isEnabled = enabled
// only enable with CPU delegate
switchPoseSegmentationMarks.isEnabled =
if (viewModel.helperState.value?.delegate == HolisticLandmarkerHelper.DELEGATE_CPU) enabled else false
spinnerDelegate.isEnabled =
if (viewModel.helperState.value?.delegate == HolisticLandmarkerHelper.DELEGATE_CPU) enabled else false
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.google.mediapipe.examples.holisticlandmarker.fragments

/*
* Copyright 2023 The TensorFlow Authors. All Rights Reserved.
* Copyright 2024 The TensorFlow Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2023 The TensorFlow Authors. All Rights Reserved.
~ Copyright 2024 The TensorFlow Authors. All Rights Reserved.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
Expand Down
Loading

0 comments on commit a3531bf

Please sign in to comment.