# MediaPipe graph to detect/predict face landmarks. (CPU input, and inference is # executed on CPU.) # # It is required that "face_landmark.tflite" is available at # "mediapipe/modules/face_landmark/face_landmark.tflite" # path during execution. # # EXAMPLE: # node { # calculator: "FaceLandmarkGpu" # input_stream: "IMAGE:image" # input_stream: "ROI:face_roi" # output_stream: "LANDMARKS:face_landmarks" # } type: "FaceLandmarkGpu" # GPU image. (GpuBuffer) input_stream: "IMAGE:image" # ROI (region of interest) within the given image where a face is located. # (NormalizedRect) input_stream: "ROI:roi" # 468 face landmarks within the given ROI. (NormalizedLandmarkList) # NOTE: if a face is not present within the given ROI, for this particular # timestamp there will not be an output packet in the LANDMARKS stream. 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: "LANDMARKS:face_landmarks" # Transforms the input image into a 192x192 tensor. node: { calculator: "ImageToTensorCalculator" input_stream: "IMAGE_GPU:image" input_stream: "NORM_RECT:roi" output_stream: "TENSORS:input_tensors" options: { [mediapipe.ImageToTensorCalculatorOptions.ext] { output_tensor_width: 192 output_tensor_height: 192 output_tensor_float_range { min: 0.0 max: 1.0 } gpu_origin: TOP_LEFT } } } # Runs a TensorFlow Lite model on GPU that takes an image tensor and outputs a # vector of GPU tensors representing, for instance, detection boxes/keypoints # and scores. node { calculator: "InferenceCalculator" input_stream: "TENSORS:input_tensors" output_stream: "TENSORS:output_tensors" options: { [mediapipe.InferenceCalculatorOptions.ext] { model_path: "mediapipe/modules/face_landmark/face_landmark.tflite" } } } # Splits a vector of tensors into multiple vectors. node { calculator: "SplitTensorVectorCalculator" input_stream: "output_tensors" output_stream: "landmark_tensors" output_stream: "face_flag_tensor" options: { [mediapipe.SplitVectorCalculatorOptions.ext] { ranges: { begin: 0 end: 1 } ranges: { begin: 1 end: 2 } } } } # Converts the face-flag tensor into a float that represents the confidence # score of face presence. node { calculator: "TensorsToFloatsCalculator" input_stream: "TENSORS:face_flag_tensor" output_stream: "FLOAT:face_presence_score" options { [mediapipe.TensorsToFloatsCalculatorOptions.ext] { activation: SIGMOID } } } # Applies a threshold to the confidence score to determine whether a face is # present. node { calculator: "ThresholdingCalculator" input_stream: "FLOAT:face_presence_score" output_stream: "FLAG:face_presence" options: { [mediapipe.ThresholdingCalculatorOptions.ext] { threshold: 0.5 } } } # Drop landmarks tensors if face is not present. node { calculator: "GateCalculator" input_stream: "landmark_tensors" input_stream: "ALLOW:face_presence" output_stream: "ensured_landmark_tensors" } # Decodes the landmark tensors into a vector of landmarks, where the landmark # coordinates are normalized by the size of the input image to the model. node { calculator: "TensorsToLandmarksCalculator" input_stream: "TENSORS:ensured_landmark_tensors" output_stream: "NORM_LANDMARKS:landmarks" options: { [mediapipe.TensorsToLandmarksCalculatorOptions.ext] { num_landmarks: 468 input_image_width: 192 input_image_height: 192 } } } # Projects the landmarks from the cropped face image to the corresponding # locations on the full image before cropping (input to the graph). node { calculator: "LandmarkProjectionCalculator" input_stream: "NORM_LANDMARKS:landmarks" input_stream: "NORM_RECT:roi" output_stream: "NORM_LANDMARKS:face_landmarks" }