Project import generated by Copybara.
GitOrigin-RevId: 5b23708185311ae39a8605b0c2eff721e7b4939f
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
# Copyright 2019 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.
|
||||
|
||||
load(
|
||||
"//mediapipe/framework/tool:mediapipe_graph.bzl",
|
||||
"mediapipe_binary_graph",
|
||||
)
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
cc_library(
|
||||
name = "iris_depth_cpu_deps",
|
||||
deps = [
|
||||
"//mediapipe/calculators/core:constant_side_packet_calculator",
|
||||
"//mediapipe/calculators/core:flow_limiter_calculator",
|
||||
"//mediapipe/calculators/core:split_vector_calculator",
|
||||
"//mediapipe/calculators/image:image_file_properties_calculator",
|
||||
"//mediapipe/calculators/image:opencv_encoded_image_to_image_frame_calculator",
|
||||
"//mediapipe/calculators/image:opencv_image_encoder_calculator",
|
||||
"//mediapipe/graphs/iris_tracking/subgraphs:iris_and_depth_renderer_cpu",
|
||||
"//mediapipe/modules/face_landmark:face_landmark_front_cpu",
|
||||
"//mediapipe/modules/iris_landmark:iris_landmark_left_and_right_cpu",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "iris_tracking_cpu_deps",
|
||||
deps = [
|
||||
"//mediapipe/calculators/core:constant_side_packet_calculator",
|
||||
"//mediapipe/calculators/core:flow_limiter_calculator",
|
||||
"//mediapipe/calculators/core:split_vector_calculator",
|
||||
"//mediapipe/graphs/iris_tracking/subgraphs:iris_renderer_cpu",
|
||||
"//mediapipe/modules/face_landmark:face_landmark_front_cpu",
|
||||
"//mediapipe/modules/iris_landmark:iris_landmark_left_and_right_cpu",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "iris_tracking_cpu_video_input_deps",
|
||||
deps = [
|
||||
"//mediapipe/calculators/core:constant_side_packet_calculator",
|
||||
"//mediapipe/calculators/core:flow_limiter_calculator",
|
||||
"//mediapipe/calculators/core:split_vector_calculator",
|
||||
"//mediapipe/calculators/video:opencv_video_decoder_calculator",
|
||||
"//mediapipe/calculators/video:opencv_video_encoder_calculator",
|
||||
"//mediapipe/graphs/iris_tracking/subgraphs:iris_renderer_cpu",
|
||||
"//mediapipe/modules/face_landmark:face_landmark_front_cpu",
|
||||
"//mediapipe/modules/iris_landmark:iris_landmark_left_and_right_cpu",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "iris_tracking_gpu_deps",
|
||||
deps = [
|
||||
"//mediapipe/calculators/core:constant_side_packet_calculator",
|
||||
"//mediapipe/calculators/core:flow_limiter_calculator",
|
||||
"//mediapipe/calculators/core:split_vector_calculator",
|
||||
"//mediapipe/graphs/iris_tracking/subgraphs:iris_and_depth_renderer_gpu",
|
||||
"//mediapipe/modules/face_landmark:face_landmark_front_gpu",
|
||||
"//mediapipe/modules/iris_landmark:iris_landmark_left_and_right_gpu",
|
||||
],
|
||||
)
|
||||
|
||||
mediapipe_binary_graph(
|
||||
name = "iris_tracking_gpu_binary_graph",
|
||||
graph = "iris_tracking_gpu.pbtxt",
|
||||
output_name = "iris_tracking_gpu.binarypb",
|
||||
deps = [":iris_tracking_gpu_deps"],
|
||||
)
|
||||
@@ -0,0 +1,92 @@
|
||||
# Copyright 2019 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.
|
||||
|
||||
load("//mediapipe/framework/port:build_config.bzl", "mediapipe_cc_proto_library")
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
proto_library(
|
||||
name = "iris_to_render_data_calculator_proto",
|
||||
srcs = ["iris_to_render_data_calculator.proto"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//mediapipe/framework:calculator_proto",
|
||||
"//mediapipe/util:color_proto",
|
||||
"//mediapipe/util:render_data_proto",
|
||||
],
|
||||
)
|
||||
|
||||
mediapipe_cc_proto_library(
|
||||
name = "iris_to_render_data_calculator_cc_proto",
|
||||
srcs = ["iris_to_render_data_calculator.proto"],
|
||||
cc_deps = [
|
||||
"//mediapipe/framework:calculator_cc_proto",
|
||||
"//mediapipe/util:color_cc_proto",
|
||||
"//mediapipe/util:render_data_cc_proto",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [":iris_to_render_data_calculator_proto"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "iris_to_render_data_calculator",
|
||||
srcs = ["iris_to_render_data_calculator.cc"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":iris_to_render_data_calculator_cc_proto",
|
||||
"//mediapipe/framework:calculator_framework",
|
||||
"//mediapipe/framework/formats:landmark_cc_proto",
|
||||
"//mediapipe/framework/port:ret_check",
|
||||
"//mediapipe/framework/port:status",
|
||||
"//mediapipe/util:color_cc_proto",
|
||||
"//mediapipe/util:render_data_cc_proto",
|
||||
"@com_google_absl//absl/strings",
|
||||
],
|
||||
alwayslink = 1,
|
||||
)
|
||||
|
||||
proto_library(
|
||||
name = "iris_to_depth_calculator_proto",
|
||||
srcs = ["iris_to_depth_calculator.proto"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//mediapipe/framework:calculator_proto",
|
||||
],
|
||||
)
|
||||
|
||||
mediapipe_cc_proto_library(
|
||||
name = "iris_to_depth_calculator_cc_proto",
|
||||
srcs = ["iris_to_depth_calculator.proto"],
|
||||
cc_deps = [
|
||||
"//mediapipe/framework:calculator_cc_proto",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [":iris_to_depth_calculator_proto"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "iris_to_depth_calculator",
|
||||
srcs = ["iris_to_depth_calculator.cc"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":iris_to_depth_calculator_cc_proto",
|
||||
"//mediapipe/framework:calculator_framework",
|
||||
"//mediapipe/framework/formats:image_file_properties_cc_proto",
|
||||
"//mediapipe/framework/formats:landmark_cc_proto",
|
||||
"//mediapipe/framework/port:ret_check",
|
||||
"//mediapipe/framework/port:status",
|
||||
"@com_google_absl//absl/strings",
|
||||
],
|
||||
alwayslink = 1,
|
||||
)
|
||||
@@ -0,0 +1,245 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "mediapipe/framework/calculator_framework.h"
|
||||
#include "mediapipe/framework/formats/image_file_properties.pb.h"
|
||||
#include "mediapipe/framework/formats/landmark.pb.h"
|
||||
#include "mediapipe/framework/port/ret_check.h"
|
||||
#include "mediapipe/framework/port/status.h"
|
||||
#include "mediapipe/graphs/iris_tracking/calculators/iris_to_depth_calculator.pb.h"
|
||||
|
||||
namespace mediapipe {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kIrisTag[] = "IRIS";
|
||||
constexpr char kImageSizeTag[] = "IMAGE_SIZE";
|
||||
constexpr char kFocalLengthPixelTag[] = "FOCAL_LENGTH";
|
||||
constexpr char kImageFilePropertiesTag[] = "IMAGE_FILE_PROPERTIES";
|
||||
constexpr char kLeftIrisDepthTag[] = "LEFT_IRIS_DEPTH_MM";
|
||||
constexpr char kRightIrisDepthTag[] = "RIGHT_IRIS_DEPTH_MM";
|
||||
constexpr int kNumIrisLandmarksPerEye = 5;
|
||||
constexpr float kDepthWeightUpdate = 0.1;
|
||||
// Avergae fixed iris size across human beings.
|
||||
constexpr float kIrisSizeInMM = 11.8;
|
||||
|
||||
inline float GetDepth(float x0, float y0, float x1, float y1) {
|
||||
return std::sqrt((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1));
|
||||
}
|
||||
|
||||
inline float GetLandmarkDepth(const NormalizedLandmark& ld0,
|
||||
const NormalizedLandmark& ld1,
|
||||
const std::pair<int, int>& image_size) {
|
||||
return GetDepth(ld0.x() * image_size.first, ld0.y() * image_size.second,
|
||||
ld1.x() * image_size.first, ld1.y() * image_size.second);
|
||||
}
|
||||
|
||||
float CalculateIrisDiameter(const NormalizedLandmarkList& landmarks,
|
||||
const std::pair<int, int>& image_size) {
|
||||
const float dist_vert = GetLandmarkDepth(landmarks.landmark(1),
|
||||
landmarks.landmark(2), image_size);
|
||||
const float dist_hori = GetLandmarkDepth(landmarks.landmark(3),
|
||||
landmarks.landmark(4), image_size);
|
||||
return (dist_hori + dist_vert) / 2.0f;
|
||||
}
|
||||
|
||||
float CalculateDepth(const NormalizedLandmark& center, float focal_length,
|
||||
float iris_size, float img_w, float img_h) {
|
||||
std::pair<float, float> origin{img_w / 2.f, img_h / 2.f};
|
||||
const auto y = GetDepth(origin.first, origin.second, center.x() * img_w,
|
||||
center.y() * img_h);
|
||||
const auto x = std::sqrt(focal_length * focal_length + y * y);
|
||||
const auto depth = kIrisSizeInMM * x / iris_size;
|
||||
return depth;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Estimates depth from iris to camera given focal length and image size.
|
||||
//
|
||||
// Usage example:
|
||||
// node {
|
||||
// calculator: "IrisToDepthCalculator"
|
||||
// # A NormalizedLandmarkList contains landmarks for both iris.
|
||||
// input_stream: "IRIS:iris_landmarks"
|
||||
// input_stream: "IMAGE_SIZE:image_size"
|
||||
// # Note: Only one of FOCAL_LENGTH or IMAGE_FILE_PROPERTIES is necessary
|
||||
// # to get focal length in pixels. Sending focal length in pixels to
|
||||
// # this calculator is optional.
|
||||
// input_side_packet: "FOCAL_LENGTH:focal_length_pixel"
|
||||
// # OR
|
||||
// input_side_packet: "IMAGE_FILE_PROPERTIES:image_file_properties"
|
||||
// output_stream: "LEFT_IRIS_DEPTH_MM:left_iris_depth_mm"
|
||||
// output_stream: "RIGHT_IRIS_DEPTH_MM:right_iris_depth_mm"
|
||||
// }
|
||||
class IrisToDepthCalculator : public CalculatorBase {
|
||||
public:
|
||||
static ::mediapipe::Status GetContract(CalculatorContract* cc) {
|
||||
cc->Inputs().Tag(kIrisTag).Set<NormalizedLandmarkList>();
|
||||
cc->Inputs().Tag(kImageSizeTag).Set<std::pair<int, int>>();
|
||||
|
||||
// Only one of kFocalLengthPixelTag or kImageFilePropertiesTag must exist
|
||||
// if they are present.
|
||||
RET_CHECK(!(cc->InputSidePackets().HasTag(kFocalLengthPixelTag) &&
|
||||
cc->InputSidePackets().HasTag(kImageFilePropertiesTag)));
|
||||
if (cc->InputSidePackets().HasTag(kFocalLengthPixelTag)) {
|
||||
cc->InputSidePackets().Tag(kFocalLengthPixelTag).SetAny();
|
||||
}
|
||||
if (cc->InputSidePackets().HasTag(kImageFilePropertiesTag)) {
|
||||
cc->InputSidePackets()
|
||||
.Tag(kImageFilePropertiesTag)
|
||||
.Set<ImageFileProperties>();
|
||||
}
|
||||
if (cc->Outputs().HasTag(kLeftIrisDepthTag)) {
|
||||
cc->Outputs().Tag(kLeftIrisDepthTag).Set<float>();
|
||||
}
|
||||
if (cc->Outputs().HasTag(kRightIrisDepthTag)) {
|
||||
cc->Outputs().Tag(kRightIrisDepthTag).Set<float>();
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status Open(CalculatorContext* cc) override;
|
||||
|
||||
::mediapipe::Status Process(CalculatorContext* cc) override;
|
||||
|
||||
private:
|
||||
float focal_length_pixels_ = -1.f;
|
||||
// TODO: Consolidate the logic when switching to input stream for
|
||||
// focal length.
|
||||
bool compute_depth_from_iris_ = false;
|
||||
float smoothed_left_depth_mm_ = -1.f;
|
||||
float smoothed_right_depth_mm_ = -1.f;
|
||||
|
||||
void GetLeftIris(const NormalizedLandmarkList& lds,
|
||||
NormalizedLandmarkList* iris);
|
||||
void GetRightIris(const NormalizedLandmarkList& lds,
|
||||
NormalizedLandmarkList* iris);
|
||||
::mediapipe::IrisToDepthCalculatorOptions options_;
|
||||
};
|
||||
REGISTER_CALCULATOR(IrisToDepthCalculator);
|
||||
|
||||
::mediapipe::Status IrisToDepthCalculator::Open(CalculatorContext* cc) {
|
||||
cc->SetOffset(TimestampDiff(0));
|
||||
if (cc->InputSidePackets().HasTag(kFocalLengthPixelTag)) {
|
||||
#if defined(__APPLE__)
|
||||
focal_length_pixels_ = *cc->InputSidePackets()
|
||||
.Tag(kFocalLengthPixelTag)
|
||||
.Get<std::unique_ptr<float>>();
|
||||
#else
|
||||
focal_length_pixels_ =
|
||||
cc->InputSidePackets().Tag(kFocalLengthPixelTag).Get<float>();
|
||||
#endif
|
||||
compute_depth_from_iris_ = true;
|
||||
} else if (cc->InputSidePackets().HasTag(kImageFilePropertiesTag)) {
|
||||
const auto& properties = cc->InputSidePackets()
|
||||
.Tag(kImageFilePropertiesTag)
|
||||
.Get<ImageFileProperties>();
|
||||
focal_length_pixels_ = properties.focal_length_pixels();
|
||||
compute_depth_from_iris_ = true;
|
||||
}
|
||||
|
||||
options_ = cc->Options<::mediapipe::IrisToDepthCalculatorOptions>();
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status IrisToDepthCalculator::Process(CalculatorContext* cc) {
|
||||
// Only process if there's input landmarks.
|
||||
if (cc->Inputs().Tag(kIrisTag).IsEmpty()) {
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
const auto& iris_landmarks =
|
||||
cc->Inputs().Tag(kIrisTag).Get<NormalizedLandmarkList>();
|
||||
RET_CHECK_EQ(iris_landmarks.landmark_size(), kNumIrisLandmarksPerEye * 2)
|
||||
<< "Wrong number of iris landmarks";
|
||||
|
||||
std::pair<int, int> image_size;
|
||||
RET_CHECK(!cc->Inputs().Tag(kImageSizeTag).IsEmpty());
|
||||
image_size = cc->Inputs().Tag(kImageSizeTag).Get<std::pair<int, int>>();
|
||||
|
||||
auto left_iris = absl::make_unique<NormalizedLandmarkList>();
|
||||
auto right_iris = absl::make_unique<NormalizedLandmarkList>();
|
||||
GetLeftIris(iris_landmarks, left_iris.get());
|
||||
GetRightIris(iris_landmarks, right_iris.get());
|
||||
|
||||
const auto left_iris_size = CalculateIrisDiameter(*left_iris, image_size);
|
||||
const auto right_iris_size = CalculateIrisDiameter(*right_iris, image_size);
|
||||
|
||||
#if defined(__APPLE__)
|
||||
if (cc->InputSidePackets().HasTag(kFocalLengthPixelTag)) {
|
||||
focal_length_pixels_ = *cc->InputSidePackets()
|
||||
.Tag(kFocalLengthPixelTag)
|
||||
.Get<std::unique_ptr<float>>();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (compute_depth_from_iris_ && focal_length_pixels_ > 0) {
|
||||
const auto left_depth =
|
||||
CalculateDepth(left_iris->landmark(0), focal_length_pixels_,
|
||||
left_iris_size, image_size.first, image_size.second);
|
||||
const auto right_depth =
|
||||
CalculateDepth(right_iris->landmark(0), focal_length_pixels_,
|
||||
right_iris_size, image_size.first, image_size.second);
|
||||
smoothed_left_depth_mm_ =
|
||||
smoothed_left_depth_mm_ < 0 || std::isinf(smoothed_left_depth_mm_)
|
||||
? left_depth
|
||||
: smoothed_left_depth_mm_ * (1 - kDepthWeightUpdate) +
|
||||
left_depth * kDepthWeightUpdate;
|
||||
smoothed_right_depth_mm_ =
|
||||
smoothed_right_depth_mm_ < 0 || std::isinf(smoothed_right_depth_mm_)
|
||||
? right_depth
|
||||
: smoothed_right_depth_mm_ * (1 - kDepthWeightUpdate) +
|
||||
right_depth * kDepthWeightUpdate;
|
||||
|
||||
if (cc->Outputs().HasTag(kLeftIrisDepthTag)) {
|
||||
cc->Outputs()
|
||||
.Tag(kLeftIrisDepthTag)
|
||||
.AddPacket(MakePacket<float>(smoothed_left_depth_mm_)
|
||||
.At(cc->InputTimestamp()));
|
||||
}
|
||||
if (cc->Outputs().HasTag(kRightIrisDepthTag)) {
|
||||
cc->Outputs()
|
||||
.Tag(kRightIrisDepthTag)
|
||||
.AddPacket(MakePacket<float>(smoothed_right_depth_mm_)
|
||||
.At(cc->InputTimestamp()));
|
||||
}
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
void IrisToDepthCalculator::GetLeftIris(const NormalizedLandmarkList& lds,
|
||||
NormalizedLandmarkList* iris) {
|
||||
// Center, top, bottom, left, right
|
||||
*iris->add_landmark() = lds.landmark(options_.left_iris_center_index());
|
||||
*iris->add_landmark() = lds.landmark(options_.left_iris_top_index());
|
||||
*iris->add_landmark() = lds.landmark(options_.left_iris_bottom_index());
|
||||
*iris->add_landmark() = lds.landmark(options_.left_iris_left_index());
|
||||
*iris->add_landmark() = lds.landmark(options_.left_iris_right_index());
|
||||
}
|
||||
|
||||
void IrisToDepthCalculator::GetRightIris(const NormalizedLandmarkList& lds,
|
||||
NormalizedLandmarkList* iris) {
|
||||
// Center, top, bottom, left, right
|
||||
*iris->add_landmark() = lds.landmark(options_.right_iris_center_index());
|
||||
*iris->add_landmark() = lds.landmark(options_.right_iris_top_index());
|
||||
*iris->add_landmark() = lds.landmark(options_.right_iris_bottom_index());
|
||||
*iris->add_landmark() = lds.landmark(options_.right_iris_left_index());
|
||||
*iris->add_landmark() = lds.landmark(options_.right_iris_right_index());
|
||||
}
|
||||
} // namespace mediapipe
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
|
||||
message IrisToDepthCalculatorOptions {
|
||||
extend CalculatorOptions {
|
||||
optional IrisToDepthCalculatorOptions ext = 303429002;
|
||||
}
|
||||
|
||||
// Indices of correspondent left iris landmarks in input stream.
|
||||
optional int32 left_iris_center_index = 1 [default = 0];
|
||||
optional int32 left_iris_top_index = 2 [default = 2];
|
||||
optional int32 left_iris_bottom_index = 3 [default = 4];
|
||||
optional int32 left_iris_left_index = 4 [default = 3];
|
||||
optional int32 left_iris_right_index = 5 [default = 1];
|
||||
|
||||
// Indices of correspondent right iris landmarks in input stream.
|
||||
optional int32 right_iris_center_index = 6 [default = 5];
|
||||
optional int32 right_iris_top_index = 7 [default = 7];
|
||||
optional int32 right_iris_bottom_index = 8 [default = 9];
|
||||
optional int32 right_iris_left_index = 9 [default = 6];
|
||||
optional int32 right_iris_right_index = 10 [default = 8];
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "mediapipe/framework/calculator_framework.h"
|
||||
#include "mediapipe/framework/formats/landmark.pb.h"
|
||||
#include "mediapipe/framework/port/ret_check.h"
|
||||
#include "mediapipe/framework/port/status.h"
|
||||
#include "mediapipe/graphs/iris_tracking/calculators/iris_to_render_data_calculator.pb.h"
|
||||
#include "mediapipe/util/color.pb.h"
|
||||
#include "mediapipe/util/render_data.pb.h"
|
||||
|
||||
namespace mediapipe {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kIrisTag[] = "IRIS";
|
||||
constexpr char kRenderDataTag[] = "RENDER_DATA";
|
||||
constexpr char kImageSizeTag[] = "IMAGE_SIZE";
|
||||
constexpr char kLeftIrisDepthTag[] = "LEFT_IRIS_DEPTH_MM";
|
||||
constexpr char kRightIrisDepthTag[] = "RIGHT_IRIS_DEPTH_MM";
|
||||
constexpr char kOvalLabel[] = "OVAL";
|
||||
constexpr float kFontHeightScale = 1.5f;
|
||||
constexpr int kNumIrisLandmarksPerEye = 5;
|
||||
// TODO: Source.
|
||||
constexpr float kIrisSizeInMM = 11.8;
|
||||
|
||||
inline void SetColor(RenderAnnotation* annotation, const Color& color) {
|
||||
annotation->mutable_color()->set_r(color.r());
|
||||
annotation->mutable_color()->set_g(color.g());
|
||||
annotation->mutable_color()->set_b(color.b());
|
||||
}
|
||||
|
||||
inline float GetDepth(float x0, float y0, float x1, float y1) {
|
||||
return std::sqrt((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1));
|
||||
}
|
||||
|
||||
inline float GetLandmarkDepth(const NormalizedLandmark& ld0,
|
||||
const NormalizedLandmark& ld1,
|
||||
const std::pair<int, int>& image_size) {
|
||||
return GetDepth(ld0.x() * image_size.first, ld0.y() * image_size.second,
|
||||
ld1.x() * image_size.first, ld1.y() * image_size.second);
|
||||
}
|
||||
|
||||
float CalculateIrisDiameter(const NormalizedLandmarkList& landmarks,
|
||||
const std::pair<int, int>& image_size) {
|
||||
const float dist_vert = GetLandmarkDepth(landmarks.landmark(1),
|
||||
landmarks.landmark(2), image_size);
|
||||
const float dist_hori = GetLandmarkDepth(landmarks.landmark(3),
|
||||
landmarks.landmark(4), image_size);
|
||||
return (dist_hori + dist_vert) / 2.0f;
|
||||
}
|
||||
|
||||
float CalculateDepth(const NormalizedLandmark& center, float focal_length,
|
||||
float iris_size, float img_w, float img_h) {
|
||||
std::pair<float, float> origin{img_w / 2.f, img_h / 2.f};
|
||||
const auto y = GetDepth(origin.first, origin.second, center.x() * img_w,
|
||||
center.y() * img_h);
|
||||
const auto x = std::sqrt(focal_length * focal_length + y * y);
|
||||
const auto depth = kIrisSizeInMM * x / iris_size;
|
||||
return depth;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Converts iris landmarks to render data and estimates depth from the camera if
|
||||
// focal length and image size. The depth will be rendered as part of the render
|
||||
// data on the frame.
|
||||
//
|
||||
// Usage example:
|
||||
// node {
|
||||
// calculator: "IrisToRenderDataCalculator"
|
||||
// input_stream: "IRIS:iris_landmarks"
|
||||
// input_stream: "IMAGE_SIZE:image_size"
|
||||
// # Note: Only one of FOCAL_LENGTH or IMAGE_FILE_PROPERTIES is necessary
|
||||
// # to get focal length in pixels. Sending focal length in pixels to
|
||||
// # this calculator is optional.
|
||||
// input_side_packet: "FOCAL_LENGTH:focal_length_pixel"
|
||||
// # OR
|
||||
// input_side_packet: "IMAGE_FILE_PROPERTIES:image_file_properties"
|
||||
// output_stream: "RENDER_DATA:iris_render_data"
|
||||
// output_stream: "LEFT_IRIS_DEPTH_MM:left_iris_depth_mm"
|
||||
// output_stream: "RIGHT_IRIS_DEPTH_MM:right_iris_depth_mm"
|
||||
// node_options: {
|
||||
// [type.googleapis.com/mediapipe.IrisToRenderDataCalculatorOptions] {
|
||||
// color { r: 255 g: 255 b: 255 }
|
||||
// thickness: 2.0
|
||||
// font_height_px: 50
|
||||
// horizontal_offset_px: 200
|
||||
// vertical_offset_px: 200
|
||||
// location: TOP_LEFT
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
class IrisToRenderDataCalculator : public CalculatorBase {
|
||||
public:
|
||||
static ::mediapipe::Status GetContract(CalculatorContract* cc) {
|
||||
cc->Inputs().Tag(kIrisTag).Set<NormalizedLandmarkList>();
|
||||
cc->Outputs().Tag(kRenderDataTag).Set<RenderData>();
|
||||
cc->Inputs().Tag(kImageSizeTag).Set<std::pair<int, int>>();
|
||||
|
||||
if (cc->Inputs().HasTag(kLeftIrisDepthTag)) {
|
||||
cc->Inputs().Tag(kLeftIrisDepthTag).Set<float>();
|
||||
}
|
||||
if (cc->Inputs().HasTag(kRightIrisDepthTag)) {
|
||||
cc->Inputs().Tag(kRightIrisDepthTag).Set<float>();
|
||||
}
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status Open(CalculatorContext* cc) override;
|
||||
|
||||
::mediapipe::Status Process(CalculatorContext* cc) override;
|
||||
|
||||
private:
|
||||
void RenderIris(const NormalizedLandmarkList& iris_landmarks,
|
||||
const IrisToRenderDataCalculatorOptions& options,
|
||||
const std::pair<int, int>& image_size, float iris_size,
|
||||
RenderData* render_data);
|
||||
void GetLeftIris(const NormalizedLandmarkList& lds,
|
||||
NormalizedLandmarkList* iris);
|
||||
void GetRightIris(const NormalizedLandmarkList& lds,
|
||||
NormalizedLandmarkList* iris);
|
||||
|
||||
void AddTextRenderData(const IrisToRenderDataCalculatorOptions& options,
|
||||
const std::pair<int, int>& image_size,
|
||||
const std::vector<std::string>& lines,
|
||||
RenderData* render_data);
|
||||
|
||||
static RenderAnnotation* AddOvalRenderData(
|
||||
const IrisToRenderDataCalculatorOptions& options,
|
||||
RenderData* render_data);
|
||||
static RenderAnnotation* AddPointRenderData(
|
||||
const IrisToRenderDataCalculatorOptions& options,
|
||||
RenderData* render_data);
|
||||
};
|
||||
REGISTER_CALCULATOR(IrisToRenderDataCalculator);
|
||||
|
||||
::mediapipe::Status IrisToRenderDataCalculator::Open(CalculatorContext* cc) {
|
||||
cc->SetOffset(TimestampDiff(0));
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
::mediapipe::Status IrisToRenderDataCalculator::Process(CalculatorContext* cc) {
|
||||
// Only process if there's input landmarks.
|
||||
if (cc->Inputs().Tag(kIrisTag).IsEmpty()) {
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
const auto& options =
|
||||
cc->Options<::mediapipe::IrisToRenderDataCalculatorOptions>();
|
||||
|
||||
const auto& iris_landmarks =
|
||||
cc->Inputs().Tag(kIrisTag).Get<NormalizedLandmarkList>();
|
||||
RET_CHECK_EQ(iris_landmarks.landmark_size(), kNumIrisLandmarksPerEye * 2)
|
||||
<< "Wrong number of iris landmarks";
|
||||
|
||||
std::pair<int, int> image_size;
|
||||
RET_CHECK(!cc->Inputs().Tag(kImageSizeTag).IsEmpty());
|
||||
image_size = cc->Inputs().Tag(kImageSizeTag).Get<std::pair<int, int>>();
|
||||
|
||||
auto render_data = absl::make_unique<RenderData>();
|
||||
auto left_iris = absl::make_unique<NormalizedLandmarkList>();
|
||||
auto right_iris = absl::make_unique<NormalizedLandmarkList>();
|
||||
GetLeftIris(iris_landmarks, left_iris.get());
|
||||
GetRightIris(iris_landmarks, right_iris.get());
|
||||
|
||||
const auto left_iris_size = CalculateIrisDiameter(*left_iris, image_size);
|
||||
const auto right_iris_size = CalculateIrisDiameter(*right_iris, image_size);
|
||||
RenderIris(*left_iris, options, image_size, left_iris_size,
|
||||
render_data.get());
|
||||
RenderIris(*right_iris, options, image_size, right_iris_size,
|
||||
render_data.get());
|
||||
|
||||
std::vector<std::string> lines;
|
||||
std::string line;
|
||||
if (cc->Inputs().HasTag(kLeftIrisDepthTag) &&
|
||||
!cc->Inputs().Tag(kLeftIrisDepthTag).IsEmpty()) {
|
||||
const float left_iris_depth =
|
||||
cc->Inputs().Tag(kLeftIrisDepthTag).Get<float>();
|
||||
if (!std::isinf(left_iris_depth)) {
|
||||
line = "Left : ";
|
||||
absl::StrAppend(&line, ":", std::round(left_iris_depth / 10), " cm");
|
||||
lines.emplace_back(line);
|
||||
}
|
||||
}
|
||||
if (cc->Inputs().HasTag(kRightIrisDepthTag) &&
|
||||
!cc->Inputs().Tag(kRightIrisDepthTag).IsEmpty()) {
|
||||
const float right_iris_depth =
|
||||
cc->Inputs().Tag(kRightIrisDepthTag).Get<float>();
|
||||
if (!std::isinf(right_iris_depth)) {
|
||||
line = "Right : ";
|
||||
absl::StrAppend(&line, ":", std::round(right_iris_depth / 10), " cm");
|
||||
lines.emplace_back(line);
|
||||
}
|
||||
}
|
||||
AddTextRenderData(options, image_size, lines, render_data.get());
|
||||
|
||||
cc->Outputs()
|
||||
.Tag(kRenderDataTag)
|
||||
.Add(render_data.release(), cc->InputTimestamp());
|
||||
return ::mediapipe::OkStatus();
|
||||
}
|
||||
|
||||
void IrisToRenderDataCalculator::AddTextRenderData(
|
||||
const IrisToRenderDataCalculatorOptions& options,
|
||||
const std::pair<int, int>& image_size,
|
||||
const std::vector<std::string>& lines, RenderData* render_data) {
|
||||
int label_baseline_px = options.vertical_offset_px();
|
||||
float label_height_px =
|
||||
std::ceil(options.font_height_px() * kFontHeightScale);
|
||||
if (options.location() == IrisToRenderDataCalculatorOptions::TOP_LEFT) {
|
||||
label_baseline_px += label_height_px;
|
||||
} else if (options.location() ==
|
||||
IrisToRenderDataCalculatorOptions::BOTTOM_LEFT) {
|
||||
label_baseline_px += image_size.second - label_height_px * lines.size();
|
||||
}
|
||||
const auto label_left_px = options.horizontal_offset_px();
|
||||
for (int i = 0; i < lines.size(); ++i) {
|
||||
auto* label_annotation = render_data->add_render_annotations();
|
||||
label_annotation->set_thickness(5);
|
||||
|
||||
label_annotation->mutable_color()->set_r(255);
|
||||
label_annotation->mutable_color()->set_g(0);
|
||||
label_annotation->mutable_color()->set_b(0);
|
||||
//
|
||||
auto* text = label_annotation->mutable_text();
|
||||
text->set_display_text(lines[i]);
|
||||
text->set_font_height(options.font_height_px());
|
||||
text->set_left(label_left_px);
|
||||
text->set_baseline(label_baseline_px + i * label_height_px);
|
||||
text->set_font_face(options.font_face());
|
||||
}
|
||||
}
|
||||
|
||||
void IrisToRenderDataCalculator::RenderIris(
|
||||
const NormalizedLandmarkList& iris_landmarks,
|
||||
const IrisToRenderDataCalculatorOptions& options,
|
||||
const std::pair<int, int>& image_size, float iris_size,
|
||||
RenderData* render_data) {
|
||||
auto* oval_data_render = AddOvalRenderData(options, render_data);
|
||||
auto* oval_data = oval_data_render->mutable_oval();
|
||||
const float iris_radius = iris_size / 2.f;
|
||||
const auto& iris_center = iris_landmarks.landmark(0);
|
||||
|
||||
oval_data->mutable_rectangle()->set_top(iris_center.y() -
|
||||
iris_radius / image_size.second);
|
||||
oval_data->mutable_rectangle()->set_bottom(iris_center.y() +
|
||||
iris_radius / image_size.second);
|
||||
oval_data->mutable_rectangle()->set_left(iris_center.x() -
|
||||
iris_radius / image_size.first);
|
||||
oval_data->mutable_rectangle()->set_right(iris_center.x() +
|
||||
iris_radius / image_size.first);
|
||||
oval_data->mutable_rectangle()->set_normalized(true);
|
||||
|
||||
for (int i = 0; i < iris_landmarks.landmark_size(); ++i) {
|
||||
const NormalizedLandmark& landmark = iris_landmarks.landmark(i);
|
||||
auto* landmark_data_render = AddPointRenderData(options, render_data);
|
||||
auto* landmark_data = landmark_data_render->mutable_point();
|
||||
landmark_data->set_normalized(true);
|
||||
landmark_data->set_x(landmark.x());
|
||||
landmark_data->set_y(landmark.y());
|
||||
}
|
||||
}
|
||||
|
||||
void IrisToRenderDataCalculator::GetLeftIris(const NormalizedLandmarkList& lds,
|
||||
NormalizedLandmarkList* iris) {
|
||||
// Center, top, bottom, left, right
|
||||
*iris->add_landmark() = lds.landmark(0);
|
||||
*iris->add_landmark() = lds.landmark(2);
|
||||
*iris->add_landmark() = lds.landmark(4);
|
||||
*iris->add_landmark() = lds.landmark(3);
|
||||
*iris->add_landmark() = lds.landmark(1);
|
||||
}
|
||||
|
||||
void IrisToRenderDataCalculator::GetRightIris(const NormalizedLandmarkList& lds,
|
||||
NormalizedLandmarkList* iris) {
|
||||
// Center, top, bottom, left, right
|
||||
*iris->add_landmark() = lds.landmark(5);
|
||||
*iris->add_landmark() = lds.landmark(7);
|
||||
*iris->add_landmark() = lds.landmark(9);
|
||||
*iris->add_landmark() = lds.landmark(6);
|
||||
*iris->add_landmark() = lds.landmark(8);
|
||||
}
|
||||
|
||||
RenderAnnotation* IrisToRenderDataCalculator::AddOvalRenderData(
|
||||
const IrisToRenderDataCalculatorOptions& options, RenderData* render_data) {
|
||||
auto* oval_data_annotation = render_data->add_render_annotations();
|
||||
oval_data_annotation->set_scene_tag(kOvalLabel);
|
||||
|
||||
SetColor(oval_data_annotation, options.oval_color());
|
||||
oval_data_annotation->set_thickness(options.oval_thickness());
|
||||
return oval_data_annotation;
|
||||
}
|
||||
|
||||
RenderAnnotation* IrisToRenderDataCalculator::AddPointRenderData(
|
||||
const IrisToRenderDataCalculatorOptions& options, RenderData* render_data) {
|
||||
auto* landmark_data_annotation = render_data->add_render_annotations();
|
||||
SetColor(landmark_data_annotation, options.landmark_color());
|
||||
landmark_data_annotation->set_thickness(options.landmark_thickness());
|
||||
|
||||
return landmark_data_annotation;
|
||||
}
|
||||
|
||||
} // namespace mediapipe
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright 2019 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.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package mediapipe;
|
||||
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
import "mediapipe/util/color.proto";
|
||||
|
||||
message IrisToRenderDataCalculatorOptions {
|
||||
extend CalculatorOptions {
|
||||
optional IrisToRenderDataCalculatorOptions ext = 289530040;
|
||||
}
|
||||
|
||||
// Color of the oval.
|
||||
optional Color oval_color = 1;
|
||||
// Color of the landmarks.
|
||||
optional Color landmark_color = 9;
|
||||
|
||||
// Thickness of the drawing of landmarks and iris oval.
|
||||
optional double oval_thickness = 2 [default = 1.0];
|
||||
optional double landmark_thickness = 10 [default = 1.0];
|
||||
|
||||
// The font height in absolute pixels.
|
||||
optional int32 font_height_px = 3 [default = 50];
|
||||
|
||||
// The offset of the starting text in horizontal direction in absolute pixels.
|
||||
optional int32 horizontal_offset_px = 7 [default = 0];
|
||||
// The offset of the starting text in vertical direction in absolute pixels.
|
||||
optional int32 vertical_offset_px = 8 [default = 0];
|
||||
|
||||
// Specifies the font for the text. Font must be one of the following from
|
||||
// OpenCV:
|
||||
// cv::FONT_HERSHEY_SIMPLEX (0)
|
||||
// cv::FONT_HERSHEY_PLAIN (1)
|
||||
// cv::FONT_HERSHEY_DUPLEX (2)
|
||||
// cv::FONT_HERSHEY_COMPLEX (3)
|
||||
// cv::FONT_HERSHEY_TRIPLEX (4)
|
||||
// cv::FONT_HERSHEY_COMPLEX_SMALL (5)
|
||||
// cv::FONT_HERSHEY_SCRIPT_SIMPLEX (6)
|
||||
// cv::FONT_HERSHEY_SCRIPT_COMPLEX (7)
|
||||
optional int32 font_face = 5 [default = 0];
|
||||
|
||||
// Label location.
|
||||
enum Location {
|
||||
TOP_LEFT = 0;
|
||||
BOTTOM_LEFT = 1;
|
||||
}
|
||||
optional Location location = 6 [default = TOP_LEFT];
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
# MediaPipe graph that performs iris distance computation on desktop with
|
||||
# TensorFlow Lite on CPU.
|
||||
# Used in the example in
|
||||
# mediapipie/examples/desktop/iris_tracking:iris_depth_from_image_desktop.
|
||||
|
||||
# Raw image bytes. (std::string)
|
||||
input_stream: "input_image_bytes"
|
||||
|
||||
# Image with all the detections rendered. (ImageFrame)
|
||||
output_stream: "output_image"
|
||||
# Estimated depth in mm from the camera to the left iris of the face (if any) in
|
||||
# the image. (float)
|
||||
output_stream: "left_iris_depth_mm"
|
||||
# Estimated depth in mm from the camera to the right iris of the face (if any)
|
||||
# in the image. (float)
|
||||
output_stream: "right_iris_depth_mm"
|
||||
|
||||
# Computes the focal length in pixels based on EXIF information stored in the
|
||||
# image file. The output is an ImageFileProperties object containing relevant
|
||||
# image EXIF information along with focal length in pixels.
|
||||
node {
|
||||
calculator: "ImageFilePropertiesCalculator"
|
||||
input_stream: "input_image_bytes"
|
||||
output_side_packet: "image_file_properties"
|
||||
}
|
||||
|
||||
# Converts a raw string with encoded image bytes into an ImageFrame object
|
||||
# via OpenCV so that it can be processed by downstream calculators.
|
||||
node {
|
||||
calculator: "OpenCvEncodedImageToImageFrameCalculator"
|
||||
input_stream: "input_image_bytes"
|
||||
output_stream: "input_image"
|
||||
}
|
||||
|
||||
# Defines how many faces to detect. Iris tracking currently only handles one
|
||||
# face (left and right eye), and therefore this should always be set to 1.
|
||||
node {
|
||||
calculator: "ConstantSidePacketCalculator"
|
||||
output_side_packet: "PACKET:0:num_faces"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.ConstantSidePacketCalculatorOptions]: {
|
||||
packet { int_value: 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Detects faces and corresponding landmarks.
|
||||
node {
|
||||
calculator: "FaceLandmarkFrontCpu"
|
||||
input_stream: "IMAGE:input_image"
|
||||
input_side_packet: "NUM_FACES:num_faces"
|
||||
output_stream: "LANDMARKS:multi_face_landmarks"
|
||||
output_stream: "ROIS_FROM_LANDMARKS:face_rects_from_landmarks"
|
||||
output_stream: "DETECTIONS:face_detections"
|
||||
output_stream: "ROIS_FROM_DETECTIONS:face_rects_from_detections"
|
||||
}
|
||||
|
||||
# Gets the very first and only face from "multi_face_landmarks" vector.
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListVectorCalculator"
|
||||
input_stream: "multi_face_landmarks"
|
||||
output_stream: "face_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 0 end: 1 }
|
||||
element_only: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Gets the very first and only face rect from "face_rects_from_landmarks"
|
||||
# vector.
|
||||
node {
|
||||
calculator: "SplitNormalizedRectVectorCalculator"
|
||||
input_stream: "face_rects_from_landmarks"
|
||||
output_stream: "face_rect"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 0 end: 1 }
|
||||
element_only: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Gets two landmarks which define left eye boundary.
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListCalculator"
|
||||
input_stream: "face_landmarks"
|
||||
output_stream: "left_eye_boundary_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 33 end: 34 }
|
||||
ranges: { begin: 133 end: 134 }
|
||||
combine_outputs: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Gets two landmarks which define right eye boundary.
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListCalculator"
|
||||
input_stream: "face_landmarks"
|
||||
output_stream: "right_eye_boundary_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 362 end: 363 }
|
||||
ranges: { begin: 263 end: 264 }
|
||||
combine_outputs: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Detects iris landmarks, eye contour landmarks, and corresponding rect (ROI).
|
||||
node {
|
||||
calculator: "IrisLandmarkLeftAndRightCpu"
|
||||
input_stream: "IMAGE:input_image"
|
||||
input_stream: "LEFT_EYE_BOUNDARY_LANDMARKS:left_eye_boundary_landmarks"
|
||||
input_stream: "RIGHT_EYE_BOUNDARY_LANDMARKS:right_eye_boundary_landmarks"
|
||||
output_stream: "LEFT_EYE_CONTOUR_LANDMARKS:left_eye_contour_landmarks"
|
||||
output_stream: "LEFT_EYE_IRIS_LANDMARKS:left_iris_landmarks"
|
||||
output_stream: "LEFT_EYE_ROI:left_eye_rect_from_landmarks"
|
||||
output_stream: "RIGHT_EYE_CONTOUR_LANDMARKS:right_eye_contour_landmarks"
|
||||
output_stream: "RIGHT_EYE_IRIS_LANDMARKS:right_iris_landmarks"
|
||||
output_stream: "RIGHT_EYE_ROI:right_eye_rect_from_landmarks"
|
||||
}
|
||||
|
||||
# Renders annotations and overlays them on top of the input images.
|
||||
node {
|
||||
calculator: "IrisAndDepthRendererCpu"
|
||||
input_stream: "IMAGE:input_image"
|
||||
input_stream: "FACE_LANDMARKS:face_landmarks"
|
||||
input_stream: "EYE_LANDMARKS_LEFT:left_eye_contour_landmarks"
|
||||
input_stream: "EYE_LANDMARKS_RIGHT:right_eye_contour_landmarks"
|
||||
input_stream: "IRIS_LANDMARKS_LEFT:left_iris_landmarks"
|
||||
input_stream: "IRIS_LANDMARKS_RIGHT:right_iris_landmarks"
|
||||
input_stream: "NORM_RECT:face_rect"
|
||||
input_stream: "LEFT_EYE_RECT:left_eye_rect_from_landmarks"
|
||||
input_stream: "RIGHT_EYE_RECT:right_eye_rect_from_landmarks"
|
||||
input_stream: "DETECTIONS:face_detections"
|
||||
input_side_packet: "IMAGE_FILE_PROPERTIES:image_file_properties"
|
||||
output_stream: "IMAGE:output_image"
|
||||
output_stream: "LEFT_IRIS_DEPTH_MM:left_iris_depth_mm"
|
||||
output_stream: "RIGHT_IRIS_DEPTH_MM:right_iris_depth_mm"
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
# MediaPipe graph that performs iris tracking on desktop with TensorFlow Lite
|
||||
# on CPU.
|
||||
# Used in the example in
|
||||
# mediapipie/examples/desktop/iris_tracking:iris_tracking_cpu.
|
||||
|
||||
# CPU image. (ImageFrame)
|
||||
input_stream: "input_video"
|
||||
|
||||
# CPU image. (ImageFrame)
|
||||
output_stream: "output_video"
|
||||
|
||||
# Defines how many faces to detect. Iris tracking currently only handles one
|
||||
# face (left and right eye), and therefore this should always be set to 1.
|
||||
node {
|
||||
calculator: "ConstantSidePacketCalculator"
|
||||
output_side_packet: "PACKET:0:num_faces"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.ConstantSidePacketCalculatorOptions]: {
|
||||
packet { int_value: 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Detects faces and corresponding landmarks.
|
||||
node {
|
||||
calculator: "FaceLandmarkFrontCpu"
|
||||
input_stream: "IMAGE:input_video"
|
||||
input_side_packet: "NUM_FACES:num_faces"
|
||||
output_stream: "LANDMARKS:multi_face_landmarks"
|
||||
output_stream: "ROIS_FROM_LANDMARKS:face_rects_from_landmarks"
|
||||
output_stream: "DETECTIONS:face_detections"
|
||||
output_stream: "ROIS_FROM_DETECTIONS:face_rects_from_detections"
|
||||
}
|
||||
|
||||
# Gets the very first and only face from "multi_face_landmarks" vector.
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListVectorCalculator"
|
||||
input_stream: "multi_face_landmarks"
|
||||
output_stream: "face_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 0 end: 1 }
|
||||
element_only: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Gets the very first and only face rect from "face_rects_from_landmarks"
|
||||
# vector.
|
||||
node {
|
||||
calculator: "SplitNormalizedRectVectorCalculator"
|
||||
input_stream: "face_rects_from_landmarks"
|
||||
output_stream: "face_rect"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 0 end: 1 }
|
||||
element_only: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Gets two landmarks which define left eye boundary.
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListCalculator"
|
||||
input_stream: "face_landmarks"
|
||||
output_stream: "left_eye_boundary_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 33 end: 34 }
|
||||
ranges: { begin: 133 end: 134 }
|
||||
combine_outputs: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Gets two landmarks which define right eye boundary.
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListCalculator"
|
||||
input_stream: "face_landmarks"
|
||||
output_stream: "right_eye_boundary_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 362 end: 363 }
|
||||
ranges: { begin: 263 end: 264 }
|
||||
combine_outputs: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Detects iris landmarks, eye contour landmarks, and corresponding rect (ROI).
|
||||
node {
|
||||
calculator: "IrisLandmarkLeftAndRightCpu"
|
||||
input_stream: "IMAGE:input_video"
|
||||
input_stream: "LEFT_EYE_BOUNDARY_LANDMARKS:left_eye_boundary_landmarks"
|
||||
input_stream: "RIGHT_EYE_BOUNDARY_LANDMARKS:right_eye_boundary_landmarks"
|
||||
output_stream: "LEFT_EYE_CONTOUR_LANDMARKS:left_eye_contour_landmarks"
|
||||
output_stream: "LEFT_EYE_IRIS_LANDMARKS:left_iris_landmarks"
|
||||
output_stream: "LEFT_EYE_ROI:left_eye_rect_from_landmarks"
|
||||
output_stream: "RIGHT_EYE_CONTOUR_LANDMARKS:right_eye_contour_landmarks"
|
||||
output_stream: "RIGHT_EYE_IRIS_LANDMARKS:right_iris_landmarks"
|
||||
output_stream: "RIGHT_EYE_ROI:right_eye_rect_from_landmarks"
|
||||
}
|
||||
|
||||
# Renders annotations and overlays them on top of the input images.
|
||||
node {
|
||||
calculator: "IrisRendererCpu"
|
||||
input_stream: "IMAGE:input_video"
|
||||
input_stream: "FACE_LANDMARKS:face_landmarks"
|
||||
input_stream: "EYE_LANDMARKS_LEFT:left_eye_contour_landmarks"
|
||||
input_stream: "EYE_LANDMARKS_RIGHT:right_eye_contour_landmarks"
|
||||
input_stream: "IRIS_LANDMARKS_LEFT:left_iris_landmarks"
|
||||
input_stream: "IRIS_LANDMARKS_RIGHT:right_iris_landmarks"
|
||||
input_stream: "NORM_RECT:face_rect"
|
||||
input_stream: "LEFT_EYE_RECT:left_eye_rect_from_landmarks"
|
||||
input_stream: "RIGHT_EYE_RECT:right_eye_rect_from_landmarks"
|
||||
input_stream: "DETECTIONS:face_detections"
|
||||
output_stream: "IMAGE:output_video"
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
# MediaPipe graph that performs iris tracking on desktop with TensorFlow Lite
|
||||
# on CPU.
|
||||
|
||||
# max_queue_size limits the number of packets enqueued on any input stream
|
||||
# by throttling inputs to the graph. This makes the graph only process one
|
||||
# frame per time.
|
||||
max_queue_size: 1
|
||||
|
||||
# Decodes an input video file into images and a video header.
|
||||
node {
|
||||
calculator: "OpenCvVideoDecoderCalculator"
|
||||
input_side_packet: "INPUT_FILE_PATH:input_video_path"
|
||||
output_stream: "VIDEO:input_video"
|
||||
output_stream: "VIDEO_PRESTREAM:input_video_header"
|
||||
}
|
||||
|
||||
# Defines how many faces to detect. Iris tracking currently only handles one
|
||||
# face (left and right eye), and therefore this should always be set to 1.
|
||||
node {
|
||||
calculator: "ConstantSidePacketCalculator"
|
||||
output_side_packet: "PACKET:0:num_faces"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.ConstantSidePacketCalculatorOptions]: {
|
||||
packet { int_value: 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Detects faces and corresponding landmarks.
|
||||
node {
|
||||
calculator: "FaceLandmarkFrontCpu"
|
||||
input_stream: "IMAGE:input_video"
|
||||
input_side_packet: "NUM_FACES:num_faces"
|
||||
output_stream: "LANDMARKS:multi_face_landmarks"
|
||||
output_stream: "ROIS_FROM_LANDMARKS:face_rects_from_landmarks"
|
||||
output_stream: "DETECTIONS:face_detections"
|
||||
output_stream: "ROIS_FROM_DETECTIONS:face_rects_from_detections"
|
||||
}
|
||||
|
||||
# Gets the very first and only face from "multi_face_landmarks" vector.
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListVectorCalculator"
|
||||
input_stream: "multi_face_landmarks"
|
||||
output_stream: "face_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 0 end: 1 }
|
||||
element_only: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Gets the very first and only face rect from "face_rects_from_landmarks"
|
||||
# vector.
|
||||
node {
|
||||
calculator: "SplitNormalizedRectVectorCalculator"
|
||||
input_stream: "face_rects_from_landmarks"
|
||||
output_stream: "face_rect"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 0 end: 1 }
|
||||
element_only: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Gets two landmarks which define left eye boundary.
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListCalculator"
|
||||
input_stream: "face_landmarks"
|
||||
output_stream: "left_eye_boundary_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 33 end: 34 }
|
||||
ranges: { begin: 133 end: 134 }
|
||||
combine_outputs: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Gets two landmarks which define right eye boundary.
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListCalculator"
|
||||
input_stream: "face_landmarks"
|
||||
output_stream: "right_eye_boundary_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 362 end: 363 }
|
||||
ranges: { begin: 263 end: 264 }
|
||||
combine_outputs: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Detects iris landmarks, eye contour landmarks, and corresponding rect (ROI).
|
||||
node {
|
||||
calculator: "IrisLandmarkLeftAndRightCpu"
|
||||
input_stream: "IMAGE:input_video"
|
||||
input_stream: "LEFT_EYE_BOUNDARY_LANDMARKS:left_eye_boundary_landmarks"
|
||||
input_stream: "RIGHT_EYE_BOUNDARY_LANDMARKS:right_eye_boundary_landmarks"
|
||||
output_stream: "LEFT_EYE_CONTOUR_LANDMARKS:left_eye_contour_landmarks"
|
||||
output_stream: "LEFT_EYE_IRIS_LANDMARKS:left_iris_landmarks"
|
||||
output_stream: "LEFT_EYE_ROI:left_eye_rect_from_landmarks"
|
||||
output_stream: "RIGHT_EYE_CONTOUR_LANDMARKS:right_eye_contour_landmarks"
|
||||
output_stream: "RIGHT_EYE_IRIS_LANDMARKS:right_iris_landmarks"
|
||||
output_stream: "RIGHT_EYE_ROI:right_eye_rect_from_landmarks"
|
||||
}
|
||||
|
||||
# Renders annotations and overlays them on top of the input images.
|
||||
node {
|
||||
calculator: "IrisRendererCpu"
|
||||
input_stream: "IMAGE:input_video"
|
||||
input_stream: "FACE_LANDMARKS:face_landmarks"
|
||||
input_stream: "EYE_LANDMARKS_LEFT:left_eye_contour_landmarks"
|
||||
input_stream: "EYE_LANDMARKS_RIGHT:right_eye_contour_landmarks"
|
||||
input_stream: "IRIS_LANDMARKS_LEFT:left_iris_landmarks"
|
||||
input_stream: "IRIS_LANDMARKS_RIGHT:right_iris_landmarks"
|
||||
input_stream: "NORM_RECT:face_rect"
|
||||
input_stream: "LEFT_EYE_RECT:left_eye_rect_from_landmarks"
|
||||
input_stream: "RIGHT_EYE_RECT:right_eye_rect_from_landmarks"
|
||||
input_stream: "DETECTIONS:face_detections"
|
||||
output_stream: "IMAGE:output_video"
|
||||
}
|
||||
|
||||
# Encodes the annotated images into a video file, adopting properties specified
|
||||
# in the input video header, e.g., video framerate.
|
||||
node {
|
||||
calculator: "OpenCvVideoEncoderCalculator"
|
||||
input_stream: "VIDEO:output_video"
|
||||
input_stream: "VIDEO_PRESTREAM:input_video_header"
|
||||
input_side_packet: "OUTPUT_FILE_PATH:output_video_path"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.OpenCvVideoEncoderCalculatorOptions]: {
|
||||
codec: "avc1"
|
||||
video_format: "mp4"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
# MediaPipe graph that performs iris tracking with TensorFlow Lite on GPU.
|
||||
# Used in the examples in
|
||||
# mediapipie/examples/android/src/java/com/mediapipe/apps/iristrackinggpu and
|
||||
|
||||
# GPU buffer. (GpuBuffer)
|
||||
input_stream: "input_video"
|
||||
|
||||
# GPU buffer. (GpuBuffer)
|
||||
output_stream: "output_video"
|
||||
|
||||
# Throttles the images flowing downstream for flow control. It passes through
|
||||
# the very first incoming image unaltered, and waits for downstream nodes
|
||||
# (calculators and subgraphs) in the graph to finish their tasks before it
|
||||
# passes through another image. All images that come in while waiting are
|
||||
# dropped, limiting the number of in-flight images in most part of the graph to
|
||||
# 1. This prevents the downstream nodes from queuing up incoming images and data
|
||||
# excessively, which leads to increased latency and memory usage, unwanted in
|
||||
# real-time mobile applications. It also eliminates unnecessarily computation,
|
||||
# e.g., the output produced by a node may get dropped downstream if the
|
||||
# subsequent nodes are still busy processing previous inputs.
|
||||
node {
|
||||
calculator: "FlowLimiterCalculator"
|
||||
input_stream: "input_video"
|
||||
input_stream: "FINISHED:output_video"
|
||||
input_stream_info: {
|
||||
tag_index: "FINISHED"
|
||||
back_edge: true
|
||||
}
|
||||
output_stream: "throttled_input_video"
|
||||
}
|
||||
|
||||
# Defines how many faces to detect. Iris tracking currently only handles one
|
||||
# face (left and right eye), and therefore this should always be set to 1.
|
||||
node {
|
||||
calculator: "ConstantSidePacketCalculator"
|
||||
output_side_packet: "PACKET:num_faces"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.ConstantSidePacketCalculatorOptions]: {
|
||||
packet { int_value: 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Detects faces and corresponding landmarks.
|
||||
node {
|
||||
calculator: "FaceLandmarkFrontGpu"
|
||||
input_stream: "IMAGE:throttled_input_video"
|
||||
input_side_packet: "NUM_FACES:num_faces"
|
||||
output_stream: "LANDMARKS:multi_face_landmarks"
|
||||
output_stream: "ROIS_FROM_LANDMARKS:face_rects_from_landmarks"
|
||||
output_stream: "DETECTIONS:face_detections"
|
||||
output_stream: "ROIS_FROM_DETECTIONS:face_rects_from_detections"
|
||||
}
|
||||
|
||||
# Gets the very first and only face from "multi_face_landmarks" vector.
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListVectorCalculator"
|
||||
input_stream: "multi_face_landmarks"
|
||||
output_stream: "face_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 0 end: 1 }
|
||||
element_only: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Gets the very first and only face rect from "face_rects_from_landmarks"
|
||||
# vector.
|
||||
node {
|
||||
calculator: "SplitNormalizedRectVectorCalculator"
|
||||
input_stream: "face_rects_from_landmarks"
|
||||
output_stream: "face_rect"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 0 end: 1 }
|
||||
element_only: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Gets two landmarks which define left eye boundary.
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListCalculator"
|
||||
input_stream: "face_landmarks"
|
||||
output_stream: "left_eye_boundary_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 33 end: 34 }
|
||||
ranges: { begin: 133 end: 134 }
|
||||
combine_outputs: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Gets two landmarks which define right eye boundary.
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListCalculator"
|
||||
input_stream: "face_landmarks"
|
||||
output_stream: "right_eye_boundary_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 362 end: 363 }
|
||||
ranges: { begin: 263 end: 264 }
|
||||
combine_outputs: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Detects iris landmarks, eye contour landmarks, and corresponding rect (ROI).
|
||||
node {
|
||||
calculator: "IrisLandmarkLeftAndRightGpu"
|
||||
input_stream: "IMAGE:throttled_input_video"
|
||||
input_stream: "LEFT_EYE_BOUNDARY_LANDMARKS:left_eye_boundary_landmarks"
|
||||
input_stream: "RIGHT_EYE_BOUNDARY_LANDMARKS:right_eye_boundary_landmarks"
|
||||
output_stream: "LEFT_EYE_CONTOUR_LANDMARKS:left_eye_contour_landmarks"
|
||||
output_stream: "LEFT_EYE_IRIS_LANDMARKS:left_iris_landmarks"
|
||||
output_stream: "LEFT_EYE_ROI:left_eye_rect_from_landmarks"
|
||||
output_stream: "RIGHT_EYE_CONTOUR_LANDMARKS:right_eye_contour_landmarks"
|
||||
output_stream: "RIGHT_EYE_IRIS_LANDMARKS:right_iris_landmarks"
|
||||
output_stream: "RIGHT_EYE_ROI:right_eye_rect_from_landmarks"
|
||||
}
|
||||
|
||||
# Renders annotations and overlays them on top of the input images.
|
||||
node {
|
||||
calculator: "IrisAndDepthRendererGpu"
|
||||
input_stream: "IMAGE:throttled_input_video"
|
||||
input_stream: "FACE_LANDMARKS:face_landmarks"
|
||||
input_stream: "EYE_LANDMARKS_LEFT:left_eye_contour_landmarks"
|
||||
input_stream: "EYE_LANDMARKS_RIGHT:right_eye_contour_landmarks"
|
||||
input_stream: "IRIS_LANDMARKS_LEFT:left_iris_landmarks"
|
||||
input_stream: "IRIS_LANDMARKS_RIGHT:right_iris_landmarks"
|
||||
input_stream: "NORM_RECT:face_rect"
|
||||
input_stream: "LEFT_EYE_RECT:left_eye_rect_from_landmarks"
|
||||
input_stream: "RIGHT_EYE_RECT:right_eye_rect_from_landmarks"
|
||||
input_stream: "DETECTIONS:face_detections"
|
||||
input_side_packet: "FOCAL_LENGTH:focal_length_pixel"
|
||||
output_stream: "IRIS_LANDMARKS:iris_landmarks"
|
||||
output_stream: "IMAGE:output_video"
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
# Copyright 2019 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.
|
||||
|
||||
load(
|
||||
"//mediapipe/framework/tool:mediapipe_graph.bzl",
|
||||
"mediapipe_simple_subgraph",
|
||||
)
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
cc_library(
|
||||
name = "renderer_calculators",
|
||||
deps = [
|
||||
"//mediapipe/calculators/core:concatenate_normalized_landmark_list_calculator",
|
||||
"//mediapipe/calculators/core:concatenate_vector_calculator",
|
||||
"//mediapipe/calculators/core:split_normalized_landmark_list_calculator",
|
||||
"//mediapipe/calculators/util:annotation_overlay_calculator",
|
||||
"//mediapipe/calculators/util:detection_label_id_to_text_calculator",
|
||||
"//mediapipe/calculators/util:detections_to_render_data_calculator",
|
||||
"//mediapipe/calculators/util:landmarks_to_render_data_calculator",
|
||||
"//mediapipe/calculators/util:rect_to_render_data_calculator",
|
||||
],
|
||||
)
|
||||
|
||||
mediapipe_simple_subgraph(
|
||||
name = "iris_and_depth_renderer_gpu",
|
||||
graph = "iris_and_depth_renderer_gpu.pbtxt",
|
||||
register_as = "IrisAndDepthRendererGpu",
|
||||
deps = [
|
||||
":renderer_calculators",
|
||||
"//mediapipe/graphs/iris_tracking/calculators:iris_to_depth_calculator",
|
||||
"//mediapipe/graphs/iris_tracking/calculators:iris_to_render_data_calculator",
|
||||
],
|
||||
)
|
||||
|
||||
mediapipe_simple_subgraph(
|
||||
name = "iris_renderer_cpu",
|
||||
graph = "iris_renderer_cpu.pbtxt",
|
||||
register_as = "IrisRendererCpu",
|
||||
deps = [
|
||||
":renderer_calculators",
|
||||
"//mediapipe/graphs/iris_tracking/calculators:iris_to_render_data_calculator",
|
||||
],
|
||||
)
|
||||
|
||||
mediapipe_simple_subgraph(
|
||||
name = "iris_and_depth_renderer_cpu",
|
||||
graph = "iris_and_depth_renderer_cpu.pbtxt",
|
||||
register_as = "IrisAndDepthRendererCpu",
|
||||
deps = [
|
||||
":renderer_calculators",
|
||||
"//mediapipe/graphs/iris_tracking/calculators:iris_to_depth_calculator",
|
||||
"//mediapipe/graphs/iris_tracking/calculators:iris_to_render_data_calculator",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,259 @@
|
||||
# MediaPipe iris tracking rendering subgraph.
|
||||
|
||||
type: "IrisAndDepthRendererCpu"
|
||||
|
||||
input_stream: "IMAGE:input_image"
|
||||
input_stream: "DETECTIONS:detections"
|
||||
input_stream: "FACE_LANDMARKS:face_landmarks"
|
||||
input_stream: "EYE_LANDMARKS_LEFT:all_left_eye_contour_landmarks"
|
||||
input_stream: "EYE_LANDMARKS_RIGHT:all_right_eye_contour_landmarks"
|
||||
input_stream: "IRIS_LANDMARKS_LEFT:left_iris_landmarks"
|
||||
input_stream: "IRIS_LANDMARKS_RIGHT:right_iris_landmarks"
|
||||
input_stream: "NORM_RECT:rect"
|
||||
input_stream: "LEFT_EYE_RECT:left_eye_rect_from_landmarks"
|
||||
input_stream: "RIGHT_EYE_RECT:right_eye_rect_from_landmarks"
|
||||
input_side_packet: "IMAGE_FILE_PROPERTIES:image_file_properties"
|
||||
output_stream: "IMAGE:output_image"
|
||||
output_stream: "LEFT_IRIS_DEPTH_MM:left_iris_depth_mm"
|
||||
output_stream: "RIGHT_IRIS_DEPTH_MM:right_iris_depth_mm"
|
||||
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListCalculator"
|
||||
input_stream: "all_left_eye_contour_landmarks"
|
||||
output_stream: "left_eye_contour_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 0 end: 15 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListCalculator"
|
||||
input_stream: "all_right_eye_contour_landmarks"
|
||||
output_stream: "right_eye_contour_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 0 end: 15 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Concatenate iris landmarks from both eyes.
|
||||
node {
|
||||
calculator: "ConcatenateNormalizedLandmarkListCalculator"
|
||||
input_stream: "left_iris_landmarks"
|
||||
input_stream: "right_iris_landmarks"
|
||||
output_stream: "iris_landmarks"
|
||||
}
|
||||
|
||||
# Concatenate iris landmarks from both eyes and face landmarks.
|
||||
node {
|
||||
calculator: "ConcatenateNormalizedLandmarkListCalculator"
|
||||
input_stream: "left_iris_landmarks"
|
||||
input_stream: "right_iris_landmarks"
|
||||
input_stream: "face_landmarks"
|
||||
output_stream: "face_iris_landmarks"
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "ImagePropertiesCalculator"
|
||||
input_stream: "IMAGE:input_image"
|
||||
output_stream: "SIZE:image_size"
|
||||
}
|
||||
|
||||
# Maps detection label IDs to the corresponding label text ("Face").
|
||||
node {
|
||||
calculator: "DetectionLabelIdToTextCalculator"
|
||||
input_stream: "detections"
|
||||
output_stream: "labeled_detections"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.DetectionLabelIdToTextCalculatorOptions] {
|
||||
label: "Face"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Converts detections to drawing primitives for annotation overlay.
|
||||
node {
|
||||
calculator: "DetectionsToRenderDataCalculator"
|
||||
input_stream: "DETECTIONS:labeled_detections"
|
||||
output_stream: "RENDER_DATA:detection_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.DetectionsToRenderDataCalculatorOptions] {
|
||||
thickness: 4.0
|
||||
color { r: 0 g: 255 b: 0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Converts landmarks to drawing primitives for annotation overlay.
|
||||
node {
|
||||
calculator: "LandmarksToRenderDataCalculator"
|
||||
input_stream: "NORM_LANDMARKS:left_eye_contour_landmarks"
|
||||
output_stream: "RENDER_DATA:left_eye_contour_landmarks_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.LandmarksToRenderDataCalculatorOptions] {
|
||||
landmark_connections: 0
|
||||
landmark_connections: 1
|
||||
landmark_connections: 1
|
||||
landmark_connections: 2
|
||||
landmark_connections: 2
|
||||
landmark_connections: 3
|
||||
landmark_connections: 3
|
||||
landmark_connections: 4
|
||||
landmark_connections: 4
|
||||
landmark_connections: 5
|
||||
landmark_connections: 5
|
||||
landmark_connections: 6
|
||||
landmark_connections: 6
|
||||
landmark_connections: 7
|
||||
landmark_connections: 7
|
||||
landmark_connections: 8
|
||||
landmark_connections: 9
|
||||
landmark_connections: 10
|
||||
landmark_connections: 10
|
||||
landmark_connections: 11
|
||||
landmark_connections: 11
|
||||
landmark_connections: 12
|
||||
landmark_connections: 12
|
||||
landmark_connections: 13
|
||||
landmark_connections: 13
|
||||
landmark_connections: 14
|
||||
landmark_connections: 0
|
||||
landmark_connections: 9
|
||||
landmark_connections: 8
|
||||
landmark_connections: 14
|
||||
landmark_color { r: 255 g: 0 b: 0 }
|
||||
connection_color { r: 255 g: 0 b: 0 }
|
||||
visualize_landmark_depth: false
|
||||
thickness: 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Converts landmarks to drawing primitives for annotation overlay.
|
||||
node {
|
||||
calculator: "LandmarksToRenderDataCalculator"
|
||||
input_stream: "NORM_LANDMARKS:right_eye_contour_landmarks"
|
||||
output_stream: "RENDER_DATA:right_eye_contour_landmarks_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.LandmarksToRenderDataCalculatorOptions] {
|
||||
landmark_connections: 0
|
||||
landmark_connections: 1
|
||||
landmark_connections: 1
|
||||
landmark_connections: 2
|
||||
landmark_connections: 2
|
||||
landmark_connections: 3
|
||||
landmark_connections: 3
|
||||
landmark_connections: 4
|
||||
landmark_connections: 4
|
||||
landmark_connections: 5
|
||||
landmark_connections: 5
|
||||
landmark_connections: 6
|
||||
landmark_connections: 6
|
||||
landmark_connections: 7
|
||||
landmark_connections: 7
|
||||
landmark_connections: 8
|
||||
landmark_connections: 9
|
||||
landmark_connections: 10
|
||||
landmark_connections: 10
|
||||
landmark_connections: 11
|
||||
landmark_connections: 11
|
||||
landmark_connections: 12
|
||||
landmark_connections: 12
|
||||
landmark_connections: 13
|
||||
landmark_connections: 13
|
||||
landmark_connections: 14
|
||||
landmark_connections: 0
|
||||
landmark_connections: 9
|
||||
landmark_connections: 8
|
||||
landmark_connections: 14
|
||||
landmark_color { r: 255 g: 0 b: 0 }
|
||||
connection_color { r: 255 g: 0 b: 0 }
|
||||
visualize_landmark_depth: false
|
||||
thickness: 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Converts normalized rects to drawing primitives for annotation overlay.
|
||||
node {
|
||||
calculator: "RectToRenderDataCalculator"
|
||||
input_stream: "NORM_RECT:rect"
|
||||
output_stream: "RENDER_DATA:rect_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.RectToRenderDataCalculatorOptions] {
|
||||
filled: false
|
||||
color { r: 255 g: 0 b: 0 }
|
||||
thickness: 4.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "RectToRenderDataCalculator"
|
||||
input_stream: "NORM_RECT:right_eye_rect_from_landmarks"
|
||||
output_stream: "RENDER_DATA:right_eye_rect_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.RectToRenderDataCalculatorOptions] {
|
||||
filled: false
|
||||
color { r: 255 g: 0 b: 0 }
|
||||
thickness: 4.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "RectToRenderDataCalculator"
|
||||
input_stream: "NORM_RECT:left_eye_rect_from_landmarks"
|
||||
output_stream: "RENDER_DATA:left_eye_rect_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.RectToRenderDataCalculatorOptions] {
|
||||
filled: false
|
||||
color { r: 255 g: 0 b: 0 }
|
||||
thickness: 4.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "IrisToDepthCalculator"
|
||||
input_stream: "IRIS:iris_landmarks"
|
||||
input_stream: "IMAGE_SIZE:image_size"
|
||||
input_side_packet: "IMAGE_FILE_PROPERTIES:image_file_properties"
|
||||
output_stream: "LEFT_IRIS_DEPTH_MM:left_iris_depth_mm"
|
||||
output_stream: "RIGHT_IRIS_DEPTH_MM:right_iris_depth_mm"
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "IrisToRenderDataCalculator"
|
||||
input_stream: "IRIS:iris_landmarks"
|
||||
input_stream: "IMAGE_SIZE:image_size"
|
||||
input_stream: "LEFT_IRIS_DEPTH_MM:left_iris_depth_mm"
|
||||
input_stream: "RIGHT_IRIS_DEPTH_MM:right_iris_depth_mm"
|
||||
output_stream: "RENDER_DATA:iris_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.IrisToRenderDataCalculatorOptions] {
|
||||
oval_color { r: 0 g: 0 b: 255 }
|
||||
landmark_color { r: 0 g: 255 b: 0 }
|
||||
oval_thickness: 2.0
|
||||
landmark_thickness: 1.0
|
||||
font_height_px: 50
|
||||
horizontal_offset_px: 200
|
||||
vertical_offset_px: 200
|
||||
location: TOP_LEFT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Draws annotations and overlays them on top of the input images.
|
||||
node {
|
||||
calculator: "AnnotationOverlayCalculator"
|
||||
input_stream: "IMAGE:input_image"
|
||||
input_stream: "detection_render_data"
|
||||
input_stream: "right_eye_contour_landmarks_render_data"
|
||||
input_stream: "left_eye_contour_landmarks_render_data"
|
||||
input_stream: "iris_render_data"
|
||||
output_stream: "IMAGE:output_image"
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
# MediaPipe iris tracking rendering subgraph.
|
||||
|
||||
type: "IrisAndDepthRendererGpu"
|
||||
|
||||
input_stream: "IMAGE:input_image"
|
||||
input_stream: "DETECTIONS:detections"
|
||||
input_stream: "FACE_LANDMARKS:face_landmarks"
|
||||
input_stream: "EYE_LANDMARKS_LEFT:all_left_eye_contour_landmarks"
|
||||
input_stream: "EYE_LANDMARKS_RIGHT:all_right_eye_contour_landmarks"
|
||||
input_stream: "IRIS_LANDMARKS_LEFT:left_iris_landmarks"
|
||||
input_stream: "IRIS_LANDMARKS_RIGHT:right_iris_landmarks"
|
||||
input_stream: "NORM_RECT:rect"
|
||||
input_stream: "LEFT_EYE_RECT:left_eye_rect_from_landmarks"
|
||||
input_stream: "RIGHT_EYE_RECT:right_eye_rect_from_landmarks"
|
||||
input_side_packet: "FOCAL_LENGTH:focal_length_pixel"
|
||||
output_stream: "IRIS_LANDMARKS:iris_landmarks"
|
||||
output_stream: "IMAGE:output_image"
|
||||
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListCalculator"
|
||||
input_stream: "all_left_eye_contour_landmarks"
|
||||
output_stream: "left_eye_contour_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 0 end: 15 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListCalculator"
|
||||
input_stream: "all_right_eye_contour_landmarks"
|
||||
output_stream: "right_eye_contour_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 0 end: 15 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Concatenate iris landmarks from both eyes.
|
||||
node {
|
||||
calculator: "ConcatenateNormalizedLandmarkListCalculator"
|
||||
input_stream: "left_iris_landmarks"
|
||||
input_stream: "right_iris_landmarks"
|
||||
output_stream: "iris_landmarks"
|
||||
}
|
||||
|
||||
# Concatenate iris landmarks from both eyes and face landmarks.
|
||||
node {
|
||||
calculator: "ConcatenateNormalizedLandmarkListCalculator"
|
||||
input_stream: "left_iris_landmarks"
|
||||
input_stream: "right_iris_landmarks"
|
||||
input_stream: "face_landmarks"
|
||||
output_stream: "face_iris_landmarks"
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "ImagePropertiesCalculator"
|
||||
input_stream: "IMAGE_GPU:input_image"
|
||||
output_stream: "SIZE:image_size"
|
||||
}
|
||||
|
||||
# Maps detection label IDs to the corresponding label text ("Face").
|
||||
node {
|
||||
calculator: "DetectionLabelIdToTextCalculator"
|
||||
input_stream: "detections"
|
||||
output_stream: "labeled_detections"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.DetectionLabelIdToTextCalculatorOptions] {
|
||||
label: "Face"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Converts detections to drawing primitives for annotation overlay.
|
||||
node {
|
||||
calculator: "DetectionsToRenderDataCalculator"
|
||||
input_stream: "DETECTIONS:labeled_detections"
|
||||
output_stream: "RENDER_DATA:detection_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.DetectionsToRenderDataCalculatorOptions] {
|
||||
thickness: 4.0
|
||||
color { r: 0 g: 255 b: 0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Converts landmarks to drawing primitives for annotation overlay.
|
||||
node {
|
||||
calculator: "LandmarksToRenderDataCalculator"
|
||||
input_stream: "NORM_LANDMARKS:left_eye_contour_landmarks"
|
||||
output_stream: "RENDER_DATA:left_eye_contour_landmarks_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.LandmarksToRenderDataCalculatorOptions] {
|
||||
landmark_connections: 0
|
||||
landmark_connections: 1
|
||||
landmark_connections: 1
|
||||
landmark_connections: 2
|
||||
landmark_connections: 2
|
||||
landmark_connections: 3
|
||||
landmark_connections: 3
|
||||
landmark_connections: 4
|
||||
landmark_connections: 4
|
||||
landmark_connections: 5
|
||||
landmark_connections: 5
|
||||
landmark_connections: 6
|
||||
landmark_connections: 6
|
||||
landmark_connections: 7
|
||||
landmark_connections: 7
|
||||
landmark_connections: 8
|
||||
landmark_connections: 9
|
||||
landmark_connections: 10
|
||||
landmark_connections: 10
|
||||
landmark_connections: 11
|
||||
landmark_connections: 11
|
||||
landmark_connections: 12
|
||||
landmark_connections: 12
|
||||
landmark_connections: 13
|
||||
landmark_connections: 13
|
||||
landmark_connections: 14
|
||||
landmark_connections: 0
|
||||
landmark_connections: 9
|
||||
landmark_connections: 8
|
||||
landmark_connections: 14
|
||||
landmark_color { r: 255 g: 0 b: 0 }
|
||||
connection_color { r: 255 g: 0 b: 0 }
|
||||
visualize_landmark_depth: false
|
||||
thickness: 2.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Converts landmarks to drawing primitives for annotation overlay.
|
||||
node {
|
||||
calculator: "LandmarksToRenderDataCalculator"
|
||||
input_stream: "NORM_LANDMARKS:right_eye_contour_landmarks"
|
||||
output_stream: "RENDER_DATA:right_eye_contour_landmarks_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.LandmarksToRenderDataCalculatorOptions] {
|
||||
landmark_connections: 0
|
||||
landmark_connections: 1
|
||||
landmark_connections: 1
|
||||
landmark_connections: 2
|
||||
landmark_connections: 2
|
||||
landmark_connections: 3
|
||||
landmark_connections: 3
|
||||
landmark_connections: 4
|
||||
landmark_connections: 4
|
||||
landmark_connections: 5
|
||||
landmark_connections: 5
|
||||
landmark_connections: 6
|
||||
landmark_connections: 6
|
||||
landmark_connections: 7
|
||||
landmark_connections: 7
|
||||
landmark_connections: 8
|
||||
landmark_connections: 9
|
||||
landmark_connections: 10
|
||||
landmark_connections: 10
|
||||
landmark_connections: 11
|
||||
landmark_connections: 11
|
||||
landmark_connections: 12
|
||||
landmark_connections: 12
|
||||
landmark_connections: 13
|
||||
landmark_connections: 13
|
||||
landmark_connections: 14
|
||||
landmark_connections: 0
|
||||
landmark_connections: 9
|
||||
landmark_connections: 8
|
||||
landmark_connections: 14
|
||||
landmark_color { r: 255 g: 0 b: 0 }
|
||||
connection_color { r: 255 g: 0 b: 0 }
|
||||
visualize_landmark_depth: false
|
||||
thickness: 2.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Converts normalized rects to drawing primitives for annotation overlay.
|
||||
node {
|
||||
calculator: "RectToRenderDataCalculator"
|
||||
input_stream: "NORM_RECT:rect"
|
||||
output_stream: "RENDER_DATA:rect_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.RectToRenderDataCalculatorOptions] {
|
||||
filled: false
|
||||
color { r: 255 g: 0 b: 0 }
|
||||
thickness: 4.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "RectToRenderDataCalculator"
|
||||
input_stream: "NORM_RECT:right_eye_rect_from_landmarks"
|
||||
output_stream: "RENDER_DATA:right_eye_rect_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.RectToRenderDataCalculatorOptions] {
|
||||
filled: false
|
||||
color { r: 255 g: 0 b: 0 }
|
||||
thickness: 4.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "RectToRenderDataCalculator"
|
||||
input_stream: "NORM_RECT:left_eye_rect_from_landmarks"
|
||||
output_stream: "RENDER_DATA:left_eye_rect_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.RectToRenderDataCalculatorOptions] {
|
||||
filled: false
|
||||
color { r: 255 g: 0 b: 0 }
|
||||
thickness: 4.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "IrisToDepthCalculator"
|
||||
input_stream: "IRIS:iris_landmarks"
|
||||
input_stream: "IMAGE_SIZE:image_size"
|
||||
input_side_packet: "FOCAL_LENGTH:focal_length_pixel"
|
||||
output_stream: "LEFT_IRIS_DEPTH_MM:left_iris_depth_mm"
|
||||
output_stream: "RIGHT_IRIS_DEPTH_MM:right_iris_depth_mm"
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "IrisToRenderDataCalculator"
|
||||
input_stream: "IRIS:iris_landmarks"
|
||||
input_stream: "IMAGE_SIZE:image_size"
|
||||
input_stream: "LEFT_IRIS_DEPTH_MM:left_iris_depth_mm"
|
||||
input_stream: "RIGHT_IRIS_DEPTH_MM:right_iris_depth_mm"
|
||||
output_stream: "RENDER_DATA:iris_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.IrisToRenderDataCalculatorOptions] {
|
||||
oval_color { r: 0 g: 0 b: 255 }
|
||||
landmark_color { r: 0 g: 255 b: 0 }
|
||||
oval_thickness: 4.0
|
||||
landmark_thickness: 2.0
|
||||
font_height_px: 50
|
||||
horizontal_offset_px: 200
|
||||
vertical_offset_px: 200
|
||||
location: TOP_LEFT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Draws annotations and overlays them on top of the input images.
|
||||
node {
|
||||
calculator: "AnnotationOverlayCalculator"
|
||||
input_stream: "IMAGE_GPU:input_image"
|
||||
input_stream: "detection_render_data"
|
||||
input_stream: "right_eye_contour_landmarks_render_data"
|
||||
input_stream: "left_eye_contour_landmarks_render_data"
|
||||
input_stream: "iris_render_data"
|
||||
output_stream: "IMAGE_GPU:output_image"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.AnnotationOverlayCalculatorOptions] {
|
||||
gpu_scale_factor: 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
# MediaPipe iris tracking rendering subgraph.
|
||||
|
||||
type: "IrisRendererCpu"
|
||||
|
||||
input_stream: "IMAGE:input_image"
|
||||
input_stream: "DETECTIONS:detections"
|
||||
input_stream: "FACE_LANDMARKS:face_landmarks"
|
||||
input_stream: "EYE_LANDMARKS_LEFT:all_left_eye_contour_landmarks"
|
||||
input_stream: "EYE_LANDMARKS_RIGHT:all_right_eye_contour_landmarks"
|
||||
input_stream: "IRIS_LANDMARKS_LEFT:left_iris_landmarks"
|
||||
input_stream: "IRIS_LANDMARKS_RIGHT:right_iris_landmarks"
|
||||
input_stream: "NORM_RECT:rect"
|
||||
input_stream: "LEFT_EYE_RECT:left_eye_rect_from_landmarks"
|
||||
input_stream: "RIGHT_EYE_RECT:right_eye_rect_from_landmarks"
|
||||
output_stream: "IMAGE:output_image"
|
||||
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListCalculator"
|
||||
input_stream: "all_left_eye_contour_landmarks"
|
||||
output_stream: "left_eye_contour_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 0 end: 15 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "SplitNormalizedLandmarkListCalculator"
|
||||
input_stream: "all_right_eye_contour_landmarks"
|
||||
output_stream: "right_eye_contour_landmarks"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.SplitVectorCalculatorOptions] {
|
||||
ranges: { begin: 0 end: 15 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Concatenate iris landmarks from both eyes.
|
||||
node {
|
||||
calculator: "ConcatenateNormalizedLandmarkListCalculator"
|
||||
input_stream: "left_iris_landmarks"
|
||||
input_stream: "right_iris_landmarks"
|
||||
output_stream: "iris_landmarks"
|
||||
}
|
||||
|
||||
# Concatenate iris landmarks from both eyes and face landmarks.
|
||||
node {
|
||||
calculator: "ConcatenateNormalizedLandmarkListCalculator"
|
||||
input_stream: "left_iris_landmarks"
|
||||
input_stream: "right_iris_landmarks"
|
||||
input_stream: "face_landmarks"
|
||||
output_stream: "face_iris_landmarks"
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "ImagePropertiesCalculator"
|
||||
input_stream: "IMAGE:input_image"
|
||||
output_stream: "SIZE:image_size"
|
||||
}
|
||||
|
||||
# Maps detection label IDs to the corresponding label text ("Face").
|
||||
node {
|
||||
calculator: "DetectionLabelIdToTextCalculator"
|
||||
input_stream: "detections"
|
||||
output_stream: "labeled_detections"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.DetectionLabelIdToTextCalculatorOptions] {
|
||||
label: "Face"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Converts detections to drawing primitives for annotation overlay.
|
||||
node {
|
||||
calculator: "DetectionsToRenderDataCalculator"
|
||||
input_stream: "DETECTIONS:labeled_detections"
|
||||
output_stream: "RENDER_DATA:detection_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.DetectionsToRenderDataCalculatorOptions] {
|
||||
thickness: 4.0
|
||||
color { r: 0 g: 255 b: 0 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Converts landmarks to drawing primitives for annotation overlay.
|
||||
node {
|
||||
calculator: "LandmarksToRenderDataCalculator"
|
||||
input_stream: "NORM_LANDMARKS:left_eye_contour_landmarks"
|
||||
output_stream: "RENDER_DATA:left_eye_contour_landmarks_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.LandmarksToRenderDataCalculatorOptions] {
|
||||
landmark_connections: 0
|
||||
landmark_connections: 1
|
||||
landmark_connections: 1
|
||||
landmark_connections: 2
|
||||
landmark_connections: 2
|
||||
landmark_connections: 3
|
||||
landmark_connections: 3
|
||||
landmark_connections: 4
|
||||
landmark_connections: 4
|
||||
landmark_connections: 5
|
||||
landmark_connections: 5
|
||||
landmark_connections: 6
|
||||
landmark_connections: 6
|
||||
landmark_connections: 7
|
||||
landmark_connections: 7
|
||||
landmark_connections: 8
|
||||
landmark_connections: 9
|
||||
landmark_connections: 10
|
||||
landmark_connections: 10
|
||||
landmark_connections: 11
|
||||
landmark_connections: 11
|
||||
landmark_connections: 12
|
||||
landmark_connections: 12
|
||||
landmark_connections: 13
|
||||
landmark_connections: 13
|
||||
landmark_connections: 14
|
||||
landmark_connections: 0
|
||||
landmark_connections: 9
|
||||
landmark_connections: 8
|
||||
landmark_connections: 14
|
||||
landmark_color { r: 255 g: 0 b: 0 }
|
||||
connection_color { r: 255 g: 0 b: 0 }
|
||||
visualize_landmark_depth: false
|
||||
thickness: 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Converts landmarks to drawing primitives for annotation overlay.
|
||||
node {
|
||||
calculator: "LandmarksToRenderDataCalculator"
|
||||
input_stream: "NORM_LANDMARKS:right_eye_contour_landmarks"
|
||||
output_stream: "RENDER_DATA:right_eye_contour_landmarks_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.LandmarksToRenderDataCalculatorOptions] {
|
||||
landmark_connections: 0
|
||||
landmark_connections: 1
|
||||
landmark_connections: 1
|
||||
landmark_connections: 2
|
||||
landmark_connections: 2
|
||||
landmark_connections: 3
|
||||
landmark_connections: 3
|
||||
landmark_connections: 4
|
||||
landmark_connections: 4
|
||||
landmark_connections: 5
|
||||
landmark_connections: 5
|
||||
landmark_connections: 6
|
||||
landmark_connections: 6
|
||||
landmark_connections: 7
|
||||
landmark_connections: 7
|
||||
landmark_connections: 8
|
||||
landmark_connections: 9
|
||||
landmark_connections: 10
|
||||
landmark_connections: 10
|
||||
landmark_connections: 11
|
||||
landmark_connections: 11
|
||||
landmark_connections: 12
|
||||
landmark_connections: 12
|
||||
landmark_connections: 13
|
||||
landmark_connections: 13
|
||||
landmark_connections: 14
|
||||
landmark_connections: 0
|
||||
landmark_connections: 9
|
||||
landmark_connections: 8
|
||||
landmark_connections: 14
|
||||
landmark_color { r: 255 g: 0 b: 0 }
|
||||
connection_color { r: 255 g: 0 b: 0 }
|
||||
visualize_landmark_depth: false
|
||||
thickness: 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Converts normalized rects to drawing primitives for annotation overlay.
|
||||
node {
|
||||
calculator: "RectToRenderDataCalculator"
|
||||
input_stream: "NORM_RECT:rect"
|
||||
output_stream: "RENDER_DATA:rect_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.RectToRenderDataCalculatorOptions] {
|
||||
filled: false
|
||||
color { r: 255 g: 0 b: 0 }
|
||||
thickness: 4.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "RectToRenderDataCalculator"
|
||||
input_stream: "NORM_RECT:right_eye_rect_from_landmarks"
|
||||
output_stream: "RENDER_DATA:right_eye_rect_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.RectToRenderDataCalculatorOptions] {
|
||||
filled: false
|
||||
color { r: 255 g: 0 b: 0 }
|
||||
thickness: 4.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "RectToRenderDataCalculator"
|
||||
input_stream: "NORM_RECT:left_eye_rect_from_landmarks"
|
||||
output_stream: "RENDER_DATA:left_eye_rect_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.RectToRenderDataCalculatorOptions] {
|
||||
filled: false
|
||||
color { r: 255 g: 0 b: 0 }
|
||||
thickness: 4.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node {
|
||||
calculator: "IrisToRenderDataCalculator"
|
||||
input_stream: "IRIS:iris_landmarks"
|
||||
input_stream: "IMAGE_SIZE:image_size"
|
||||
output_stream: "RENDER_DATA:iris_render_data"
|
||||
node_options: {
|
||||
[type.googleapis.com/mediapipe.IrisToRenderDataCalculatorOptions] {
|
||||
oval_color { r: 0 g: 0 b: 255 }
|
||||
landmark_color { r: 0 g: 255 b: 0 }
|
||||
oval_thickness: 4.0
|
||||
landmark_thickness: 2.0
|
||||
font_height_px: 50
|
||||
horizontal_offset_px: 200
|
||||
vertical_offset_px: 200
|
||||
location: TOP_LEFT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Draws annotations and overlays them on top of the input images.
|
||||
node {
|
||||
calculator: "AnnotationOverlayCalculator"
|
||||
input_stream: "IMAGE:input_image"
|
||||
input_stream: "detection_render_data"
|
||||
input_stream: "right_eye_contour_landmarks_render_data"
|
||||
input_stream: "left_eye_contour_landmarks_render_data"
|
||||
input_stream: "iris_render_data"
|
||||
output_stream: "IMAGE:output_image"
|
||||
}
|
||||
Reference in New Issue
Block a user