# MediaPipe subgraph that extracts geometry from a single face using the face
# landmark pipeline on an input GPU image. The face landmarks are also
# "smoothed" to achieve better visual results.

type: "SingleFaceGeometryFromLandmarksGpu"

# GPU image. (GpuBuffer)
input_stream: "IMAGE:input_image"

# Environment that describes the current virtual scene.
# (face_geometry::Environment)
input_side_packet: "ENVIRONMENT:environment"

# A list of geometry data for a single detected face. The size of this
# collection is at most 1 because of the single-face use in this graph.
# (std::vector<face_geometry::FaceGeometry>)
#
# NOTE: if no face is detected at a particular timestamp, there will not be an
# output packet in the `MULTI_FACE_GEOMETRY` stream for this timestamp. However,
# the MediaPipe framework will internally inform the downstream calculators of
# the absence of this packet so that they don't wait for it unnecessarily.
output_stream: "MULTI_FACE_GEOMETRY:multi_face_geometry"

# Creates a packet to inform the `FaceLandmarkFrontGpu` subgraph to detect at
# most 1 face.
node {
  calculator: "ConstantSidePacketCalculator"
  output_side_packet: "PACKET:num_faces"
  node_options: {
    [type.googleapis.com/mediapipe.ConstantSidePacketCalculatorOptions]: {
      packet { int_value: 1 }
    }
  }
}

# Subgraph that detects faces and corresponding landmarks using the face
# landmark pipeline.
node {
  calculator: "FaceLandmarkFrontGpu"
  input_stream: "IMAGE:input_image"
  input_side_packet: "NUM_FACES:num_faces"
  output_stream: "LANDMARKS:multi_face_landmarks"
}

# 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_GPU:input_image"
  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"
}

# Computes face geometry from face landmarks for a single face.
node {
  calculator: "FaceGeometryFromLandmarks"
  input_stream: "MULTI_FACE_LANDMARKS:multi_smoothed_face_landmarks"
  input_stream: "IMAGE_SIZE:input_image_size"
  input_side_packet: "ENVIRONMENT:environment"
  output_stream: "MULTI_FACE_GEOMETRY:multi_face_geometry"
}
