177 lines
7.1 KiB
C++
177 lines
7.1 KiB
C++
/* Copyright 2022 The MediaPipe Authors. All Rights Reserved.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
==============================================================================*/
|
|
|
|
#include "absl/status/statusor.h"
|
|
#include "mediapipe/framework/api2/builder.h"
|
|
#include "mediapipe/framework/api2/port.h"
|
|
#include "mediapipe/framework/calculator_framework.h"
|
|
#include "mediapipe/framework/formats/image.h"
|
|
#include "mediapipe/framework/formats/rect.pb.h"
|
|
#include "mediapipe/tasks/cc/components/containers/proto/embeddings.pb.h"
|
|
#include "mediapipe/tasks/cc/components/processors/embedding_postprocessing_graph.h"
|
|
#include "mediapipe/tasks/cc/components/processors/image_preprocessing_graph.h"
|
|
#include "mediapipe/tasks/cc/components/processors/proto/embedding_postprocessing_graph_options.pb.h"
|
|
#include "mediapipe/tasks/cc/components/processors/proto/image_preprocessing_graph_options.pb.h"
|
|
#include "mediapipe/tasks/cc/core/model_task_graph.h"
|
|
#include "mediapipe/tasks/cc/vision/image_embedder/proto/image_embedder_graph_options.pb.h"
|
|
|
|
namespace mediapipe {
|
|
namespace tasks {
|
|
namespace vision {
|
|
namespace image_embedder {
|
|
|
|
namespace {
|
|
|
|
using ::mediapipe::api2::Input;
|
|
using ::mediapipe::api2::Output;
|
|
using ::mediapipe::api2::builder::GenericNode;
|
|
using ::mediapipe::api2::builder::Graph;
|
|
using ::mediapipe::api2::builder::Source;
|
|
using ::mediapipe::tasks::components::containers::proto::EmbeddingResult;
|
|
|
|
constexpr char kEmbeddingsTag[] = "EMBEDDINGS";
|
|
constexpr char kImageTag[] = "IMAGE";
|
|
constexpr char kNormRectTag[] = "NORM_RECT";
|
|
constexpr char kTensorsTag[] = "TENSORS";
|
|
|
|
// Struct holding the different output streams produced by the image embedder
|
|
// graph.
|
|
struct ImageEmbedderOutputStreams {
|
|
Source<EmbeddingResult> embedding_result;
|
|
Source<Image> image;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
// An ImageEmbedderGraph performs image embedding extraction.
|
|
// - Accepts CPU input images and outputs embeddings on CPU.
|
|
//
|
|
// Inputs:
|
|
// IMAGE - Image
|
|
// Image to perform embedding extraction on.
|
|
// NORM_RECT - NormalizedRect @Optional
|
|
// Describes region of image to perform embedding extraction on.
|
|
// @Optional: rect covering the whole image is used if not specified.
|
|
// Outputs:
|
|
// EMBEDDINGS - EmbeddingResult
|
|
// The embedding result.
|
|
// IMAGE - Image
|
|
// The image that embedding extraction runs on.
|
|
//
|
|
// Example:
|
|
// node {
|
|
// calculator: "mediapipe.tasks.vision.image_embedder.ImageEmbedderGraph"
|
|
// input_stream: "IMAGE:image_in"
|
|
// output_stream: "EMBEDDINGS:embedding_result_out"
|
|
// output_stream: "IMAGE:image_out"
|
|
// options {
|
|
// [mediapipe.tasks.vision.image_embedder.proto.ImageEmbedderOptions.ext]
|
|
// {
|
|
// base_options {
|
|
// model_asset {
|
|
// file_name: "/path/to/model.tflite"
|
|
// }
|
|
// }
|
|
// embedder_options {
|
|
// l2_normalize: true
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
class ImageEmbedderGraph : public core::ModelTaskGraph {
|
|
public:
|
|
absl::StatusOr<CalculatorGraphConfig> GetConfig(
|
|
SubgraphContext* sc) override {
|
|
ASSIGN_OR_RETURN(
|
|
const auto* model_resources,
|
|
CreateModelResources<proto::ImageEmbedderGraphOptions>(sc));
|
|
Graph graph;
|
|
ASSIGN_OR_RETURN(
|
|
auto output_streams,
|
|
BuildImageEmbedderTask(
|
|
sc->Options<proto::ImageEmbedderGraphOptions>(), *model_resources,
|
|
graph[Input<Image>(kImageTag)],
|
|
graph[Input<NormalizedRect>::Optional(kNormRectTag)], graph));
|
|
output_streams.embedding_result >>
|
|
graph[Output<EmbeddingResult>(kEmbeddingsTag)];
|
|
output_streams.image >> graph[Output<Image>(kImageTag)];
|
|
return graph.GetConfig();
|
|
}
|
|
|
|
private:
|
|
// Adds a mediapipe image embedding teask graph into the provided
|
|
// builder::Graph instance. The image embedding task takes images
|
|
// (mediapipe::Image) and optional region-of-interest
|
|
// (mediapipe::NormalizedRect) as inputs and returns on embedding result per
|
|
// input image.
|
|
//
|
|
// task_options: the mediapipe tasks ImageEmbedderGraphOptions.
|
|
// model_resources: the ModelSources object initialized from an image
|
|
// embedding model file with model optional metadata.
|
|
// image_in: (mediapipe::Image) stream to run embedding extraction on.
|
|
// norm_rect_in: (mediapipe::NormalizedRect) optional region-of-interest to
|
|
// perform embedding extraction on.
|
|
// graph: the mediapipe builder::Graph instance to be updated.
|
|
absl::StatusOr<ImageEmbedderOutputStreams> BuildImageEmbedderTask(
|
|
const proto::ImageEmbedderGraphOptions& task_options,
|
|
const core::ModelResources& model_resources, Source<Image> image_in,
|
|
Source<NormalizedRect> norm_rect_in, Graph& graph) {
|
|
// Adds preprocessing calculators and connects them to the graph input image
|
|
// stream.
|
|
auto& preprocessing = graph.AddNode(
|
|
"mediapipe.tasks.components.processors.ImagePreprocessingGraph");
|
|
bool use_gpu =
|
|
components::processors::DetermineImagePreprocessingGpuBackend(
|
|
task_options.base_options().acceleration());
|
|
MP_RETURN_IF_ERROR(components::processors::ConfigureImagePreprocessingGraph(
|
|
model_resources, use_gpu,
|
|
&preprocessing.GetOptions<tasks::components::processors::proto::
|
|
ImagePreprocessingGraphOptions>()));
|
|
image_in >> preprocessing.In(kImageTag);
|
|
norm_rect_in >> preprocessing.In(kNormRectTag);
|
|
|
|
// Adds inference subgraph and connects its input stream to the outoput
|
|
// tensors produced by the ImageToTensorCalculator.
|
|
auto& inference = AddInference(
|
|
model_resources, task_options.base_options().acceleration(), graph);
|
|
preprocessing.Out(kTensorsTag) >> inference.In(kTensorsTag);
|
|
|
|
// Adds postprocessing calculators and connects its input stream to the
|
|
// inference results.
|
|
auto& postprocessing = graph.AddNode(
|
|
"mediapipe.tasks.components.processors.EmbeddingPostprocessingGraph");
|
|
MP_RETURN_IF_ERROR(
|
|
components::processors::ConfigureEmbeddingPostprocessingGraph(
|
|
model_resources, task_options.embedder_options(),
|
|
&postprocessing
|
|
.GetOptions<components::processors::proto::
|
|
EmbeddingPostprocessingGraphOptions>()));
|
|
inference.Out(kTensorsTag) >> postprocessing.In(kTensorsTag);
|
|
|
|
// Outputs the embedding results.
|
|
return ImageEmbedderOutputStreams{
|
|
/*embedding_result=*/postprocessing[Output<EmbeddingResult>(
|
|
kEmbeddingsTag)],
|
|
/*image=*/preprocessing[Output<Image>(kImageTag)]};
|
|
}
|
|
};
|
|
REGISTER_MEDIAPIPE_GRAPH(
|
|
::mediapipe::tasks::vision::image_embedder::ImageEmbedderGraph);
|
|
|
|
} // namespace image_embedder
|
|
} // namespace vision
|
|
} // namespace tasks
|
|
} // namespace mediapipe
|