google-ai-edge / mediapipe

Cross-platform, customizable ML solutions for live and streaming media.
https://ai.google.dev/edge/mediapipe
Apache License 2.0
27.76k stars 5.18k forks source link

how can i use landmarks_smoothing_calculator in the face mesh solution #4166

Open BTLDXX-x opened 1 year ago

BTLDXX-x commented 1 year ago

Have I written custom code (as opposed to using a stock example script provided in MediaPipe)

None

OS Platform and Distribution

android

MediaPipe version

latest

Bazel version

5.2.0

Solution

FaceMesh

Programming Language and version

java

Describe the actual behavior

hello, 
i am using the face mesh solution at android platform.

in the build.gradle:
    // MediaPipe Face Mesh Solution.
    implementation 'com.google.mediapipe:solution-core:latest.release'
    implementation 'com.google.mediapipe:facemesh:latest.release'

my FaceMeshResultGlRenderer class implements ResultGlRenderer<FaceMeshResult>. it is used to render the FaceMeshResult, but i have a jittering problem. 
i found that the face effect has used landmarks_smoothing_calculator, but i don't know how to use. should i custom a new graph? if it is, how can i write the .pbtxt file?

Describe the expected behaviour

No response

Standalone code/steps you may have used to try to get what you need

No response

Other info / Complete Logs

No response

BTLDXX-x commented 1 year ago

my face_mesh_smooth.pbtxt:

# MediaPipe graph that performs face mesh with TensorFlow Lite on GPU.

# GPU buffer. (GpuBuffer)
input_stream: "input_video"

# Max number of faces to detect/process. (int)
input_side_packet: "num_faces"

# Output image with rendered results. (GpuBuffer)
output_stream: "output_video"
# Collection of detected/processed faces, each represented as a list of
# landmarks. (std::vector<NormalizedLandmarkList>)
output_stream: "smoothed_face_landmarks"

# 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
# passes through another image. All images that come in while waiting are
# dropped, limiting the number of in-flight images in most part of the graph to
# 1. This prevents the downstream nodes from queuing up incoming images and data
# excessively, which leads to increased latency and memory usage, unwanted in
# 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"
  input_stream: "FINISHED:output_video"
  input_stream_info: {
    tag_index: "FINISHED"
    back_edge: true
  }
  output_stream: "throttled_input_video"
}

# Defines side packets for further use in the graph.
node {
  calculator: "ConstantSidePacketCalculator"
  output_side_packet: "PACKET:with_attention"
  node_options: {
    [type.googleapis.com/mediapipe.ConstantSidePacketCalculatorOptions]: {
      packet { bool_value: true }
    }
  }
}

# Subgraph that detects faces and corresponding landmarks.
node {
  calculator: "FaceLandmarkFrontGpu"
  input_stream: "IMAGE:throttled_input_video"
  input_side_packet: "NUM_FACES:num_faces"
  input_side_packet: "WITH_ATTENTION:with_attention"
  output_stream: "LANDMARKS:multi_face_landmarks"
  output_stream: "ROIS_FROM_LANDMARKS:face_rects_from_landmarks"
  output_stream: "DETECTIONS:face_detections"
  output_stream: "ROIS_FROM_DETECTIONS:face_rects_from_detections"
}

# Extracts a single set of face landmarks associated with the most prominent
# face detected from a collection.
node {
  calculator: "SplitNormalizedLandmarkListVectorCalculator"
  input_stream: "multi_face_landmarks"
  output_stream: "face_landmarks"
  node_options: {
    [type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
      ranges: { begin: 0 end: 1 }
      element_only: true
    }
  }
}

# Extracts the input image frame dimensions as a separate packet.
node {
  calculator: "ImagePropertiesCalculator"
  input_stream: "IMAGE:throttled_input_video"
  output_stream: "SIZE:input_image_size"
}

# Applies smoothing to the single set of face landmarks.
node {
  calculator: "FaceLandmarksSmoothing"
  input_stream: "NORM_LANDMARKS:face_landmarks"
  input_stream: "IMAGE_SIZE:input_image_size"
  output_stream: "NORM_FILTERED_LANDMARKS:smoothed_face_landmarks"
}

# Subgraph that renders face-landmark annotation onto the input image.
node {
  calculator: "FaceRendererGpu"
  input_stream: "IMAGE:throttled_input_video"
  input_stream: "LANDMARKS:smoothed_face_landmarks"
  input_stream: "NORM_RECTS:face_rects_from_landmarks"
  input_stream: "DETECTIONS:face_detections"
  output_stream: "IMAGE:output_video"
}

the BUILD file:

load(
    "//mediapipe/framework/tool:mediapipe_graph.bzl",
    "mediapipe_binary_graph",
)

licenses(["notice"])

package(default_visibility = ["//visibility:public"])

cc_library(
    name = "mobile_calculators",
    deps = [
        "//mediapipe/calculators/core:flow_limiter_calculator",
        "//mediapipe/graphs/face_mesh_smooth/subgraphs:face_renderer_gpu",
        "//mediapipe/graphs/face_mesh_smooth/subgraphs:face_landmarks_smoothing",
        "//mediapipe/modules/face_landmark:face_landmark_front_gpu",
    ],
)

mediapipe_binary_graph(
    name = "face_mesh_mobile_gpu_binary_graph",
    graph = "face_mesh_smooth.pbtxt",
    output_name = "face_mesh_mobile_gpu.binarypb",
    deps = [":mobile_calculators"],
)

i followed the doc to build the aar. But i met a problem:

unknown: Input stream "throttled_input_video" of calculator "facelandmarkfrontgpu__ImagePropertiesCalculator_2" expects packets of type "mediapipe::GpuBuffer" 
but the connected output stream will contain packets of type "[Same Type As OneOf<::mediapipe::Image, mediapipe::ImageFrame>]"

what should i do to solve this problem? thanks very much

ayushgdev commented 1 year ago

This error is occurring since the data types of the input and output streams are not compatible. The error is thrown from validated_graph_config.cc -> ValidatedGraphConfig::ValidateStreamTypes() if the input stream/input edge and index of the corresponding output stream which produces the data this edge will see, are not same. In your case, Image tag is used for input stream to ImagePropertiesCalculator. With that tag, the width and height of the input stream will be derived by treating the input as Image or ImageFrame. However, since you are running a GPU based computation, you are providing GpuBuffer. Hence you should be using IMAGE_GPU as the input_stream tag so that this block will be triggered.

BTLDXX-x commented 1 year ago

hi @ayushgdev, i have solved that error, but i have a new question. the FaceLandmarksSmoothing seems process single face landmarks only, how can i process multi face landmarks?

BTLDXX-x commented 1 year ago

i deleted the node:

# Extracts a single set of face landmarks associated with the most prominent
# face detected from a collection.
node {
  calculator: "SplitNormalizedLandmarkListVectorCalculator"
  input_stream: "multi_face_landmarks"
  output_stream: "face_landmarks"
  node_options: {
    [type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
      ranges: { begin: 0 end: 1 }
      element_only: true
    }
  }
}

changed face_mesh_smooth.pbtxt:

# MediaPipe graph that performs face mesh with TensorFlow Lite on GPU.

