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.72k stars 5.18k forks source link

How to programmatically disable face effect calculator #4862

Closed generalomosco closed 1 year ago

generalomosco commented 1 year ago

I tried to use PassThroughCalculator to disable the FaceGeometry but unfortunately it is given me error saying input and output must be assigned to PassThroughCalculator! The goal is to add more custom calculators so i can disable the one which is not required



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

# An integer, which indicate which effect is selected. (int)
#
# If `selected_effect_id` is `0`, the Axis effect is selected.
# If `selected_effect_id` is `1`, the Facepaint effect is selected.
# If `selected_effect_id` is `2`, the Glasses effect is selected.
#
# No other values are allowed for `selected_effect_id`.
input_stream: "selected_effect_id"

# Indicates whether to use the face detection as the input source. (bool)
#
# If `true`, the face detection pipeline will be used to produce landmarks.
# If `false`, the face landmark pipeline will be used to produce landmarks.
input_side_packet: "disable_face_effect"

# Output image with rendered results. (GpuBuffer)
output_stream: "output_video"

# Output image results. (CPU Buffer)
output_stream: "output_video_cpu"

# A list of geometry data for a single detected face.
#
# NOTE: there will not be an output packet in this stream for this particular
# timestamp if none of faces detected.
#
# (std::vector<face_geometry::FaceGeometry>)
output_stream: "multi_face_geometry"

# 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"
}

# Generates an environment that describes the current virtual scene.
node {
  calculator: "FaceGeometryEnvGeneratorCalculator"
  output_side_packet: "ENVIRONMENT:environment"
  node_options: {
    [type.googleapis.com/mediapipe.FaceGeometryEnvGeneratorCalculatorOptions] {
      environment: {
        origin_point_location: TOP_LEFT_CORNER
        perspective_camera: {
          vertical_fov_degrees: 63.0  # 63 degrees
          near: 1.0  # 1cm
          far: 10000.0  # 100m
        }
      }
    }
  }
}

node {
  calculator: "SwitchContainer"
  input_stream: "IMAGE:throttled_input_video"
  input_side_packet: "ENABLE:disable_face_effect"
  input_side_packet: "ENVIRONMENT:environment"
  output_stream: "MULTI_FACE_GEOMETRY:multi_face_geometry"
  node_options: {
    [type.googleapis.com/mediapipe.SwitchContainerOptions] {
      contained_node: {
        calculator: "SingleFaceGeometryFromLandmarksGpu"
      }
      contained_node: {
        calculator: "PassThroughCalculator"
      }
    }
  }
}

# Renders the selected effect based on `selected_effect_id`.
node {
  calculator: "SwitchContainer"
  input_stream: "SELECT:selected_effect_id"
  input_stream: "IMAGE_GPU:throttled_input_video"
  input_stream: "MULTI_FACE_GEOMETRY:multi_face_geometry"
  input_side_packet: "ENVIRONMENT:environment"
  output_stream: "IMAGE_GPU:output_video"
  node_options: {
    [type.googleapis.com/mediapipe.SwitchContainerOptions] {
      contained_node: {
        calculator: "FaceGeometryEffectRendererCalculator"
        node_options: {
          [type.googleapis.com/mediapipe.FaceGeometryEffectRendererCalculatorOptions] {
            effect_texture_path: "mediapipe/graphs/face_effect/effects/data/axis.pngblob"
            effect_mesh_3d_path: "mediapipe/graphs/face_effect/effects/data/axis.binarypb"
          }
        }
      }
      contained_node: {
        calculator: "FaceGeometryEffectRendererCalculator"
        node_options: {
          [type.googleapis.com/mediapipe.FaceGeometryEffectRendererCalculatorOptions] {
            effect_texture_path: "mediapipe/graphs/face_effect/effects/data/facepaint.pngblob"
          }
        }
      }
    }
  }
}
# converts the output GPU_BUFFER to IMAGE_FRAME Data type because 
# we want to do CPU for view operations
node{
  calculator: "GpuBufferToImageFrameCalculator"
  input_stream: "output_video"
  output_stream: "output_video_cpu"
}```
generalomosco commented 1 year ago

I created a mock FaceGeometry calculator that output empty MULTI_FACE_GEOMETRY:multi_face_geometry to disable it, I thought I can call processor.setInputSidePackets(inputSidePackets); at anytime. The issue now is that I can only change disable_face_effect to enable or disable when graph has not started, when graph get started I won't be able to call processor.setInputSidePackets(...) anymore

generalomosco commented 1 year ago

It works perfect now by changing disable_face_effect input_side_packet to input_stream because input_side_packet is for static env

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

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