Add FaceLandmarkerResult for FaceLandmarker API
PiperOrigin-RevId: 514137566
This commit is contained in:
parent
cd14d2e688
commit
763842289a
|
@ -114,3 +114,31 @@ cc_library(
|
||||||
],
|
],
|
||||||
alwayslink = 1,
|
alwayslink = 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "face_landmarker_result",
|
||||||
|
srcs = ["face_landmarker_result.cc"],
|
||||||
|
hdrs = ["face_landmarker_result.h"],
|
||||||
|
deps = [
|
||||||
|
"//mediapipe/framework/formats:classification_cc_proto",
|
||||||
|
"//mediapipe/framework/formats:landmark_cc_proto",
|
||||||
|
"//mediapipe/framework/formats:matrix",
|
||||||
|
"//mediapipe/framework/formats:matrix_data_cc_proto",
|
||||||
|
"//mediapipe/tasks/cc/components/containers:classification_result",
|
||||||
|
"//mediapipe/tasks/cc/components/containers:landmark",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "face_landmarker_result_cc",
|
||||||
|
srcs = ["face_landmarker_result.cc"],
|
||||||
|
hdrs = ["face_landmarker_result.h"],
|
||||||
|
deps = [
|
||||||
|
"//mediapipe/framework/formats:classification_cc_proto",
|
||||||
|
"//mediapipe/framework/formats:landmark_cc_proto",
|
||||||
|
"//mediapipe/framework/formats:matrix",
|
||||||
|
"//mediapipe/framework/formats:matrix_data_cc_proto",
|
||||||
|
"//mediapipe/tasks/cc/components/containers:classification_result",
|
||||||
|
"//mediapipe/tasks/cc/components/containers:landmark",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
/* 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 "mediapipe/tasks/cc/vision/face_landmarker/face_landmarker_result.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "mediapipe/framework/formats/classification.pb.h"
|
||||||
|
#include "mediapipe/framework/formats/landmark.pb.h"
|
||||||
|
#include "mediapipe/framework/formats/matrix.h"
|
||||||
|
#include "mediapipe/framework/formats/matrix_data.pb.h"
|
||||||
|
#include "mediapipe/tasks/cc/components/containers/classification_result.h"
|
||||||
|
#include "mediapipe/tasks/cc/components/containers/landmark.h"
|
||||||
|
|
||||||
|
namespace mediapipe {
|
||||||
|
namespace tasks {
|
||||||
|
namespace vision {
|
||||||
|
namespace face_landmarker {
|
||||||
|
|
||||||
|
FaceLandmarkerResult ConvertToFaceLandmarkerResult(
|
||||||
|
std::vector<mediapipe::NormalizedLandmarkList> face_landmarks_proto,
|
||||||
|
std::optional<std::vector<mediapipe::ClassificationList>>
|
||||||
|
face_blendshapes_proto,
|
||||||
|
std::optional<std::vector<mediapipe::MatrixData>>
|
||||||
|
facial_transformation_matrix_proto) {
|
||||||
|
FaceLandmarkerResult result;
|
||||||
|
result.face_landmarks.resize(face_landmarks_proto.size());
|
||||||
|
std::transform(face_landmarks_proto.begin(), face_landmarks_proto.end(),
|
||||||
|
result.face_landmarks.begin(),
|
||||||
|
components::containers::ConvertToNormalizedLandmarks);
|
||||||
|
if (face_blendshapes_proto.has_value()) {
|
||||||
|
result.face_blendshapes =
|
||||||
|
std::vector<components::containers::Classifications>(
|
||||||
|
face_blendshapes_proto->size());
|
||||||
|
std::transform(
|
||||||
|
face_blendshapes_proto->begin(), face_blendshapes_proto->end(),
|
||||||
|
result.face_blendshapes->begin(),
|
||||||
|
[](const mediapipe::ClassificationList& classification_list) {
|
||||||
|
return components::containers::ConvertToClassifications(
|
||||||
|
classification_list);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (facial_transformation_matrix_proto.has_value()) {
|
||||||
|
result.facial_transformation_matrix =
|
||||||
|
std::vector<Matrix>(facial_transformation_matrix_proto->size());
|
||||||
|
std::transform(facial_transformation_matrix_proto->begin(),
|
||||||
|
facial_transformation_matrix_proto->end(),
|
||||||
|
result.facial_transformation_matrix->begin(),
|
||||||
|
[](const mediapipe::MatrixData& matrix_proto) {
|
||||||
|
mediapipe::Matrix matrix;
|
||||||
|
MatrixFromMatrixDataProto(matrix_proto, &matrix);
|
||||||
|
return matrix;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace face_landmarker
|
||||||
|
} // namespace vision
|
||||||
|
} // namespace tasks
|
||||||
|
} // namespace mediapipe
|
|
@ -0,0 +1,59 @@
|
||||||
|
/* 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.
|
||||||
|
==============================================================================*/
|
||||||
|
|
||||||
|
#ifndef MEDIAPIPE_TASKS_CC_VISION_FACE_LANDMARKER_FACE_LANDMARKER_RESULT_H_
|
||||||
|
#define MEDIAPIPE_TASKS_CC_VISION_FACE_LANDMARKER_FACE_LANDMARKER_RESULT_H_
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "mediapipe/framework/formats/classification.pb.h"
|
||||||
|
#include "mediapipe/framework/formats/landmark.pb.h"
|
||||||
|
#include "mediapipe/framework/formats/matrix.h"
|
||||||
|
#include "mediapipe/framework/formats/matrix_data.pb.h"
|
||||||
|
#include "mediapipe/tasks/cc/components/containers/classification_result.h"
|
||||||
|
#include "mediapipe/tasks/cc/components/containers/landmark.h"
|
||||||
|
|
||||||
|
namespace mediapipe {
|
||||||
|
namespace tasks {
|
||||||
|
namespace vision {
|
||||||
|
namespace face_landmarker {
|
||||||
|
|
||||||
|
// The face landmarks detection result from FaceLandmarker, where each vector
|
||||||
|
// element represents a single face detected in the image.
|
||||||
|
struct FaceLandmarkerResult {
|
||||||
|
// Detected hand landmarks in normalized image coordinates.
|
||||||
|
std::vector<components::containers::NormalizedLandmarks> face_landmarks;
|
||||||
|
// Optional face blendshapes results.
|
||||||
|
std::optional<std::vector<components::containers::Classifications>>
|
||||||
|
face_blendshapes;
|
||||||
|
// Optional facial transformation matrix.
|
||||||
|
std::optional<std::vector<Matrix>> facial_transformation_matrix;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convert face landmarks result from proto format to FaceLandmarkerResult.
|
||||||
|
FaceLandmarkerResult ConvertToFaceLandmarkerResult(
|
||||||
|
std::vector<mediapipe::NormalizedLandmarkList> face_landmarks_proto,
|
||||||
|
std::optional<std::vector<mediapipe::ClassificationList>>
|
||||||
|
face_blendshapes_proto = std::nullopt,
|
||||||
|
std::optional<std::vector<mediapipe::MatrixData>>
|
||||||
|
facial_transformation_matrix_proto = std::nullopt);
|
||||||
|
|
||||||
|
} // namespace face_landmarker
|
||||||
|
} // namespace vision
|
||||||
|
} // namespace tasks
|
||||||
|
} // namespace mediapipe
|
||||||
|
|
||||||
|
#endif // MEDIAPIPE_TASKS_CC_VISION_FACE_LANDMARKER_FACE_LANDMARKER_RESULT_H_
|
|
@ -0,0 +1,85 @@
|
||||||
|
/* 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 "mediapipe/tasks/cc/vision/face_landmarker/face_landmarker_result.h"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "mediapipe/framework/formats/classification.pb.h"
|
||||||
|
#include "mediapipe/framework/formats/landmark.pb.h"
|
||||||
|
#include "mediapipe/framework/formats/matrix.h"
|
||||||
|
#include "mediapipe/framework/formats/matrix_data.pb.h"
|
||||||
|
#include "mediapipe/framework/port/gmock.h"
|
||||||
|
#include "mediapipe/framework/port/gtest.h"
|
||||||
|
|
||||||
|
namespace mediapipe {
|
||||||
|
namespace tasks {
|
||||||
|
namespace vision {
|
||||||
|
namespace face_landmarker {
|
||||||
|
|
||||||
|
class FaceLandmarkerResultTest : public ::testing::Test {};
|
||||||
|
|
||||||
|
TEST(FaceLandmarkerResultTest, Succeeds) {
|
||||||
|
mediapipe::NormalizedLandmarkList face_landmarks_proto;
|
||||||
|
mediapipe::NormalizedLandmark& normalized_landmark_proto =
|
||||||
|
*face_landmarks_proto.add_landmark();
|
||||||
|
normalized_landmark_proto.set_x(0.1);
|
||||||
|
normalized_landmark_proto.set_y(0.2);
|
||||||
|
normalized_landmark_proto.set_z(0.3);
|
||||||
|
|
||||||
|
mediapipe::ClassificationList face_blendshapes_proto;
|
||||||
|
mediapipe::Classification& classification_proto =
|
||||||
|
*face_blendshapes_proto.add_classification();
|
||||||
|
classification_proto.set_index(1);
|
||||||
|
classification_proto.set_score(0.9075446);
|
||||||
|
classification_proto.set_label("browDownLeft");
|
||||||
|
|
||||||
|
mediapipe::MatrixData matrix_proto;
|
||||||
|
matrix_proto.set_rows(3);
|
||||||
|
matrix_proto.set_cols(3);
|
||||||
|
for (int i = 0; i < matrix_proto.rows() * matrix_proto.cols(); i++) {
|
||||||
|
matrix_proto.add_packed_data(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
FaceLandmarkerResult face_landmarker_result = ConvertToFaceLandmarkerResult(
|
||||||
|
{{face_landmarks_proto}}, {{face_blendshapes_proto}}, {{matrix_proto}});
|
||||||
|
|
||||||
|
EXPECT_EQ(face_landmarker_result.face_landmarks.size(), 1);
|
||||||
|
EXPECT_EQ(face_landmarker_result.face_landmarks[0].landmarks.size(), 1);
|
||||||
|
EXPECT_THAT(face_landmarker_result.face_landmarks[0].landmarks[0],
|
||||||
|
testing::FieldsAre(testing::FloatEq(0.1), testing::FloatEq(0.2),
|
||||||
|
testing::FloatEq(0.3), std::nullopt,
|
||||||
|
std::nullopt, std::nullopt));
|
||||||
|
|
||||||
|
ASSERT_TRUE(face_landmarker_result.face_blendshapes.has_value());
|
||||||
|
EXPECT_EQ(face_landmarker_result.face_blendshapes->size(), 1);
|
||||||
|
EXPECT_EQ(face_landmarker_result.face_blendshapes->at(0).categories.size(),
|
||||||
|
1);
|
||||||
|
EXPECT_THAT(face_landmarker_result.face_blendshapes->at(0).categories[0],
|
||||||
|
testing::FieldsAre(1, testing::FloatEq(0.9075446), "browDownLeft",
|
||||||
|
std::nullopt));
|
||||||
|
|
||||||
|
Matrix expected_matrix{{0, 3, 6}, {1, 4, 7}, {2, 5, 8}};
|
||||||
|
ASSERT_TRUE(face_landmarker_result.facial_transformation_matrix.has_value());
|
||||||
|
EXPECT_EQ(face_landmarker_result.facial_transformation_matrix->size(), 1);
|
||||||
|
EXPECT_EQ(face_landmarker_result.facial_transformation_matrix->at(0),
|
||||||
|
expected_matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace face_landmarker
|
||||||
|
} // namespace vision
|
||||||
|
} // namespace tasks
|
||||||
|
} // namespace mediapipe
|
Loading…
Reference in New Issue
Block a user