# GPU buffer. (GpuBuffer)
input_stream: "input_video"

# Max number of faces to detect/process. (int)
input_side_packet: "num_faces"

# Output image with rendered results. (GpuBuffer)
output_stream: "output_video"
# Collection of detected/processed faces, each represented as a list of
# landmarks. (std::vector<NormalizedLandmarkList>)
output_stream: "smoothed_face_landmarks"

# 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
# passes through another image. All images that come in while waiting are
# dropped, limiting the number of in-flight images in most part of the graph to
# 1. This prevents the downstream nodes from queuing up incoming images and data
# excessively, which leads to increased latency and memory usage, unwanted in
# 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"
  input_stream: "FINISHED:output_video"
  input_stream_info: {
    tag_index: "FINISHED"
    back_edge: true
  }
  output_stream: "throttled_input_video"
}

# Defines side packets for further use in the graph.
node {
  calculator: "ConstantSidePacketCalculator"
  output_side_packet: "PACKET:with_attention"
  node_options: {
    [type.googleapis.com/mediapipe.ConstantSidePacketCalculatorOptions]: {
      packet { bool_value: true }
    }
  }
}

# Subgraph that detects faces and corresponding landmarks.
node {
  calculator: "FaceLandmarkFrontGpu"
  input_stream: "IMAGE:throttled_input_video"
  input_side_packet: "NUM_FACES:num_faces"
  input_side_packet: "WITH_ATTENTION:with_attention"
  output_stream: "LANDMARKS:multi_face_landmarks"
  output_stream: "ROIS_FROM_LANDMARKS:face_rects_from_landmarks"
  output_stream: "DETECTIONS:face_detections"
  output_stream: "ROIS_FROM_DETECTIONS:face_rects_from_detections"
}

# Extracts the input image frame dimensions as a separate packet.
node {
  calculator: "ImagePropertiesCalculator"
  input_stream: "IMAGE_GPU:throttled_input_video"
  output_stream: "SIZE:input_image_size"
}

# Applies smoothing to the multi face landmarks.
node {
  calculator: "FaceLandmarksSmoothing"
  input_stream: "NORM_LANDMARKS:multi_face_landmarks"
  input_stream: "IMAGE_SIZE:input_image_size"
  output_stream: "NORM_FILTERED_LANDMARKS:smoothed_face_landmarks"
}

# Subgraph that renders face-landmark annotation onto the input image.
node {
  calculator: "FaceRendererGpu"
  input_stream: "IMAGE:throttled_input_video"
  input_stream: "LANDMARKS:smoothed_face_landmarks"
  input_stream: "NORM_RECTS:face_rects_from_landmarks"
  input_stream: "DETECTIONS:face_detections"
  output_stream: "IMAGE:output_video"
}

the error:

unknown: Input stream "multi_face_landmarks" of calculator "facelandmarkssmoothing__LandmarksSmoothingCalculator" expects packets of type "mediapipe::NormalizedLandmarkList" 
but the connected output stream will contain packets of type "std::__ndk1::vector<mediapipe::NormalizedLandmarkList, std::__ndk1::allocator<mediapipe::NormalizedLandmarkList> >"
BTLDXX-x commented 1 year ago

hi, @ayushgdev I found BeginLoopNormalizedLandmarkListVectorCalculator and EndLoopNormalizedLandmarkListVectorCalculator to process multi face landmarks. But when detected the face, it crashed. Here is the logcat:

