Internal change
PiperOrigin-RevId: 514498364
This commit is contained in:
		
							parent
							
								
									77fcaa9597
								
							
						
					
					
						commit
						f15244997f
					
				
							
								
								
									
										46
									
								
								mediapipe/tasks/cc/vision/face_geometry/BUILD
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								mediapipe/tasks/cc/vision/face_geometry/BUILD
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,46 @@
 | 
				
			||||||
 | 
					# Copyright 2023 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.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					licenses(["notice"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package(default_visibility = ["//mediapipe/tasks:internal"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cc_library(
 | 
				
			||||||
 | 
					    name = "face_geometry_from_landmarks_graph",
 | 
				
			||||||
 | 
					    srcs = ["face_geometry_from_landmarks_graph.cc"],
 | 
				
			||||||
 | 
					    data = [
 | 
				
			||||||
 | 
					        "//mediapipe/tasks/cc/vision/face_geometry/data:geometry_pipeline_metadata_landmarks",
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    deps = [
 | 
				
			||||||
 | 
					        "//mediapipe/calculators/core:begin_loop_calculator",
 | 
				
			||||||
 | 
					        "//mediapipe/calculators/core:end_loop_calculator",
 | 
				
			||||||
 | 
					        "//mediapipe/calculators/core:split_proto_list_calculator",
 | 
				
			||||||
 | 
					        "//mediapipe/calculators/core:split_vector_calculator_cc_proto",
 | 
				
			||||||
 | 
					        "//mediapipe/framework:calculator_cc_proto",
 | 
				
			||||||
 | 
					        "//mediapipe/framework:calculator_framework",
 | 
				
			||||||
 | 
					        "//mediapipe/framework:subgraph",
 | 
				
			||||||
 | 
					        "//mediapipe/framework/api2:builder",
 | 
				
			||||||
 | 
					        "//mediapipe/framework/api2:port",
 | 
				
			||||||
 | 
					        "//mediapipe/framework/formats:landmark_cc_proto",
 | 
				
			||||||
 | 
					        "//mediapipe/tasks/cc/vision/face_geometry/calculators:env_generator_calculator",
 | 
				
			||||||
 | 
					        "//mediapipe/tasks/cc/vision/face_geometry/calculators:env_generator_calculator_cc_proto",
 | 
				
			||||||
 | 
					        "//mediapipe/tasks/cc/vision/face_geometry/calculators:geometry_pipeline_calculator",
 | 
				
			||||||
 | 
					        "//mediapipe/tasks/cc/vision/face_geometry/calculators:geometry_pipeline_calculator_cc_proto",
 | 
				
			||||||
 | 
					        "//mediapipe/tasks/cc/vision/face_geometry/proto:environment_cc_proto",
 | 
				
			||||||
 | 
					        "//mediapipe/tasks/cc/vision/face_geometry/proto:face_geometry_cc_proto",
 | 
				
			||||||
 | 
					        "//mediapipe/util:graph_builder_utils",
 | 
				
			||||||
 | 
					        "@com_google_absl//absl/status:statusor",
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    alwayslink = 1,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,204 @@
 | 
				
			||||||
 | 
					/* Copyright 2023 The MediaPipe Authors. All Rights Reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					==============================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <optional>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "absl/status/statusor.h"
 | 
				
			||||||
 | 
					#include "mediapipe/calculators/core/split_vector_calculator.pb.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/api2/builder.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/calculator.pb.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/calculator_framework.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/formats/landmark.pb.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/subgraph.h"
 | 
				
			||||||
 | 
					#include "mediapipe/tasks/cc/vision/face_geometry/calculators/env_generator_calculator.pb.h"
 | 
				
			||||||
 | 
					#include "mediapipe/tasks/cc/vision/face_geometry/calculators/geometry_pipeline_calculator.pb.h"
 | 
				
			||||||
 | 
					#include "mediapipe/tasks/cc/vision/face_geometry/proto/environment.pb.h"
 | 
				
			||||||
 | 
					#include "mediapipe/tasks/cc/vision/face_geometry/proto/face_geometry.pb.h"
 | 
				
			||||||
 | 
					#include "mediapipe/util/graph_builder_utils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace mediapipe::tasks::vision::face_geometry {
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using ::mediapipe::api2::builder::Graph;
 | 
				
			||||||
 | 
					using ::mediapipe::api2::builder::SidePacket;
 | 
				
			||||||
 | 
					using ::mediapipe::api2::builder::Stream;
 | 
				
			||||||
 | 
					using ::mediapipe::tasks::vision::face_geometry::proto::Environment;
 | 
				
			||||||
 | 
					using ::mediapipe::tasks::vision::face_geometry::proto::FaceGeometry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					constexpr char kMultiFaceLandmarksTag[] = "MULTI_FACE_LANDMARKS";
 | 
				
			||||||
 | 
					constexpr char kMultiFaceGeometryTag[] = "MULTI_FACE_GEOMETRY";
 | 
				
			||||||
 | 
					constexpr char kFaceLandmarksTag[] = "FACE_LANDMARKS";
 | 
				
			||||||
 | 
					constexpr char kFaceGeometryTag[] = "FACE_GEOMETRY";
 | 
				
			||||||
 | 
					constexpr char kImageSizeTag[] = "IMAGE_SIZE";
 | 
				
			||||||
 | 
					constexpr char kEnvironmentTag[] = "ENVIRONMENT";
 | 
				
			||||||
 | 
					constexpr char kIterableTag[] = "ITERABLE";
 | 
				
			||||||
 | 
					constexpr char kBatchEndTag[] = "BATCH_END";
 | 
				
			||||||
 | 
					constexpr char kItemTag[] = "ITEM";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					constexpr char kGeometryPipelineMetadataPath[] =
 | 
				
			||||||
 | 
					    "mediapipe/tasks/cc/vision/face_geometry/data/"
 | 
				
			||||||
 | 
					    "geometry_pipeline_metadata_landmarks.binarypb";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct FaceGeometryOuts {
 | 
				
			||||||
 | 
					  Stream<std::vector<FaceGeometry>> multi_face_geometry;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ConfigureSplitNormalizedLandmarkListCalculator(
 | 
				
			||||||
 | 
					    mediapipe::SplitVectorCalculatorOptions& options) {
 | 
				
			||||||
 | 
					  auto& range = *options.add_ranges();
 | 
				
			||||||
 | 
					  // Extract the first 468 face landmarks, excluding iris;
 | 
				
			||||||
 | 
					  range.set_begin(0);
 | 
				
			||||||
 | 
					  range.set_end(468);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ConfigureFaceGeometryEnvGeneratorCalculator(
 | 
				
			||||||
 | 
					    FaceGeometryEnvGeneratorCalculatorOptions& options) {
 | 
				
			||||||
 | 
					  options.mutable_environment()->set_origin_point_location(
 | 
				
			||||||
 | 
					      proto::OriginPointLocation::TOP_LEFT_CORNER);
 | 
				
			||||||
 | 
					  auto& perspective_camera =
 | 
				
			||||||
 | 
					      *options.mutable_environment()->mutable_perspective_camera();
 | 
				
			||||||
 | 
					  perspective_camera.set_vertical_fov_degrees(63.0 /*degrees*/);
 | 
				
			||||||
 | 
					  perspective_camera.set_near(1.0 /* 1cm */);
 | 
				
			||||||
 | 
					  perspective_camera.set_far(10000.0 /* 100m */);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}  // namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// A "mediapipe.tasks.vision.face_landmarker.FaceGeometryFromLandmarksGraph"
 | 
				
			||||||
 | 
					// graph to extract 3D transform from the given canonical face to multi face
 | 
				
			||||||
 | 
					// landmarks.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// It is required that "geometry_pipeline_metadata_from_landmark.binarypb" is
 | 
				
			||||||
 | 
					// available at
 | 
				
			||||||
 | 
					// "mediapipe/tasks/cc/vision/face_geometry/data/geometry_pipeline_metadata_from_landmarks.binarypb"
 | 
				
			||||||
 | 
					// path during execution.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Inputs:
 | 
				
			||||||
 | 
					//   IMAGE_SIZE - std::pair<int,int>
 | 
				
			||||||
 | 
					//     The size of the image that face landmarks are detected on.
 | 
				
			||||||
 | 
					//   FACE_LANDMARKS - std::vector<NormalizedLandmarkList>
 | 
				
			||||||
 | 
					//     A vector of multiple face landmarks that the given canonical face would
 | 
				
			||||||
 | 
					//     transform to.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//  SideInputs:
 | 
				
			||||||
 | 
					//   ENVIRONMENT - ENVIRONMENT
 | 
				
			||||||
 | 
					//     Environment that describes the current virtual scene. If not provided, a
 | 
				
			||||||
 | 
					//     default environment will be used which can be applied to common webcam.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Outputs:
 | 
				
			||||||
 | 
					//   FACE_GEOMETRY: - std::vector<FaceGeometry>
 | 
				
			||||||
 | 
					//    A vector of 3D transform data for each detected face.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Example:
 | 
				
			||||||
 | 
					// node {
 | 
				
			||||||
 | 
					//   calculator:
 | 
				
			||||||
 | 
					//   "mediapipe.tasks.vision.face_landmarker.FaceGeometryFromLandmarksGraph"
 | 
				
			||||||
 | 
					//   input_stream: "IMAGE_SIZE:image_size"
 | 
				
			||||||
 | 
					//   input_stream: "FACE_LANDMARKS:face_landmarks"
 | 
				
			||||||
 | 
					//   input_side_packet: "ENVIRONMENT:environment"
 | 
				
			||||||
 | 
					//   output_stream: "FACE_GEOMETRY:face_geometry"
 | 
				
			||||||
 | 
					// }
 | 
				
			||||||
 | 
					class FaceGeometryFromLandmarksGraph : public Subgraph {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  absl::StatusOr<CalculatorGraphConfig> GetConfig(
 | 
				
			||||||
 | 
					      SubgraphContext* sc) override {
 | 
				
			||||||
 | 
					    Graph graph;
 | 
				
			||||||
 | 
					    std::optional<SidePacket<Environment>> environment;
 | 
				
			||||||
 | 
					    if (HasSideInput(sc->OriginalNode(), kEnvironmentTag)) {
 | 
				
			||||||
 | 
					      environment = std::make_optional<>(
 | 
				
			||||||
 | 
					          graph.SideIn(kEnvironmentTag).Cast<Environment>());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    ASSIGN_OR_RETURN(auto outs,
 | 
				
			||||||
 | 
					                     BuildFaceGeometryFromLandmarksGraph(
 | 
				
			||||||
 | 
					                         graph.In(kFaceLandmarksTag)
 | 
				
			||||||
 | 
					                             .Cast<std::vector<NormalizedLandmarkList>>(),
 | 
				
			||||||
 | 
					                         graph.In(kImageSizeTag).Cast<std::pair<int, int>>(),
 | 
				
			||||||
 | 
					                         environment, graph));
 | 
				
			||||||
 | 
					    outs.multi_face_geometry >>
 | 
				
			||||||
 | 
					        graph.Out(kFaceGeometryTag).Cast<std::vector<FaceGeometry>>();
 | 
				
			||||||
 | 
					    return graph.GetConfig();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 private:
 | 
				
			||||||
 | 
					  absl::StatusOr<FaceGeometryOuts> BuildFaceGeometryFromLandmarksGraph(
 | 
				
			||||||
 | 
					      Stream<std::vector<NormalizedLandmarkList>> multi_face_landmarks,
 | 
				
			||||||
 | 
					      Stream<std::pair<int, int>> image_size,
 | 
				
			||||||
 | 
					      std::optional<SidePacket<Environment>> environment, Graph& graph) {
 | 
				
			||||||
 | 
					    if (!environment.has_value()) {
 | 
				
			||||||
 | 
					      // If there is no provided Environment, use a a default environment which
 | 
				
			||||||
 | 
					      // is good enough for most general use case.
 | 
				
			||||||
 | 
					      auto& env_generator = graph.AddNode(
 | 
				
			||||||
 | 
					          "mediapipe.tasks.vision.face_geometry."
 | 
				
			||||||
 | 
					          "FaceGeometryEnvGeneratorCalculator");
 | 
				
			||||||
 | 
					      ConfigureFaceGeometryEnvGeneratorCalculator(
 | 
				
			||||||
 | 
					          env_generator
 | 
				
			||||||
 | 
					              .GetOptions<FaceGeometryEnvGeneratorCalculatorOptions>());
 | 
				
			||||||
 | 
					      environment = std::make_optional<>(
 | 
				
			||||||
 | 
					          env_generator.SideOut(kEnvironmentTag).Cast<Environment>());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // For loop to go over the vector of face landmarks list, and remove the
 | 
				
			||||||
 | 
					    // iris landmarks.
 | 
				
			||||||
 | 
					    auto& begin_loop_landmark_list_vector =
 | 
				
			||||||
 | 
					        graph.AddNode("BeginLoopNormalizedLandmarkListVectorCalculator");
 | 
				
			||||||
 | 
					    multi_face_landmarks >> begin_loop_landmark_list_vector.In(kIterableTag);
 | 
				
			||||||
 | 
					    auto batch_end = begin_loop_landmark_list_vector.Out(kBatchEndTag);
 | 
				
			||||||
 | 
					    auto single_face_landmarks = begin_loop_landmark_list_vector.Out(kItemTag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Take first 468 face landmarks and exclude iris landmarks.
 | 
				
			||||||
 | 
					    auto& split_landmark_list =
 | 
				
			||||||
 | 
					        graph.AddNode("SplitNormalizedLandmarkListCalculator");
 | 
				
			||||||
 | 
					    ConfigureSplitNormalizedLandmarkListCalculator(
 | 
				
			||||||
 | 
					        split_landmark_list
 | 
				
			||||||
 | 
					            .GetOptions<mediapipe::SplitVectorCalculatorOptions>());
 | 
				
			||||||
 | 
					    single_face_landmarks >> split_landmark_list.In("");
 | 
				
			||||||
 | 
					    auto single_face_landmarks_no_iris = split_landmark_list.Out("");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto& end_loop_landmark_list_vector =
 | 
				
			||||||
 | 
					        graph.AddNode("EndLoopNormalizedLandmarkListVectorCalculator");
 | 
				
			||||||
 | 
					    batch_end >> end_loop_landmark_list_vector.In(kBatchEndTag);
 | 
				
			||||||
 | 
					    single_face_landmarks_no_iris >> end_loop_landmark_list_vector.In(kItemTag);
 | 
				
			||||||
 | 
					    auto multi_face_landmarks_no_iris =
 | 
				
			||||||
 | 
					        end_loop_landmark_list_vector.Out(kIterableTag)
 | 
				
			||||||
 | 
					            .Cast<std::vector<NormalizedLandmarkList>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Find the transformation from the canonical face to the list of multi face
 | 
				
			||||||
 | 
					    // landmarks.
 | 
				
			||||||
 | 
					    auto& geometry_pipeline = graph.AddNode(
 | 
				
			||||||
 | 
					        "mediapipe.tasks.vision.face_geometry.FaceGeometryPipelineCalculator");
 | 
				
			||||||
 | 
					    auto& geometry_pipeline_options =
 | 
				
			||||||
 | 
					        geometry_pipeline.GetOptions<FaceGeometryPipelineCalculatorOptions>();
 | 
				
			||||||
 | 
					    geometry_pipeline_options.set_metadata_path(kGeometryPipelineMetadataPath);
 | 
				
			||||||
 | 
					    image_size >> geometry_pipeline.In(kImageSizeTag);
 | 
				
			||||||
 | 
					    multi_face_landmarks_no_iris >>
 | 
				
			||||||
 | 
					        geometry_pipeline.In(kMultiFaceLandmarksTag);
 | 
				
			||||||
 | 
					    environment.value() >> geometry_pipeline.SideIn(kEnvironmentTag);
 | 
				
			||||||
 | 
					    auto multi_face_geometry = geometry_pipeline.Out(kMultiFaceGeometryTag)
 | 
				
			||||||
 | 
					                                   .Cast<std::vector<FaceGeometry>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {{/*multi_face_geometry */ multi_face_geometry}};
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// clang-format off
 | 
				
			||||||
 | 
					REGISTER_MEDIAPIPE_GRAPH(
 | 
				
			||||||
 | 
					  ::mediapipe::tasks::vision::face_geometry::FaceGeometryFromLandmarksGraph); // NOLINT
 | 
				
			||||||
 | 
					// clang-format on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  // namespace mediapipe::tasks::vision::face_geometry
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,153 @@
 | 
				
			||||||
 | 
					/* Copyright 2023 The MediaPipe Authors. All Rights Reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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.
 | 
				
			||||||
 | 
					==============================================================================*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <utility>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "absl/flags/flag.h"
 | 
				
			||||||
 | 
					#include "absl/status/statusor.h"
 | 
				
			||||||
 | 
					#include "absl/strings/str_format.h"
 | 
				
			||||||
 | 
					#include "absl/strings/string_view.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/api2/port.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/calculator_framework.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/calculator_runner.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/deps/file_path.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/formats/landmark.pb.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/packet.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/port/file_helpers.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/port/gmock.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/port/gtest.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/port/parse_text_proto.h"
 | 
				
			||||||
 | 
					#include "mediapipe/framework/tool/sink.h"
 | 
				
			||||||
 | 
					#include "mediapipe/tasks/cc/vision/face_geometry/proto/environment.pb.h"
 | 
				
			||||||
 | 
					#include "mediapipe/tasks/cc/vision/face_geometry/proto/face_geometry.pb.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace mediapipe {
 | 
				
			||||||
 | 
					namespace tasks {
 | 
				
			||||||
 | 
					namespace vision {
 | 
				
			||||||
 | 
					namespace face_geometry {
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using ::file::Defaults;
 | 
				
			||||||
 | 
					using ::mediapipe::tasks::vision::face_geometry::proto::Environment;
 | 
				
			||||||
 | 
					// using ::mediapipe::face_geometry::Environment;
 | 
				
			||||||
 | 
					using ::mediapipe::tasks::vision::face_geometry::proto::FaceGeometry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					constexpr char kTestDataDirectory[] = "/mediapipe/tasks/testdata/vision/";
 | 
				
			||||||
 | 
					constexpr char kFaceLandmarksFileName[] =
 | 
				
			||||||
 | 
					    "face_blendshapes_in_landmarks.prototxt";
 | 
				
			||||||
 | 
					constexpr char kFaceGeometryFileName[] = "face_geometry_expected_out.pbtxt";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::vector<NormalizedLandmarkList> GetLandmarks(absl::string_view filename) {
 | 
				
			||||||
 | 
					  NormalizedLandmarkList landmarks;
 | 
				
			||||||
 | 
					  MP_EXPECT_OK(GetTextProto(file::JoinPath("./", kTestDataDirectory, filename),
 | 
				
			||||||
 | 
					                            &landmarks, Defaults()));
 | 
				
			||||||
 | 
					  return {landmarks};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FaceGeometry GetExpectedFaceGeometry(absl::string_view filename) {
 | 
				
			||||||
 | 
					  FaceGeometry face_geometry;
 | 
				
			||||||
 | 
					  MP_EXPECT_OK(GetTextProto(file::JoinPath("./", kTestDataDirectory, filename),
 | 
				
			||||||
 | 
					                            &face_geometry, Defaults()));
 | 
				
			||||||
 | 
					  return face_geometry;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Environment CreateEnvironment() {
 | 
				
			||||||
 | 
					  Environment environment;
 | 
				
			||||||
 | 
					  environment.set_origin_point_location(
 | 
				
			||||||
 | 
					      proto::OriginPointLocation::TOP_LEFT_CORNER);
 | 
				
			||||||
 | 
					  auto& perspective_camera = *environment.mutable_perspective_camera();
 | 
				
			||||||
 | 
					  perspective_camera.set_vertical_fov_degrees(63.0 /*degrees*/);
 | 
				
			||||||
 | 
					  perspective_camera.set_near(1.0 /* 1cm */);
 | 
				
			||||||
 | 
					  perspective_camera.set_far(10000.0 /* 100m */);
 | 
				
			||||||
 | 
					  return environment;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void MakeInputPacketsAndRunGraph(CalculatorGraph& graph) {
 | 
				
			||||||
 | 
					  MP_ASSERT_OK(graph.StartRun({}));
 | 
				
			||||||
 | 
					  MP_ASSERT_OK(graph.AddPacketToInputStream(
 | 
				
			||||||
 | 
					      "face_landmarks", MakePacket<std::vector<NormalizedLandmarkList>>(
 | 
				
			||||||
 | 
					                            GetLandmarks(kFaceLandmarksFileName))
 | 
				
			||||||
 | 
					                            .At(Timestamp(0))));
 | 
				
			||||||
 | 
					  MP_ASSERT_OK(graph.AddPacketToInputStream(
 | 
				
			||||||
 | 
					      "image_size", MakePacket<std::pair<int, int>>(std::make_pair(820, 1024))
 | 
				
			||||||
 | 
					                        .At(Timestamp(0))));
 | 
				
			||||||
 | 
					  MP_ASSERT_OK(graph.WaitUntilIdle());
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(FaceGeometryFromLandmarksGraphTest, DefaultEnvironment) {
 | 
				
			||||||
 | 
					  CalculatorGraphConfig graph_config = ParseTextProtoOrDie<
 | 
				
			||||||
 | 
					      CalculatorGraphConfig>(R"pb(
 | 
				
			||||||
 | 
					    input_stream: "FACE_LANDMARKS:face_landmarks"
 | 
				
			||||||
 | 
					    input_stream: "IMAGE_SIZE:image_size"
 | 
				
			||||||
 | 
					    output_stream: "FACE_GEOMETRY:face_geometry"
 | 
				
			||||||
 | 
					    node {
 | 
				
			||||||
 | 
					      calculator: "mediapipe.tasks.vision.face_geometry.FaceGeometryFromLandmarksGraph"
 | 
				
			||||||
 | 
					      input_stream: "FACE_LANDMARKS:face_landmarks"
 | 
				
			||||||
 | 
					      input_stream: "IMAGE_SIZE:image_size"
 | 
				
			||||||
 | 
					      output_stream: "FACE_GEOMETRY:face_geometry"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  )pb");
 | 
				
			||||||
 | 
					  std::vector<Packet> output_packets;
 | 
				
			||||||
 | 
					  tool::AddVectorSink("face_geometry", &graph_config, &output_packets);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Run the graph.
 | 
				
			||||||
 | 
					  CalculatorGraph graph;
 | 
				
			||||||
 | 
					  MP_ASSERT_OK(graph.Initialize(graph_config));
 | 
				
			||||||
 | 
					  MakeInputPacketsAndRunGraph(graph);
 | 
				
			||||||
 | 
					  ASSERT_THAT(output_packets, testing::SizeIs(1));
 | 
				
			||||||
 | 
					  auto& face_geometry = output_packets[0].Get<std::vector<FaceGeometry>>()[0];
 | 
				
			||||||
 | 
					  EXPECT_THAT(
 | 
				
			||||||
 | 
					      face_geometry,
 | 
				
			||||||
 | 
					      testing::EqualsProto(GetExpectedFaceGeometry(kFaceGeometryFileName)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(FaceGeometryFromLandmarksGraphTest, SideInEnvironment) {
 | 
				
			||||||
 | 
					  CalculatorGraphConfig graph_config = ParseTextProtoOrDie<
 | 
				
			||||||
 | 
					      CalculatorGraphConfig>(R"pb(
 | 
				
			||||||
 | 
					    input_stream: "FACE_LANDMARKS:face_landmarks"
 | 
				
			||||||
 | 
					    input_stream: "IMAGE_SIZE:image_size"
 | 
				
			||||||
 | 
					    input_side_packet: "ENVIRONMENT:environment"
 | 
				
			||||||
 | 
					    output_stream: "FACE_GEOMETRY:face_geometry"
 | 
				
			||||||
 | 
					    node {
 | 
				
			||||||
 | 
					      calculator: "mediapipe.tasks.vision.face_geometry.FaceGeometryFromLandmarksGraph"
 | 
				
			||||||
 | 
					      input_stream: "FACE_LANDMARKS:face_landmarks"
 | 
				
			||||||
 | 
					      input_stream: "IMAGE_SIZE:image_size"
 | 
				
			||||||
 | 
					      input_side_packet: "ENVIRONMENT:environment"
 | 
				
			||||||
 | 
					      output_stream: "FACE_GEOMETRY:face_geometry"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  )pb");
 | 
				
			||||||
 | 
					  std::vector<Packet> output_packets;
 | 
				
			||||||
 | 
					  tool::AddVectorSink("face_geometry", &graph_config, &output_packets);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Run the graph.
 | 
				
			||||||
 | 
					  CalculatorGraph graph;
 | 
				
			||||||
 | 
					  std::map<std::string, Packet> input_side_packets;
 | 
				
			||||||
 | 
					  input_side_packets["environment"] =
 | 
				
			||||||
 | 
					      MakePacket<Environment>(CreateEnvironment());
 | 
				
			||||||
 | 
					  MP_ASSERT_OK(graph.Initialize(graph_config, input_side_packets));
 | 
				
			||||||
 | 
					  MakeInputPacketsAndRunGraph(graph);
 | 
				
			||||||
 | 
					  ASSERT_THAT(output_packets, testing::SizeIs(1));
 | 
				
			||||||
 | 
					  auto& face_geometry = output_packets[0].Get<std::vector<FaceGeometry>>()[0];
 | 
				
			||||||
 | 
					  EXPECT_THAT(
 | 
				
			||||||
 | 
					      face_geometry,
 | 
				
			||||||
 | 
					      testing::EqualsProto(GetExpectedFaceGeometry(kFaceGeometryFileName)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  // namespace
 | 
				
			||||||
 | 
					}  // namespace face_geometry
 | 
				
			||||||
 | 
					}  // namespace vision
 | 
				
			||||||
 | 
					}  // namespace tasks
 | 
				
			||||||
 | 
					}  // namespace mediapipe
 | 
				
			||||||
							
								
								
									
										2
									
								
								mediapipe/tasks/testdata/vision/BUILD
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								mediapipe/tasks/testdata/vision/BUILD
									
									
									
									
										vendored
									
									
								
							| 
						 | 
					@ -85,6 +85,7 @@ exports_files(
 | 
				
			||||||
        "expected_left_up_hand_rotated_landmarks.prototxt",
 | 
					        "expected_left_up_hand_rotated_landmarks.prototxt",
 | 
				
			||||||
        "expected_right_down_hand_landmarks.prototxt",
 | 
					        "expected_right_down_hand_landmarks.prototxt",
 | 
				
			||||||
        "expected_right_up_hand_landmarks.prototxt",
 | 
					        "expected_right_up_hand_landmarks.prototxt",
 | 
				
			||||||
 | 
					        "face_geometry_expected_out.pbtxt",
 | 
				
			||||||
        "gesture_recognizer.task",
 | 
					        "gesture_recognizer.task",
 | 
				
			||||||
        "portrait_expected_detection.pbtxt",
 | 
					        "portrait_expected_detection.pbtxt",
 | 
				
			||||||
        "portrait_rotated_expected_detection.pbtxt",
 | 
					        "portrait_rotated_expected_detection.pbtxt",
 | 
				
			||||||
| 
						 | 
					@ -172,6 +173,7 @@ filegroup(
 | 
				
			||||||
        "expected_left_up_hand_rotated_landmarks.prototxt",
 | 
					        "expected_left_up_hand_rotated_landmarks.prototxt",
 | 
				
			||||||
        "expected_right_down_hand_landmarks.prototxt",
 | 
					        "expected_right_down_hand_landmarks.prototxt",
 | 
				
			||||||
        "expected_right_up_hand_landmarks.prototxt",
 | 
					        "expected_right_up_hand_landmarks.prototxt",
 | 
				
			||||||
 | 
					        "face_geometry_expected_out.pbtxt",
 | 
				
			||||||
        "fist_landmarks.pbtxt",
 | 
					        "fist_landmarks.pbtxt",
 | 
				
			||||||
        "hand_detector_result_one_hand.pbtxt",
 | 
					        "hand_detector_result_one_hand.pbtxt",
 | 
				
			||||||
        "hand_detector_result_one_hand_rotated.pbtxt",
 | 
					        "hand_detector_result_one_hand_rotated.pbtxt",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										5060
									
								
								mediapipe/tasks/testdata/vision/face_geometry_expected_out.pbtxt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5060
									
								
								mediapipe/tasks/testdata/vision/face_geometry_expected_out.pbtxt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										30
									
								
								third_party/external_files.bzl
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								third_party/external_files.bzl
									
									
									
									
										vendored
									
									
								
							| 
						 | 
					@ -268,30 +268,6 @@ def external_files():
 | 
				
			||||||
        urls = ["https://storage.googleapis.com/mediapipe-assets/external_file.txt?generation=1661875736240688"],
 | 
					        urls = ["https://storage.googleapis.com/mediapipe-assets/external_file.txt?generation=1661875736240688"],
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    http_file(
 | 
					 | 
				
			||||||
        name = "com_google_mediapipe_face_blendshapes_generated_graph_pbtxt",
 | 
					 | 
				
			||||||
        sha256 = "92e016a08940e1f81752e749e1931f9e551fa9483786b8fba0624257e9c41d3d",
 | 
					 | 
				
			||||||
        urls = ["https://storage.googleapis.com/mediapipe-assets/face_blendshapes_generated_graph.pbtxt?generation=1677522753449135"],
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    http_file(
 | 
					 | 
				
			||||||
        name = "com_google_mediapipe_face_blendshapes_in_landmarks_prototxt",
 | 
					 | 
				
			||||||
        sha256 = "f6a10fa5825f2eee695371a449c605698403c146c270b2cb7574512f3f9e4af8",
 | 
					 | 
				
			||||||
        urls = ["https://storage.googleapis.com/mediapipe-assets/face_blendshapes_in_landmarks.prototxt?generation=1677522757270549"],
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    http_file(
 | 
					 | 
				
			||||||
        name = "com_google_mediapipe_face_blendshapes_out_prototxt",
 | 
					 | 
				
			||||||
        sha256 = "ea7740add8b87c9bd375eaa40a05b509eaca04f025cb6bdc7ca486e9fb32dfba",
 | 
					 | 
				
			||||||
        urls = ["https://storage.googleapis.com/mediapipe-assets/face_blendshapes_out.prototxt?generation=1677522761312644"],
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    http_file(
 | 
					 | 
				
			||||||
        name = "com_google_mediapipe_face_blendshapes_tflite",
 | 
					 | 
				
			||||||
        sha256 = "4f36dded049db18d76048567439b2a7f58f1daabc00d78bfe8f3ad396a2d2082",
 | 
					 | 
				
			||||||
        urls = ["https://storage.googleapis.com/mediapipe-assets/face_blendshapes.tflite?generation=1677522764748685"],
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    http_file(
 | 
					    http_file(
 | 
				
			||||||
        name = "com_google_mediapipe_face_detection_full_range_sparse_tflite",
 | 
					        name = "com_google_mediapipe_face_detection_full_range_sparse_tflite",
 | 
				
			||||||
        sha256 = "2c3728e6da56f21e21a320433396fb06d40d9088f2247c05e5635a688d45dfe1",
 | 
					        sha256 = "2c3728e6da56f21e21a320433396fb06d40d9088f2247c05e5635a688d45dfe1",
 | 
				
			||||||
| 
						 | 
					@ -310,6 +286,12 @@ def external_files():
 | 
				
			||||||
        urls = ["https://storage.googleapis.com/mediapipe-assets/face_detection_short_range.tflite?generation=1677044301978921"],
 | 
					        urls = ["https://storage.googleapis.com/mediapipe-assets/face_detection_short_range.tflite?generation=1677044301978921"],
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http_file(
 | 
				
			||||||
 | 
					        name = "com_google_mediapipe_face_geometry_expected_out_pbtxt",
 | 
				
			||||||
 | 
					        sha256 = "611b203bca40e547ae75bf0822fda0695d512d02940e7af08a70068eaa8524f7",
 | 
				
			||||||
 | 
					        urls = ["https://storage.googleapis.com/mediapipe-assets/face_geometry_expected_out.pbtxt?generation=1677787710308910"],
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    http_file(
 | 
					    http_file(
 | 
				
			||||||
        name = "com_google_mediapipe_face_landmark_tflite",
 | 
					        name = "com_google_mediapipe_face_landmark_tflite",
 | 
				
			||||||
        sha256 = "1055cb9d4a9ca8b8c688902a3a5194311138ba256bcc94e336d8373a5f30c814",
 | 
					        sha256 = "1055cb9d4a9ca8b8c688902a3a5194311138ba256bcc94e336d8373a5f30c814",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user