# 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: "SingleFaceGeometryFromDetectionGpu"

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

# Subgraph that detects faces and corresponding landmarks using the face
# detection pipeline.
node {
  calculator: "FaceDetectionShortRangeGpu"
  input_stream: "IMAGE:input_image"
  output_stream: "DETECTIONS:multi_face_detection"
}

# Extracts the first face detection associated with the most prominent face from
# a collection.
node {
  calculator: "SplitDetectionVectorCalculator"
  input_stream: "multi_face_detection"
  output_stream: "face_detection"
  node_options: {
    [type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
      ranges: { begin: 0 end: 1 }
      element_only: true
    }
  }
}

# Extracts face detection keypoints as a normalized landmarks.
node {
  calculator: "DetectionToLandmarksCalculator"
  input_stream: "DETECTION:face_detection"
  output_stream: "LANDMARKS:face_landmarks"
}

# 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 face landmarks previously extracted from the face
# detection keypoints.
node {
  calculator: "FaceLandmarksSmoothing"
  input_stream: "NORM_LANDMARKS:face_landmarks"
  input_stream: "IMAGE_SIZE:input_image_size"
  output_stream: "NORM_FILTERED_LANDMARKS:smoothed_face_landmarks"
}

# Converts smoothed face landmarks back into the detection format.
node {
  calculator: "LandmarksToDetectionCalculator"
  input_stream: "NORM_LANDMARKS:smoothed_face_landmarks"
  output_stream: "DETECTION:smoothed_face_detection"
}

# Puts the smoothed single face detection back into a collection to simplify
# passing the result into the `FaceGeometryFromDetection` subgraph.
node {
  calculator: "ConcatenateDetectionVectorCalculator"
  input_stream: "smoothed_face_detection"
  output_stream: "multi_smoothed_face_detection"
}

# Computes face geometry from the single face detection.
node {
  calculator: "FaceGeometryFromDetection"
  input_stream: "MULTI_FACE_DETECTION:multi_smoothed_face_detection"
  input_stream: "IMAGE_SIZE:input_image_size"
  input_side_packet: "ENVIRONMENT:environment"
  output_stream: "MULTI_FACE_GEOMETRY:multi_face_geometry"
}