---------------------------- PROCESS STARTED (9058) for package com.example.mediapipemyface ----------------------------
2023-03-14 06:51:48.165  9058-9077  ActivityThread          com.example.mediapipemyface          I  Init compatible state: true
2023-03-14 06:51:48.165  9058-9077  HwFramewor...rtsFactory com.example.mediapipemyface          D  HwFrameworkSecurityPartsFactory in.
2023-03-14 06:51:48.165  9058-9077  HwFramewor...rtsFactory com.example.mediapipemyface          I  add HwFrameworkSecurityPartsFactory to memory.
2023-03-14 06:51:48.166  9058-9077  BehaviorCollectManager  com.example.mediapipemyface          E  Fail to acquire dataAnalyzerService...
2023-03-14 06:51:48.180  9058-9058  ApplicationLoaders      com.example.mediapipemyface          D  createClassLoader zip: /data/app/com.example.mediapipemyface-0n71o32S8Iq3La0LKuj7BQ==/base.apk librarySearchPath: /data/app/com.example.mediapipemyface-0n71o32S8Iq3La0LKuj7BQ==/lib/arm64:/data/app/com.example.mediapipemyface-0n71o32S8Iq3La0LKuj7BQ==/base.apk!/lib/arm64-v8a libraryPermittedPath: /data/user/0/com.example.mediapipemyface parent: java.lang.BootClassLoader@cf47846 targetSdkVersion: 32 isBundled: false classLoaderName: null sharedLibraries: null
2023-03-14 06:51:48.181  9058-9076  HwPartIawareFactory     com.example.mediapipemyface          I  add android.common.HwPartIawareFactoryImpl to memory.
2023-03-14 06:51:48.453  9058-9077  HwApiCacheMangerEx      com.example.mediapipemyface          I  apicache path=/storage/emulated/0 state=mounted key=com.example.mediapipemyface#10132#256
2023-03-14 06:51:48.453  9058-9077  HwApiCacheMangerEx      com.example.mediapipemyface          I  need clear apicache,because volumes changed,oldCnt=0 newCnt=1
2023-03-14 06:51:48.454  9058-9077  HwApiCacheMangerEx      com.example.mediapipemyface          I  apicache path=/storage/emulated/0 state=mounted key=com.example.mediapipemyface#10132#0
2023-03-14 06:51:48.454  9058-9077  HwApiCacheMangerEx      com.example.mediapipemyface          I  need clear apicache,because volumes changed,oldCnt=1 newCnt=1
2023-03-14 06:51:48.457  9058-9077  AwareBitmapCacher       com.example.mediapipemyface          I  init processName:com.example.mediapipemyface pid=9058 uid=10132
2023-03-14 06:51:48.464  9058-9058  HwTypeface              com.example.mediapipemyface          I  updateFont: scale=1.0
2023-03-14 06:51:48.464  9058-9058  SystemFonts             com.example.mediapipemyface          D  areFontsVariable: script=Hans
2023-03-14 06:51:48.465  9058-9058  ActivityThread          com.example.mediapipemyface          I  finishPreloaded preloadStatus 0
2023-03-14 06:51:48.465  9058-9058  RmeSchedManager         com.example.mediapipemyface          I  init Rme, version is: v1.0
2023-03-14 06:51:48.465  9058-9058  RtgSchedEvent           com.example.mediapipemyface          I  current pid:9058 AppType:-1
2023-03-14 06:51:48.465  9058-9058  RmeSchedManager         com.example.mediapipemyface          I  init Rme, version is: v1.0
2023-03-14 06:51:48.469  9058-9058  OpenGLRenderer          com.example.mediapipemyface          D  disableOutlineDraw is true
2023-03-14 06:51:48.472  9058-9104  OpenGLRenderer          com.example.mediapipemyface          I  RenderThread: progress name = [com.example.mediapipemyface], viewCornerType = 0
2023-03-14 06:51:48.472  9058-9106  iGraphics               com.example.mediapipemyface          I  [0020080c] pn: com.example.mediapipemyface, p: 9058
2023-03-14 06:51:48.472  9058-9106  iGraphics               com.example.mediapipemyface          I  [0030080c] no spt app: com.example.mediapipemyface
2023-03-14 06:51:48.524  9058-9058  ActivityThread          com.example.mediapipemyface          V  callActivityOnCreate
2023-03-14 06:51:48.542  9058-9058  DecorView[]             com.example.mediapipemyface          I  pkgName:com.example.mediapipemyface old windowMode:0 new windoMode:1, isFixedSize:false
2023-03-14 06:51:48.557  9058-9058  OverScroll...timization com.example.mediapipemyface          I  start init SmartSlideOverScroller and get the overscroller config
2023-03-14 06:51:48.557  9058-9058  OverScroll...timization com.example.mediapipemyface          I  get the overscroller config
2023-03-14 06:51:48.583  9058-9058  mediapipemyfac          com.example.mediapipemyface          W  Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
2023-03-14 06:51:48.583  9058-9058  mediapipemyfac          com.example.mediapipemyface          W  Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
2023-03-14 06:51:48.649  9058-9058  native                  com.example.mediapipemyface          I  I20230314 06:51:48.649137  9058 asset_manager_util.cc:59] Created global reference to asset manager.
2023-03-14 06:51:48.655  9058-9058  libEGL                  com.example.mediapipemyface          E  validate_display:104 error 3008 (EGL_BAD_DISPLAY)
2023-03-14 06:51:48.662  9058-9058  native                  com.example.mediapipemyface          I  I20230314 06:51:48.662715  9058 gl_context_egl.cc:84] Successfully initialized EGL. Major : 1 Minor: 4
2023-03-14 06:51:48.663  9058-9123  native                  com.example.mediapipemyface          I  I20230314 06:51:48.663606  9123 gl_context.cc:342] GL version: 3.2 (OpenGL ES 3.2 v1.r18p0-01rel0.ba548f403b67fe8cf761fb65dbed7cc1)
2023-03-14 06:51:48.664  9058-9058  PermissionHelper        com.example.mediapipemyface          D  checkAndRequestCameraPermissions
2023-03-14 06:51:48.665  9058-9058  ActivityThread          com.example.mediapipemyface          D  add activity client record, r= ActivityRecord{1f07a27 token=android.os.BinderProxy@a662a7 {com.example.mediapipemyface/com.example.mediapipemyface.MainActivity}} token= android.os.BinderProxy@a662a7
2023-03-14 06:51:48.674  9058-9124  GlThread                com.example.mediapipemyface          D  Starting GL thread ExternalTextureConverter
2023-03-14 06:51:48.691  9058-9058  CameraManagerGlobal     com.example.mediapipemyface          I  Connecting to camera service
2023-03-14 06:51:48.707  9058-9058  MouseWheelSynthesizer   com.example.mediapipemyface          D  mMoveStepInDp: 64, mMoveStepInPixel: 192, mUpTimeDelayed: 100
2023-03-14 06:51:48.708  9058-9058  ViewRootImpl            com.example.mediapipemyface          D  ViewRootImpl mIsInProductivePCDisplay: false
2023-03-14 06:51:48.708  9058-9058  HwPartPowe...iceFactory com.example.mediapipemyface          I  add HwPartPowerOfficeFactoryImpl to memory.
2023-03-14 06:51:48.712  9058-9058  DecorView[]             com.example.mediapipemyface          I  pkgName:com.example.mediapipemyface old windowMode:1 new windoMode:1, isFixedSize:false
2023-03-14 06:51:48.716  9058-9058  InputEventReceiver      com.example.mediapipemyface          D  dispatchInputInterval 1000000
2023-03-14 06:51:48.717  9058-9127  CameraRepository        com.example.mediapipemyface          D  Added camera: 0
2023-03-14 06:51:48.718  9058-9058  RmeSchedManager         com.example.mediapipemyface          I  init Rme, version is: v1.0
2023-03-14 06:51:48.718  9058-9058  RtgSchedEvent           com.example.mediapipemyface          I  current pid:9058 AppType:-1
2023-03-14 06:51:48.719  9058-9104  OpenGLRenderer          com.example.mediapipemyface          D  disableOutlineDraw is true
2023-03-14 06:51:48.722  2596-3085  DollieAdapterService    pid-2596                             E  notifyActivityState pkg:com.example.mediapipemyface/com.example.mediapipemyface.MainActivity state:2 fg:true mUid:10132
2023-03-14 06:51:48.733  9058-9128  HiTouch_Pr...reDetector com.example.mediapipemyface          D  onAttached, package=com.example.mediapipemyface, windowType=1, mIsHiTouchRestricted=false
2023-03-14 06:51:48.744  9058-9127  Camera2CameraInfo       com.example.mediapipemyface          I  Device Level: INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED
2023-03-14 06:51:48.745  9058-9127  CameraRepository        com.example.mediapipemyface          D  Added camera: 1
2023-03-14 06:51:48.745  9058-9133  UseCaseAttachState      com.example.mediapipemyface          D  Active and attached use case: [] for camera: 0
2023-03-14 06:51:48.752  9058-9127  Camera2CameraInfo       com.example.mediapipemyface          I  Device Level: INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED
2023-03-14 06:51:48.753  9058-9127  CameraRepository        com.example.mediapipemyface          D  Added camera: 2
2023-03-14 06:51:48.755  9058-9104  mali_winsys             com.example.mediapipemyface          D  EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, EGLBoolean) returns 0x3000
2023-03-14 06:51:48.757  9058-9134  UseCaseAttachState      com.example.mediapipemyface          D  Active and attached use case: [] for camera: 1
2023-03-14 06:51:48.767  9058-9127  Camera2CameraInfo       com.example.mediapipemyface          I  Device Level: INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED
2023-03-14 06:51:48.767  9058-9127  CameraRepository        com.example.mediapipemyface          D  Added camera: 3
2023-03-14 06:51:48.770  9058-9104  Gralloc3                com.example.mediapipemyface          W  mapper 3.x is not supported
2023-03-14 06:51:48.771  9058-9127  Camera2CameraInfo       com.example.mediapipemyface          I  Device Level: INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED
2023-03-14 06:51:48.771  9058-9135  UseCaseAttachState      com.example.mediapipemyface          D  Active and attached use case: [] for camera: 2
2023-03-14 06:51:48.772  9058-9127  CameraRepository        com.example.mediapipemyface          D  Added camera: 4
2023-03-14 06:51:48.774  9058-9136  UseCaseAttachState      com.example.mediapipemyface          D  Active and attached use case: [] for camera: 3
2023-03-14 06:51:48.775  9058-9127  Camera2CameraInfo       com.example.mediapipemyface          I  Device Level: INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED
2023-03-14 06:51:48.776  9058-9133  UseCaseAttachState      com.example.mediapipemyface          D  Active and attached use case: [] for camera: 4
2023-03-14 06:51:48.783  9058-9058  HwViewRootImpl          com.example.mediapipemyface          I  removeInvalidNode jank list is null
2023-03-14 06:51:48.808  9058-9058  DecorView               com.example.mediapipemyface          D  showOrHideHighlightView: hasFocus=true; winMode=1; isMrgNull=true
2023-03-14 06:51:48.810  9058-9058  InputMethodManager      com.example.mediapipemyface          W  startInputReason = 1
2023-03-14 06:51:48.810  9058-9058  HwRemoteIn...hodManager com.example.mediapipemyface          W  isCasting false because IHwDistributedWindowManager is invalid.
2023-03-14 06:51:48.827  9058-9058  CameraOrientationUtil   com.example.mediapipemyface          D  getRelativeImageRotation: destRotationDegrees=0, sourceRotationDegrees=270, isOppositeFacing=false, result=270
2023-03-14 06:51:48.831  9058-9058  DeferrableSurface       com.example.mediapipemyface          D  Surface created[total_surfaces=1, used_surfaces=0](androidx.camera.core.SurfaceRequest$2@cf7e265}
2023-03-14 06:51:48.832  9058-9125  CameraXPreviewHelper    com.example.mediapipemyface          D  Received surface request for resolution 1280x720
2023-03-14 06:51:48.832  9058-9058  CameraOrientationUtil   com.example.mediapipemyface          D  getRelativeImageRotation: destRotationDegrees=0, sourceRotationDegrees=270, isOppositeFacing=false, result=270
2023-03-14 06:51:48.834  9058-9135  UseCaseAttachState      com.example.mediapipemyface          D  Active and attached use case: [] for camera: 1
2023-03-14 06:51:48.834  9058-9135  UseCaseAttachState      com.example.mediapipemyface          D  All use case: [androidx.camera.core.Preview-0e1fb5c3-5899-4452-9b4e-2ed890ccf0d679809070] for camera: 1
2023-03-14 06:51:48.834  9058-9135  UseCaseAttachState      com.example.mediapipemyface          D  Active and attached use case: [androidx.camera.core.Preview-0e1fb5c3-5899-4452-9b4e-2ed890ccf0d679809070] for camera: 1
2023-03-14 06:51:48.836  9058-9125  CameraXPreviewHelper    com.example.mediapipemyface          D  Providing surface
2023-03-14 06:51:48.836  9058-9058  InputMethodManager      com.example.mediapipemyface          W  startInputReason = 5
2023-03-14 06:51:48.838  9058-9135  CameraStateRegistry     com.example.mediapipemyface          D  tryOpenCamera(Camera@669201e[id=1]) [Available Cameras: 1, Already Open: false (Previous state: null)] --> SUCCESS
2023-03-14 06:51:48.839  9058-9135  CameraStateRegistry     com.example.mediapipemyface          D  Recalculating open cameras:
                                                                                                    Camera                                       State                 
                                                                                                    -------------------------------------------------------------------
                                                                                                    Camera@e1e275d[id=0]                         UNKNOWN               
                                                                                                    Camera@29dae1b[id=2]                         UNKNOWN               
                                                                                                    Camera@669201e[id=1]                         OPENING               
                                                                                                    Camera@e2fab64[id=3]                         UNKNOWN               
                                                                                                    Camera@9ee19d0[id=4]                         UNKNOWN               
                                                                                                    -------------------------------------------------------------------
                                                                                                    Open count: 1 (Max allowed: 1)
