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