Add landmarks smoothing filter when requested face num is 1.
PiperOrigin-RevId: 520825046
This commit is contained in:
parent
ea9083c89d
commit
4ce87866da
|
@ -181,9 +181,12 @@ cc_library(
|
||||||
":face_landmarks_detector_graph",
|
":face_landmarks_detector_graph",
|
||||||
"//mediapipe/calculators/core:begin_loop_calculator",
|
"//mediapipe/calculators/core:begin_loop_calculator",
|
||||||
"//mediapipe/calculators/core:clip_vector_size_calculator_cc_proto",
|
"//mediapipe/calculators/core:clip_vector_size_calculator_cc_proto",
|
||||||
|
"//mediapipe/calculators/core:concatenate_vector_calculator",
|
||||||
"//mediapipe/calculators/core:end_loop_calculator",
|
"//mediapipe/calculators/core:end_loop_calculator",
|
||||||
"//mediapipe/calculators/core:gate_calculator",
|
"//mediapipe/calculators/core:gate_calculator",
|
||||||
"//mediapipe/calculators/core:gate_calculator_cc_proto",
|
"//mediapipe/calculators/core:gate_calculator_cc_proto",
|
||||||
|
"//mediapipe/calculators/core:get_vector_item_calculator",
|
||||||
|
"//mediapipe/calculators/core:get_vector_item_calculator_cc_proto",
|
||||||
"//mediapipe/calculators/core:pass_through_calculator",
|
"//mediapipe/calculators/core:pass_through_calculator",
|
||||||
"//mediapipe/calculators/core:previous_loopback_calculator",
|
"//mediapipe/calculators/core:previous_loopback_calculator",
|
||||||
"//mediapipe/calculators/image:image_properties_calculator",
|
"//mediapipe/calculators/image:image_properties_calculator",
|
||||||
|
@ -191,6 +194,8 @@ cc_library(
|
||||||
"//mediapipe/calculators/util:association_norm_rect_calculator",
|
"//mediapipe/calculators/util:association_norm_rect_calculator",
|
||||||
"//mediapipe/calculators/util:collection_has_min_size_calculator",
|
"//mediapipe/calculators/util:collection_has_min_size_calculator",
|
||||||
"//mediapipe/calculators/util:collection_has_min_size_calculator_cc_proto",
|
"//mediapipe/calculators/util:collection_has_min_size_calculator_cc_proto",
|
||||||
|
"//mediapipe/calculators/util:landmarks_smoothing_calculator",
|
||||||
|
"//mediapipe/calculators/util:landmarks_smoothing_calculator_cc_proto",
|
||||||
"//mediapipe/framework/api2:builder",
|
"//mediapipe/framework/api2:builder",
|
||||||
"//mediapipe/framework/api2:port",
|
"//mediapipe/framework/api2:port",
|
||||||
"//mediapipe/framework/formats:classification_cc_proto",
|
"//mediapipe/framework/formats:classification_cc_proto",
|
||||||
|
|
|
@ -20,9 +20,13 @@ limitations under the License.
|
||||||
|
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
#include "mediapipe/calculators/core/clip_vector_size_calculator.pb.h"
|
#include "mediapipe/calculators/core/clip_vector_size_calculator.pb.h"
|
||||||
|
#include "mediapipe/calculators/core/concatenate_vector_calculator.h"
|
||||||
#include "mediapipe/calculators/core/gate_calculator.pb.h"
|
#include "mediapipe/calculators/core/gate_calculator.pb.h"
|
||||||
|
#include "mediapipe/calculators/core/get_vector_item_calculator.h"
|
||||||
|
#include "mediapipe/calculators/core/get_vector_item_calculator.pb.h"
|
||||||
#include "mediapipe/calculators/util/association_calculator.pb.h"
|
#include "mediapipe/calculators/util/association_calculator.pb.h"
|
||||||
#include "mediapipe/calculators/util/collection_has_min_size_calculator.pb.h"
|
#include "mediapipe/calculators/util/collection_has_min_size_calculator.pb.h"
|
||||||
|
#include "mediapipe/calculators/util/landmarks_smoothing_calculator.pb.h"
|
||||||
#include "mediapipe/framework/api2/builder.h"
|
#include "mediapipe/framework/api2/builder.h"
|
||||||
#include "mediapipe/framework/api2/port.h"
|
#include "mediapipe/framework/api2/port.h"
|
||||||
#include "mediapipe/framework/formats/classification.pb.h"
|
#include "mediapipe/framework/formats/classification.pb.h"
|
||||||
|
@ -91,6 +95,9 @@ constexpr char kEnvironmentTag[] = "ENVIRONMENT";
|
||||||
constexpr char kBlendshapesTag[] = "BLENDSHAPES";
|
constexpr char kBlendshapesTag[] = "BLENDSHAPES";
|
||||||
constexpr char kImageSizeTag[] = "IMAGE_SIZE";
|
constexpr char kImageSizeTag[] = "IMAGE_SIZE";
|
||||||
constexpr char kSizeTag[] = "SIZE";
|
constexpr char kSizeTag[] = "SIZE";
|
||||||
|
constexpr char kVectorTag[] = "VECTOR";
|
||||||
|
constexpr char kItemTag[] = "ITEM";
|
||||||
|
constexpr char kNormFilteredLandmarksTag[] = "NORM_FILTERED_LANDMARKS";
|
||||||
constexpr char kFaceDetectorTFLiteName[] = "face_detector.tflite";
|
constexpr char kFaceDetectorTFLiteName[] = "face_detector.tflite";
|
||||||
constexpr char kFaceLandmarksDetectorTFLiteName[] =
|
constexpr char kFaceLandmarksDetectorTFLiteName[] =
|
||||||
"face_landmarks_detector.tflite";
|
"face_landmarks_detector.tflite";
|
||||||
|
@ -166,6 +173,18 @@ absl::Status SetSubTaskBaseOptions(const ModelAssetBundleResources& resources,
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigureLandmarksSmoothingCalculator(
|
||||||
|
mediapipe::LandmarksSmoothingCalculatorOptions& options) {
|
||||||
|
// Min cutoff 0.05 results into ~0.01 alpha in landmark EMA filter when
|
||||||
|
// landmark is static.
|
||||||
|
options.mutable_one_euro_filter()->set_min_cutoff(0.05f);
|
||||||
|
// Beta 80.0 in combintation with min_cutoff 0.05 results into ~0.94
|
||||||
|
// alpha in landmark EMA filter when landmark is moving fast.
|
||||||
|
options.mutable_one_euro_filter()->set_beta(80.0f);
|
||||||
|
// Derivative cutoff 1.0 results into ~0.17 alpha in landmark velocity
|
||||||
|
// EMA filter.
|
||||||
|
options.mutable_one_euro_filter()->set_derivate_cutoff(1.0f);
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// A "mediapipe.tasks.vision.face_landmarker.FaceLandmarkerGraph" performs face
|
// A "mediapipe.tasks.vision.face_landmarker.FaceLandmarkerGraph" performs face
|
||||||
|
@ -428,13 +447,46 @@ class FaceLandmarkerGraph : public core::ModelTaskGraph {
|
||||||
image_in >> face_landmarks_detector_graph.In(kImageTag);
|
image_in >> face_landmarks_detector_graph.In(kImageTag);
|
||||||
clipped_face_rects >> face_landmarks_detector_graph.In(kNormRectTag);
|
clipped_face_rects >> face_landmarks_detector_graph.In(kNormRectTag);
|
||||||
|
|
||||||
// TODO: add landmarks smoothing calculators.
|
std::optional<Source<std::vector<NormalizedLandmarkList>>> face_landmarks;
|
||||||
auto landmarks = face_landmarks_detector_graph.Out(kNormLandmarksTag)
|
face_landmarks = face_landmarks_detector_graph.Out(kNormLandmarksTag)
|
||||||
.Cast<std::vector<NormalizedLandmarkList>>();
|
.Cast<std::vector<NormalizedLandmarkList>>();
|
||||||
auto face_rects_for_next_frame =
|
auto face_rects_for_next_frame =
|
||||||
face_landmarks_detector_graph.Out(kFaceRectsNextFrameTag)
|
face_landmarks_detector_graph.Out(kFaceRectsNextFrameTag)
|
||||||
.Cast<std::vector<NormalizedRect>>();
|
.Cast<std::vector<NormalizedRect>>();
|
||||||
|
|
||||||
|
auto& image_properties = graph.AddNode("ImagePropertiesCalculator");
|
||||||
|
image_in >> image_properties.In(kImageTag);
|
||||||
|
auto image_size = image_properties.Out(kSizeTag);
|
||||||
|
|
||||||
|
// Apply smoothing filter only on the single face landmarks, because
|
||||||
|
// landmakrs smoothing calculator doesn't support multiple landmarks yet.
|
||||||
|
if (tasks_options.face_detector_graph_options().num_faces() == 1) {
|
||||||
|
// Get the single face landmarks
|
||||||
|
auto& get_vector_item =
|
||||||
|
graph.AddNode("GetNormalizedLandmarkListVectorItemCalculator");
|
||||||
|
get_vector_item.GetOptions<mediapipe::GetVectorItemCalculatorOptions>()
|
||||||
|
.set_item_index(0);
|
||||||
|
*face_landmarks >> get_vector_item.In(kVectorTag);
|
||||||
|
auto single_face_landmarks = get_vector_item.Out(kItemTag);
|
||||||
|
|
||||||
|
// Apply smoothing filter on face landmarks.
|
||||||
|
auto& landmarks_smoothing = graph.AddNode("LandmarksSmoothingCalculator");
|
||||||
|
ConfigureLandmarksSmoothingCalculator(
|
||||||
|
landmarks_smoothing
|
||||||
|
.GetOptions<mediapipe::LandmarksSmoothingCalculatorOptions>());
|
||||||
|
single_face_landmarks >> landmarks_smoothing.In(kNormLandmarksTag);
|
||||||
|
image_size >> landmarks_smoothing.In(kImageSizeTag);
|
||||||
|
auto smoothed_single_face_landmarks =
|
||||||
|
landmarks_smoothing.Out(kNormFilteredLandmarksTag);
|
||||||
|
|
||||||
|
// Wrap the single face landmarks into a vector of landmarks.
|
||||||
|
auto& concatenate_vector =
|
||||||
|
graph.AddNode("ConcatenateNormalizedLandmarkListVectorCalculator");
|
||||||
|
smoothed_single_face_landmarks >> concatenate_vector.In("");
|
||||||
|
face_landmarks.emplace(concatenate_vector.Out("")
|
||||||
|
.Cast<std::vector<NormalizedLandmarkList>>());
|
||||||
|
}
|
||||||
|
|
||||||
if (tasks_options.base_options().use_stream_mode()) {
|
if (tasks_options.base_options().use_stream_mode()) {
|
||||||
auto& previous_loopback = graph.AddNode("PreviousLoopbackCalculator");
|
auto& previous_loopback = graph.AddNode("PreviousLoopbackCalculator");
|
||||||
image_in >> previous_loopback.In(kMainTag);
|
image_in >> previous_loopback.In(kMainTag);
|
||||||
|
@ -491,9 +543,6 @@ class FaceLandmarkerGraph : public core::ModelTaskGraph {
|
||||||
// Optional face geometry output.
|
// Optional face geometry output.
|
||||||
std::optional<Source<std::vector<FaceGeometry>>> face_geometry;
|
std::optional<Source<std::vector<FaceGeometry>>> face_geometry;
|
||||||
if (output_geometry) {
|
if (output_geometry) {
|
||||||
auto& image_properties = graph.AddNode("ImagePropertiesCalculator");
|
|
||||||
image_in >> image_properties.In(kImageTag);
|
|
||||||
auto image_size = image_properties.Out(kSizeTag);
|
|
||||||
auto& face_geometry_from_landmarks = graph.AddNode(
|
auto& face_geometry_from_landmarks = graph.AddNode(
|
||||||
"mediapipe.tasks.vision.face_geometry."
|
"mediapipe.tasks.vision.face_geometry."
|
||||||
"FaceGeometryFromLandmarksGraph");
|
"FaceGeometryFromLandmarksGraph");
|
||||||
|
@ -503,7 +552,7 @@ class FaceLandmarkerGraph : public core::ModelTaskGraph {
|
||||||
if (environment.has_value()) {
|
if (environment.has_value()) {
|
||||||
*environment >> face_geometry_from_landmarks.SideIn(kEnvironmentTag);
|
*environment >> face_geometry_from_landmarks.SideIn(kEnvironmentTag);
|
||||||
}
|
}
|
||||||
landmarks >> face_geometry_from_landmarks.In(kFaceLandmarksTag);
|
*face_landmarks >> face_geometry_from_landmarks.In(kFaceLandmarksTag);
|
||||||
image_size >> face_geometry_from_landmarks.In(kImageSizeTag);
|
image_size >> face_geometry_from_landmarks.In(kImageSizeTag);
|
||||||
face_geometry = face_geometry_from_landmarks.Out(kFaceGeometryTag)
|
face_geometry = face_geometry_from_landmarks.Out(kFaceGeometryTag)
|
||||||
.Cast<std::vector<FaceGeometry>>();
|
.Cast<std::vector<FaceGeometry>>();
|
||||||
|
@ -515,7 +564,7 @@ class FaceLandmarkerGraph : public core::ModelTaskGraph {
|
||||||
image_in >> pass_through.In("");
|
image_in >> pass_through.In("");
|
||||||
|
|
||||||
return {{
|
return {{
|
||||||
/* landmark_lists= */ landmarks,
|
/* landmark_lists= */ *face_landmarks,
|
||||||
/* face_rects_next_frame= */
|
/* face_rects_next_frame= */
|
||||||
face_rects_for_next_frame,
|
face_rects_for_next_frame,
|
||||||
/* face_rects= */
|
/* face_rects= */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user