2023-03-14 06:51:48.840  9058-9135  UseCaseAttachState      com.example.mediapipemyface          D  All use case: [androidx.camera.core.Preview-0e1fb5c3-5899-4452-9b4e-2ed890ccf0d679809070] for camera: 1
2023-03-14 06:51:48.849  9058-9135  CameraManager           com.example.mediapipemyface          I  open camera: 1, package name: com.example.mediapipemyface
2023-03-14 06:51:48.856  9058-9058  RenderService           com.example.mediapipemyface          D  RCS is disable
2023-03-14 06:51:48.858  9058-9058  System.out              com.example.mediapipemyface          I  surfaceCreated
2023-03-14 06:51:48.859  9058-9123  mali_winsys             com.example.mediapipemyface          D  EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, EGLBoolean) returns 0x3000
2023-03-14 06:51:48.860  9058-9058  System.out              com.example.mediapipemyface          I  surfaceChanged
2023-03-14 06:51:48.876  9058-9135  UseCaseAttachState      com.example.mediapipemyface          D  Active and attached use case: [androidx.camera.core.Preview-0e1fb5c3-5899-4452-9b4e-2ed890ccf0d679809070] for camera: 1
2023-03-14 06:51:48.884  9058-9135  CameraStateRegistry     com.example.mediapipemyface          D  Recalculating open cameras:
                                                                                                    Camera                                       State                 
                                                                                                    -------------------------------------------------------------------
                                                                                                    Camera@e1e275d[id=0]                         UNKNOWN               
                                                                                                    Camera@29dae1b[id=2]                         UNKNOWN               
                                                                                                    Camera@669201e[id=1]                         OPEN                  
                                                                                                    Camera@e2fab64[id=3]                         UNKNOWN               
                                                                                                    Camera@9ee19d0[id=4]                         UNKNOWN               
                                                                                                    -------------------------------------------------------------------
                                                                                                    Open count: 1 (Max allowed: 1)
2023-03-14 06:51:48.896  9058-9135  UseCaseAttachState      com.example.mediapipemyface          D  All use case: [androidx.camera.core.Preview-0e1fb5c3-5899-4452-9b4e-2ed890ccf0d679809070] for camera: 1
2023-03-14 06:51:48.902  9058-9135  DeferrableSurface       com.example.mediapipemyface          D  New surface in use[total_surfaces=1, used_surfaces=1](androidx.camera.core.SurfaceRequest$2@cf7e265}
2023-03-14 06:51:48.902  9058-9135  DeferrableSurface       com.example.mediapipemyface          D  use count+1, useCount=1 androidx.camera.core.SurfaceRequest$2@cf7e265
2023-03-14 06:51:48.903  9058-9135  CaptureSession          com.example.mediapipemyface          D  Opening capture session.
2023-03-14 06:51:48.905  1740-1895  WindowManager           pid-1740                             E  win=Window{b56edad u0 Splash Screen com.example.mediapipemyface EXITING} destroySurfaces: appStopped=false win.mWindowRemovalAllowed=true win.mRemoveOnExit=true
2023-03-14 06:51:48.948  9058-9135  CaptureSession          com.example.mediapipemyface          D  Attempting to send capture request onConfigured
2023-03-14 06:51:48.948  9058-9135  CaptureSession          com.example.mediapipemyface          D  Issuing request for session.
2023-03-14 06:51:48.962  9058-9135  CaptureSession          com.example.mediapipemyface          D  CameraCaptureSession.onConfigured() mState=OPENED
2023-03-14 06:51:48.962  9058-9135  CaptureSession          com.example.mediapipemyface          D  CameraCaptureSession.onReady() OPENED
2023-03-14 06:51:48.963  9058-9103  Gralloc3                com.example.mediapipemyface          W  allocator 3.x is not supported
2023-03-14 06:51:49.208  9058-9124  ExternalTextureConv     com.example.mediapipemyface          D  Created output texture: 3 width: 720 height: 1280
2023-03-14 06:51:49.229  9058-9124  native                  com.example.mediapipemyface          I  I20230314 06:51:49.229887  9124 graph.cc:476] Start running the graph, waiting for inputs.
2023-03-14 06:51:49.230  9058-9124  native                  com.example.mediapipemyface          I  I20230314 06:51:49.230132  9124 gl_context_egl.cc:84] Successfully initialized EGL. Major : 1 Minor: 4
2023-03-14 06:51:49.247  9058-9203  native                  com.example.mediapipemyface          I  I20230314 06:51:49.247066  9203 gl_context.cc:342] GL version: 3.2 (OpenGL ES 3.2 v1.r18p0-01rel0.ba548f403b67fe8cf761fb65dbed7cc1)
2023-03-14 06:51:49.249  9058-9123  native                  com.example.mediapipemyface          I  I20230314 06:51:49.249614  9123 resource_util_android.cc:90] Successfully loaded: face_detection_short_range.tflite
2023-03-14 06:51:49.250  9058-9123  tflite                  com.example.mediapipemyface          I  Initialized TensorFlow Lite runtime.
2023-03-14 06:51:49.250  9058-9123  tflite                  com.example.mediapipemyface          I  Replacing 164 node(s) with delegate (unknown) node, yielding 1 partitions for the whole graph.
2023-03-14 06:51:49.253  9058-9123  tflite                  com.example.mediapipemyface          I  Replacing 164 node(s) with delegate (unknown) node, yielding 1 partitions for the whole graph.
2023-03-14 06:51:49.255  9058-9189  native                  com.example.mediapipemyface          I  I20230314 06:51:49.255018  9189 resource_util_android.cc:90] Successfully loaded: face_landmark_with_attention.tflite
2023-03-14 06:51:49.257  9058-9124  ExternalTextureConv     com.example.mediapipemyface          D  Created output texture: 4 width: 720 height: 1280
2023-03-14 06:51:49.262  9058-9123  libOpenCLv1             com.example.mediapipemyface          E  [higpu]can not get property ro.board.gpu_vendor,continue to load
2023-03-14 06:51:49.262  9058-9123  libOpenCLv1             com.example.mediapipemyface          D  loaded /system/vendor/lib64/egl/libGLES_mali.so
2023-03-14 06:51:49.266  9058-9193  native                  com.example.mediapipemyface          I  I20230314 06:51:49.266136  9193 jni_util.cc:41] GetEnv: not attached
2023-03-14 06:51:49.309  9058-9196  native                  com.example.mediapipemyface          I  I20230314 06:51:49.309494  9196 jni_util.cc:41] GetEnv: not attached
2023-03-14 06:51:49.344  9058-9194  native                  com.example.mediapipemyface          I  I20230314 06:51:49.344868  9194 jni_util.cc:41] GetEnv: not attached
2023-03-14 06:51:49.383  9058-9190  native                  com.example.mediapipemyface          I  I20230314 06:51:49.383806  9190 jni_util.cc:41] GetEnv: not attached
2023-03-14 06:51:49.461  9058-9192  native                  com.example.mediapipemyface          I  I20230314 06:51:49.460983  9192 jni_util.cc:41] GetEnv: not attached
2023-03-14 06:51:49.701  9058-9189  native                  com.example.mediapipemyface          I  I20230314 06:51:49.701364  9189 jni_util.cc:41] GetEnv: not attached
2023-03-14 06:51:50.117  9058-9123  tflite                  com.example.mediapipemyface          I  Created TensorFlow Lite delegate for GPU.
2023-03-14 06:51:50.119  9058-9123  tflite                  com.example.mediapipemyface          I  Replacing 712 node(s) with delegate (TfLiteGpuDelegate) node, yielding 1 partitions for the whole graph.
2023-03-14 06:51:50.144  9058-9191  native                  com.example.mediapipemyface          I  I20230314 06:51:50.144011  9191 jni_util.cc:41] GetEnv: not attached
2023-03-14 06:51:50.219  9058-9195  native                  com.example.mediapipemyface          I  I20230314 06:51:50.219576  9195 jni_util.cc:41] GetEnv: not attached
2023-03-14 06:51:50.262  9058-9123  native                  com.example.mediapipemyface          I  I20230314 06:51:50.262663  9123 jni_util.cc:41] GetEnv: not attached
2023-03-14 06:51:53.458  9058-9058  AwareBitmapCacher       com.example.mediapipemyface          D  handleInit switch not opened pid=9058
2023-03-14 06:51:53.570  9058-9193  libc                    com.example.mediapipemyface          A  Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 9193 (Thread-9), pid 9058 (mediapipemyface)
2023-03-14 06:51:53.648  9226-9226  DEBUG                   pid-9226                             A  pid: 9058, tid: 9193, name: Thread-9  >>> com.example.mediapipemyface <<<
2023-03-14 06:51:53.649  9226-9226  DEBUG                   pid-9226                             A        #01 pc 0000000000642da8  /data/app/com.example.mediapipemyface-0n71o32S8Iq3La0LKuj7BQ==/lib/arm64/libmediapipe_jni.so
2023-03-14 06:51:53.649  9226-9226  DEBUG                   pid-9226                             A        #02 pc 0000000000642570  /data/app/com.example.mediapipemyface-0n71o32S8Iq3La0LKuj7BQ==/lib/arm64/libmediapipe_jni.so
2023-03-14 06:51:53.649  9226-9226  DEBUG                   pid-9226                             A        #03 pc 0000000000642718  /data/app/com.example.mediapipemyface-0n71o32S8Iq3La0LKuj7BQ==/lib/arm64/libmediapipe_jni.so
2023-03-14 06:51:53.649  9226-9226  DEBUG                   pid-9226                             A        #04 pc 00000000006435a0  /data/app/com.example.mediapipemyface-0n71o32S8Iq3La0LKuj7BQ==/lib/arm64/libmediapipe_jni.so
2023-03-14 06:51:53.649  9226-9226  DEBUG                   pid-9226                             A        #05 pc 00000000001046f4  /data/app/com.example.mediapipemyface-0n71o32S8Iq3La0LKuj7BQ==/lib/arm64/libmediapipe_jni.so
2023-03-14 06:51:53.649  9226-9226  DEBUG                   pid-9226                             A        #06 pc 00000000001018b0  /data/app/com.example.mediapipemyface-0n71o32S8Iq3La0LKuj7BQ==/lib/arm64/libmediapipe_jni.so
2023-03-14 06:51:53.649  9226-9226  DEBUG                   pid-9226                             A        #07 pc 000000000055a970  /data/app/com.example.mediapipemyface-0n71o32S8Iq3La0LKuj7BQ==/lib/arm64/libmediapipe_jni.so
2023-03-14 06:51:53.649  9226-9226  DEBUG                   pid-9226                             A        #08 pc 0000000000550804  /data/app/com.example.mediapipemyface-0n71o32S8Iq3La0LKuj7BQ==/lib/arm64/libmediapipe_jni.so
2023-03-14 06:51:53.649  9226-9226  DEBUG                   pid-9226                             A        #09 pc 00000000005503b8  /data/app/com.example.mediapipemyface-0n71o32S8Iq3La0LKuj7BQ==/lib/arm64/libmediapipe_jni.so
2023-03-14 06:51:53.649  9226-9226  DEBUG                   pid-9226                             A        #10 pc 000000000057215c  /data/app/com.example.mediapipemyface-0n71o32S8Iq3La0LKuj7BQ==/lib/arm64/libmediapipe_jni.so
2023-03-14 06:51:53.649  9226-9226  DEBUG                   pid-9226                             A        #11 pc 0000000000571ec4  /data/app/com.example.mediapipemyface-0n71o32S8Iq3La0LKuj7BQ==/lib/arm64/libmediapipe_jni.so
2023-03-14 06:51:53.988  9058-9058  RtgSchedManager         com.example.mediapipemyface          E  endActivityTransaction: margin state not match
2023-03-14 06:51:53.993  9058-9124  GlThread                com.example.mediapipemyface          D  Stopping GL thread ExternalTextureConverter
2023-03-14 06:51:53.994  9058-9058  System.out              com.example.mediapipemyface          I  surfaceDestroyed
2023-03-14 06:51:54.043  1740-2058  InputDispatcher         pid-1740                             E  channel 'b56ed05 com.example.mediapipemyface/com.example.mediapipemyface.MainActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
2023-03-14 06:51:54.072  1740-2932  WindowManager           pid-1740                             E  win=Window{b56ed05 u0 com.example.mediapipemyface/com.example.mediapipemyface.MainActivity EXITING} destroySurfaces: appStopped=false win.mWindowRemovalAllowed=true win.mRemoveOnExit=true
---------------------------- PROCESS ENDED (9058) for package com.example.mediapipemyface ----------------------------
2023-03-14 06:51:54.100  2596-3085  DollieAdapterService    pid-2596                             E  notifyActivityState pkg:com.example.mediapipemyface/com.example.mediapipemyface.MainActivity state:20 fg:false mUid:10132

if there is no face, it will print

W/native: W20230314 06:54:07.288632  9663 calculator_graph.cc:1240] Resolved a deadlock by increasing max_queue_size of input stream: image_size to: 101. Consider increasing max_queue_size for better performance.

how to solve this warning? thanks a lot.

BTLDXX-x commented 1 year ago

the code:

public class MainActivity extends AppCompatActivity {

    private static String TAG = "MainActivity";

    private static final String BINARY_GRAPH_NAME = "face_mesh_mobile_gpu.binarypb";
    private static final String INPUT_VIDEO_STREAM_NAME = "input_video";
    private static final String OUTPUT_VIDEO_STREAM_NAME = "output_video";
    private static final String OUTPUT_LANDMARKS_STREAM_NAME = "smoothed_face_landmarks";
    private static final String NUM_FACES = "num_faces";
    private static final String WITH_ATTENTION = "with_attention";
    private static final String USE_PREV_LANDMARKS = "use_prev_landmarks";
    private static final CameraHelper.CameraFacing CAMERA_FACING = CameraHelper.CameraFacing.FRONT;
    // Flips the camera-preview frames vertically before sending them into FrameProcessor to be
    // processed in a MediaPipe graph, and flips the processed frames back when they are displayed.
    // This is 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 top-left.
    private static final boolean FLIP_FRAMES_VERTICALLY = true;

    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.out.println("java.lang.UnsatisfiedLinkError: " + e.toString());
            System.loadLibrary("opencv_java4");
        }
    }

    // {@link SurfaceTexture} where the camera-preview frames can be accessed.
    private SurfaceTexture previewFrameTexture;
    // {@link SurfaceView} that displays the camera-preview frames processed by a MediaPipe graph.
    private SurfaceView previewDisplayView;
    // Creates and manages an {@link EGLContext}.
    private EglManager eglManager;
    // Sends camera-preview frames into a MediaPipe graph for processing, and displays the processed
    // frames onto a {@link Surface}.
    private FrameProcessor processor;
    // Converts the GL_TEXTURE_EXTERNAL_OES texture from Android camera into a regular texture to be
    // consumed by {@link FrameProcessor} and the underlying MediaPipe graph.
    private ExternalTextureConverter converter;
    // ApplicationInfo for retrieving metadata defined in the manifest.
    private ApplicationInfo applicationInfo;
    // Handles camera access via the {@link CameraX} Jetpack support library.
    private CameraXPreviewHelper cameraHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(getContentViewLayoutResId());

        try {
            applicationInfo =
                    getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "Cannot find application info: " + e);
        }

        previewDisplayView = new SurfaceView(this);
        setupPreviewDisplayView();

        // Initialize asset manager so that MediaPipe native libraries can access the app assets, e.g.,
        // binary graphs.
        AndroidAssetUtil.initializeNativeAssetManager(this);
        eglManager = new EglManager(null);
        processor =
                new FrameProcessor(
                        this,
                        eglManager.getNativeContext(),
                        BINARY_GRAPH_NAME,
                        INPUT_VIDEO_STREAM_NAME,
                        OUTPUT_VIDEO_STREAM_NAME);
        processor
                .getVideoSurfaceOutput()
                .setFlipY(FLIP_FRAMES_VERTICALLY);

        PermissionHelper.checkAndRequestCameraPermissions(this);
        AndroidPacketCreator packetCreator = processor.getPacketCreator();
        Map<String, Packet> inputSidePackets = new HashMap<>();
        inputSidePackets.put(NUM_FACES, packetCreator.createInt32(2));
//        inputSidePackets.put(WITH_ATTENTION, packetCreator.createBool(false));
//        inputSidePackets.put(USE_PREV_LANDMARKS, packetCreator.createBool(false));
        processor.setInputSidePackets(inputSidePackets);

        processor.addPacketCallback(
                OUTPUT_LANDMARKS_STREAM_NAME,
                (packet) -> {
                    Log.v(TAG, "Received multi-face landmarks packet.");
                    List<LandmarkProto.NormalizedLandmarkList> multiFaceLandmarks =
                            PacketGetter.getProtoVector(packet, LandmarkProto.NormalizedLandmarkList.parser());
                    Log.v(
                            TAG,
                            "[TS:"
                                    + packet.getTimestamp()
                                    + "] "
                                    + getMultiFaceLandmarksDebugString(multiFaceLandmarks));
                });
    }

    // 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;
    }

    @Override
    protected void onResume() {
        super.onResume();
        converter =
                new ExternalTextureConverter(
                        eglManager.getContext(), 2);
        converter.setFlipY(FLIP_FRAMES_VERTICALLY);
        converter.setConsumer(processor);
        if (PermissionHelper.cameraPermissionsGranted(this)) {
            startCamera();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        converter.close();

        // Hide preview display until we re-open the camera again.
        previewDisplayView.setVisibility(View.GONE);
    }

    @Override
    public void onRequestPermissionsResult(
            int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionHelper.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    protected void onCameraStarted(SurfaceTexture surfaceTexture) {
        previewFrameTexture = surfaceTexture;
        // Make the display view visible to start showing the preview. This triggers the
        // SurfaceHolder.Callback added to (the holder of) previewDisplayView.
        previewDisplayView.setVisibility(View.VISIBLE);
    }

    protected Size cameraTargetResolution() {
        return null; // No preference and let the camera (helper) decide.
    }

    public void startCamera() {
        cameraHelper = new CameraXPreviewHelper();
        cameraHelper.setOnCameraStartedListener(
                surfaceTexture -> {
                    onCameraStarted(surfaceTexture);
                });
        CameraHelper.CameraFacing cameraFacing = CameraHelper.CameraFacing.FRONT;
        cameraHelper.startCamera(
                this, cameraFacing, /*unusedSurfaceTexture=*/ null, cameraTargetResolution());
    }

    protected Size computeViewSize(int width, int height) {
        return new Size(width, height);
    }

    protected void onPreviewDisplaySurfaceChanged(
            SurfaceHolder holder, int format, int width, int height) {
        // (Re-)Compute the ideal size of the camera-preview display (the area that the
        // camera-preview frames get rendered onto, potentially with scaling and rotation)
        // based on the size of the SurfaceView that contains the display.
        Size viewSize = computeViewSize(width, height);
        Size displaySize = cameraHelper.computeDisplaySizeFromViewSize(viewSize);
        boolean isCameraRotated = cameraHelper.isCameraRotated();

        // Connect the converter to the camera-preview frames as its input (via
        // previewFrameTexture), and configure the output width and height as the computed
        // display size.
        converter.setSurfaceTextureAndAttachToGLContext(
                previewFrameTexture,
                isCameraRotated ? displaySize.getHeight() : displaySize.getWidth(),
                isCameraRotated ? displaySize.getWidth() : displaySize.getHeight());
    }

    private void setupPreviewDisplayView() {
        previewDisplayView.setVisibility(View.GONE);
        ViewGroup viewGroup = findViewById(R.id.preview_display_layout);
        viewGroup.addView(previewDisplayView);

        previewDisplayView
                .getHolder()
                .addCallback(
                        new SurfaceHolder.Callback() {
                            @Override
                            public void surfaceCreated(SurfaceHolder holder) {
                                System.out.println("surfaceCreated");
                                processor.getVideoSurfaceOutput().setSurface(holder.getSurface());
                            }

                            @Override
                            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                                System.out.println("surfaceChanged");
                                onPreviewDisplaySurfaceChanged(holder, format, width, height);
                            }

                            @Override
                            public void surfaceDestroyed(SurfaceHolder holder) {
                                System.out.println("surfaceDestroyed");
                                processor.getVideoSurfaceOutput().setSurface(null);
                            }
                        });
    }

    private String getMultiFaceLandmarksDebugString(List<LandmarkProto.NormalizedLandmarkList> multiFaceLandmarks) {
        if (multiFaceLandmarks.isEmpty()) {
            return "No faces";
        }
        String multiFaceLandmarksStr = "Number of faces detected: " + multiFaceLandmarks.size() + "\n";
        int faceIndex = 0;
        for (LandmarkProto.NormalizedLandmarkList landmarks : multiFaceLandmarks) {
            multiFaceLandmarksStr +=
                    "\t#Face landmarks for face[" + faceIndex + "]: " + landmarks.getLandmarkCount() + "\n";
            int landmarkIndex = 0;
            for (LandmarkProto.NormalizedLandmark landmark : landmarks.getLandmarkList()) {
                multiFaceLandmarksStr +=
                        "\t\tLandmark ["
                                + landmarkIndex
                                + "]: ("
                                + landmark.getX()
                                + ", "
                                + landmark.getY()
                                + ", "
                                + landmark.getZ()
                                + ")\n";
                ++landmarkIndex;
            }
            ++faceIndex;
        }
        return multiFaceLandmarksStr;
    }
}
ayushgdev commented 1 year ago

Hello @BTLDXX-x Are you still looking for a resolution?

BTLDXX-x commented 1 year ago

hi @ayushgdev , i can use landmark_smoothing_calcaulator to process single face landmarks. but how can use it to process multi face landmarks? thank you!

ayushgdev commented 1 year ago

@jiuqiant Can you please help in this issue?

google-ml-butler[bot] commented 1 year ago

Are you satisfied with the resolution of your issue? Yes No

BTLDXX-x commented 1 year ago

hi @ayushgdev, i has the same problem at ios platform. i complied the framework of face_mesh successfully, and it could be used in my project. Now, i add the landmarks_smoothing_calculator into graph. bazel built successfully, but when i ran the project, it failed.

this is my graph:

# MediaPipe graph that performs face mesh with TensorFlow Lite on GPU.

# GPU buffer. (GpuBuffer)
input_stream: "input_video"

# Max number of faces to detect/process. (int)
input_side_packet: "num_faces"

# Output image with rendered results. (GpuBuffer)
output_stream: "output_video"
# Collection of detected/processed faces, each represented as a list of
# landmarks. (std::vector<NormalizedLandmarkList>)
output_stream: "multi_smoothed_face_landmarks"

# 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
# passes through another image. All images that come in while waiting are
# dropped, limiting the number of in-flight images in most part of the graph to
# 1. This prevents the downstream nodes from queuing up incoming images and data
# excessively, which leads to increased latency and memory usage, unwanted in
# 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"
  input_stream: "FINISHED:output_video"
  input_stream_info: {
    tag_index: "FINISHED"
    back_edge: true
  }
  output_stream: "throttled_input_video"
}

# Defines side packets for further use in the graph.
node {
  calculator: "ConstantSidePacketCalculator"
  output_side_packet: "PACKET:with_attention"
  node_options: {
    [type.googleapis.com/mediapipe.ConstantSidePacketCalculatorOptions]: {
      packet { bool_value: true }
    }
  }
}

# Subgraph that detects faces and corresponding landmarks.
node {
  calculator: "FaceLandmarkFrontGpu"
  input_stream: "IMAGE:throttled_input_video"
  input_side_packet: "NUM_FACES:num_faces"
  input_side_packet: "WITH_ATTENTION:with_attention"
  output_stream: "LANDMARKS:multi_face_landmarks"
  output_stream: "ROIS_FROM_LANDMARKS:face_rects_from_landmarks"
  output_stream: "DETECTIONS:face_detections"
  output_stream: "ROIS_FROM_DETECTIONS:face_rects_from_detections"
}

# Subgraph that renders face-landmark annotation onto the input image.
node {
  calculator: "FaceRendererGpu"
  input_stream: "IMAGE:throttled_input_video"
  input_stream: "LANDMARKS:multi_face_landmarks"
  input_stream: "NORM_RECTS:face_rects_from_landmarks"
  input_stream: "DETECTIONS:face_detections"
  output_stream: "IMAGE:output_video"
}

node {
  calculator: "SplitNormalizedLandmarkListVectorCalculator"
  input_stream: "multi_face_landmarks"
  output_stream: "face_landmarks"
  node_options: {
    [type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
      ranges: { begin: 0 end: 1 }
      element_only: true
    }
  }
}

# Extracts the input image frame dimensions as a separate packet.
node {
  calculator: "ImagePropertiesCalculator"
  input_stream: "IMAGE:throttled_input_video"
  output_stream: "SIZE:input_image_size"
}

# Applies smoothing to the single set of face landmarks.
node {
  calculator: "FaceLandmarksSmoothing"
  input_stream: "NORM_LANDMARKS:face_landmarks"
  input_stream: "IMAGE_SIZE:input_image_size"
  output_stream: "NORM_FILTERED_LANDMARKS:smoothed_face_landmarks"
}

# Puts the single set of smoothed landmarks back into a collection to simplify
# passing the result into the `FaceGeometryFromLandmarks` subgraph.
node {
  calculator: "ConcatenateNormalizedLandmarkListVectorCalculator"
  input_stream: "smoothed_face_landmarks"
  output_stream: "multi_smoothed_face_landmarks"
}

in the build file, i also add the relative deps:

# 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.

load(
    "//mediapipe/framework/tool:mediapipe_graph.bzl",
    "mediapipe_binary_graph",
)

licenses(["notice"])

package(default_visibility = ["//visibility:public"])

cc_library(
    name = "mobile_calculators",
    deps = [
        "//mediapipe/calculators/core:flow_limiter_calculator",
    "//mediapipe/calculators/core:split_vector_calculator",
    "//mediapipe/calculators/core:concatenate_detection_vector_calculator",
    "//mediapipe/calculators/image:image_properties_calculator",
    "//mediapipe/calculators/core:concatenate_vector_calculator",
        "//mediapipe/examples/newfacemesh/graphs/subgraphs:face_renderer_gpu",
        "//mediapipe/modules/face_landmark:face_landmark_front_gpu",
    "//mediapipe/examples/newfacemesh/graphs/subgraphs:face_landmarks_smoothing",
    "//mediapipe/calculators/core:constant_side_packet_calculator",

    ],
)

mediapipe_binary_graph(
    name = "face_mesh_mobile_gpu_binary_graph",
    graph = "face_mesh_mobile.pbtxt",
    output_name = "face_mesh_mobile_gpu.binarypb",
    deps = [":mobile_calculators"],
)

can you please help this? thank you very much!

BTLDXX-x commented 1 year ago

hi @ayushgdev, i has the same problem at ios platform. i complied the framework of face_mesh successfully, and it could be used in my project. Now, i add the landmarks_smoothing_calculator into graph. bazel built successfully, but when i ran the project, it failed.

this is my graph:

# MediaPipe graph that performs face mesh with TensorFlow Lite on GPU.

# GPU buffer. (GpuBuffer)
input_stream: "input_video"

# Max number of faces to detect/process. (int)
input_side_packet: "num_faces"

# Output image with rendered results. (GpuBuffer)
output_stream: "output_video"
# Collection of detected/processed faces, each represented as a list of
# landmarks. (std::vector<NormalizedLandmarkList>)
output_stream: "multi_smoothed_face_landmarks"

# 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
# passes through another image. All images that come in while waiting are
# dropped, limiting the number of in-flight images in most part of the graph to
# 1. This prevents the downstream nodes from queuing up incoming images and data
# excessively, which leads to increased latency and memory usage, unwanted in
# 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"
  input_stream: "FINISHED:output_video"
  input_stream_info: {
    tag_index: "FINISHED"
    back_edge: true
  }
  output_stream: "throttled_input_video"
}

# Defines side packets for further use in the graph.
node {
  calculator: "ConstantSidePacketCalculator"
  output_side_packet: "PACKET:with_attention"
  node_options: {
    [type.googleapis.com/mediapipe.ConstantSidePacketCalculatorOptions]: {
      packet { bool_value: true }
    }
  }
}

# Subgraph that detects faces and corresponding landmarks.
node {
  calculator: "FaceLandmarkFrontGpu"
  input_stream: "IMAGE:throttled_input_video"
  input_side_packet: "NUM_FACES:num_faces"
  input_side_packet: "WITH_ATTENTION:with_attention"
  output_stream: "LANDMARKS:multi_face_landmarks"
  output_stream: "ROIS_FROM_LANDMARKS:face_rects_from_landmarks"
  output_stream: "DETECTIONS:face_detections"
  output_stream: "ROIS_FROM_DETECTIONS:face_rects_from_detections"
}

# Subgraph that renders face-landmark annotation onto the input image.
node {
  calculator: "FaceRendererGpu"
  input_stream: "IMAGE:throttled_input_video"
  input_stream: "LANDMARKS:multi_face_landmarks"
  input_stream: "NORM_RECTS:face_rects_from_landmarks"
  input_stream: "DETECTIONS:face_detections"
  output_stream: "IMAGE:output_video"
}

node {
  calculator: "SplitNormalizedLandmarkListVectorCalculator"
  input_stream: "multi_face_landmarks"
  output_stream: "face_landmarks"
  node_options: {
    [type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
      ranges: { begin: 0 end: 1 }
      element_only: true
    }
  }
}

# Extracts the input image frame dimensions as a separate packet.
node {
  calculator: "ImagePropertiesCalculator"
  input_stream: "IMAGE:throttled_input_video"
  output_stream: "SIZE:input_image_size"
}

# Applies smoothing to the single set of face landmarks.
node {
  calculator: "FaceLandmarksSmoothing"
  input_stream: "NORM_LANDMARKS:face_landmarks"
  input_stream: "IMAGE_SIZE:input_image_size"
  output_stream: "NORM_FILTERED_LANDMARKS:smoothed_face_landmarks"
}

# Puts the single set of smoothed landmarks back into a collection to simplify
# passing the result into the `FaceGeometryFromLandmarks` subgraph.
node {
  calculator: "ConcatenateNormalizedLandmarkListVectorCalculator"
  input_stream: "smoothed_face_landmarks"
  output_stream: "multi_smoothed_face_landmarks"
}

in the build file, i also add the relative deps:

# 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.

load(
    "//mediapipe/framework/tool:mediapipe_graph.bzl",
    "mediapipe_binary_graph",
)

licenses(["notice"])

package(default_visibility = ["//visibility:public"])

cc_library(
    name = "mobile_calculators",
    deps = [
        "//mediapipe/calculators/core:flow_limiter_calculator",
  "//mediapipe/calculators/core:split_vector_calculator",
  "//mediapipe/calculators/core:concatenate_detection_vector_calculator",
  "//mediapipe/calculators/image:image_properties_calculator",
  "//mediapipe/calculators/core:concatenate_vector_calculator",
        "//mediapipe/examples/newfacemesh/graphs/subgraphs:face_renderer_gpu",
        "//mediapipe/modules/face_landmark:face_landmark_front_gpu",
  "//mediapipe/examples/newfacemesh/graphs/subgraphs:face_landmarks_smoothing",
  "//mediapipe/calculators/core:constant_side_packet_calculator",

    ],
)

mediapipe_binary_graph(
    name = "face_mesh_mobile_gpu_binary_graph",
    graph = "face_mesh_mobile.pbtxt",
    output_name = "face_mesh_mobile_gpu.binarypb",
    deps = [":mobile_calculators"],
)

can you please help this? thank you very much!

i have solved this. the reason is that i wrote the false tag of ImagePropertiesCalculator. it should be IMAGE_GPU rather than IMAGE.