Project import generated by Copybara.
GitOrigin-RevId: bbbbcb4f5174dea33525729ede47c770069157cd
This commit is contained in:
@@ -531,9 +531,13 @@ cc_test(
|
||||
":split_vector_calculator",
|
||||
"//mediapipe/framework:calculator_framework",
|
||||
"//mediapipe/framework:calculator_runner",
|
||||
"//mediapipe/framework/api2:node",
|
||||
"//mediapipe/framework/api2:port",
|
||||
"//mediapipe/framework/port:gtest_main",
|
||||
"//mediapipe/framework/port:parse_text_proto",
|
||||
"//mediapipe/framework/port:status",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/types:optional",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -47,4 +47,8 @@ typedef BeginLoopCalculator<std::vector<std::vector<Matrix>>>
|
||||
BeginLoopMatrixVectorCalculator;
|
||||
REGISTER_CALCULATOR(BeginLoopMatrixVectorCalculator);
|
||||
|
||||
// A calculator to process std::vector<uint64_t>.
|
||||
typedef BeginLoopCalculator<std::vector<uint64_t>> BeginLoopUint64tCalculator;
|
||||
REGISTER_CALCULATOR(BeginLoopUint64tCalculator);
|
||||
|
||||
} // namespace mediapipe
|
||||
|
||||
@@ -14,7 +14,11 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "mediapipe/calculators/core/split_vector_calculator.h"
|
||||
#include "mediapipe/framework/api2/node.h"
|
||||
#include "mediapipe/framework/api2/port.h"
|
||||
#include "mediapipe/framework/calculator_framework.h"
|
||||
#include "mediapipe/framework/calculator_runner.h"
|
||||
#include "mediapipe/framework/port/gtest.h"
|
||||
@@ -301,4 +305,99 @@ TEST(MuxCalculatorTest, DiscardSkippedInputs_MuxInputStreamHandler) {
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class PassThroughAndTsBoundUpdateNode : public mediapipe::api2::Node {
|
||||
public:
|
||||
static constexpr mediapipe::api2::Input<int> kInValue{"VALUE"};
|
||||
static constexpr mediapipe::api2::Output<int> kOutValue{"VALUE"};
|
||||
static constexpr mediapipe::api2::Output<int> kOutTsBoundUpdate{
|
||||
"TS_BOUND_UPDATE"};
|
||||
MEDIAPIPE_NODE_CONTRACT(kInValue, kOutValue, kOutTsBoundUpdate);
|
||||
|
||||
absl::Status Process(CalculatorContext* cc) override {
|
||||
kOutValue(cc).Send(kInValue(cc));
|
||||
kOutTsBoundUpdate(cc).SetNextTimestampBound(
|
||||
cc->InputTimestamp().NextAllowedInStream());
|
||||
return absl::OkStatus();
|
||||
}
|
||||
};
|
||||
MEDIAPIPE_REGISTER_NODE(PassThroughAndTsBoundUpdateNode);
|
||||
|
||||
class ToOptionalNode : public mediapipe::api2::Node {
|
||||
public:
|
||||
static constexpr mediapipe::api2::Input<int> kTick{"TICK"};
|
||||
static constexpr mediapipe::api2::Input<int> kInValue{"VALUE"};
|
||||
static constexpr mediapipe::api2::Output<absl::optional<int>> kOutValue{
|
||||
"OUTPUT"};
|
||||
MEDIAPIPE_NODE_CONTRACT(kTick, kInValue, kOutValue);
|
||||
|
||||
absl::Status Process(CalculatorContext* cc) override {
|
||||
if (kInValue(cc).IsEmpty()) {
|
||||
kOutValue(cc).Send(absl::nullopt);
|
||||
} else {
|
||||
kOutValue(cc).Send({kInValue(cc).Get()});
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
};
|
||||
MEDIAPIPE_REGISTER_NODE(ToOptionalNode);
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(MuxCalculatorTest, HandleTimestampBoundUpdates) {
|
||||
CalculatorGraphConfig config =
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(
|
||||
R"pb(
|
||||
input_stream: "select"
|
||||
node {
|
||||
calculator: "PassThroughAndTsBoundUpdateNode"
|
||||
input_stream: "VALUE:select"
|
||||
output_stream: "VALUE:select_ps"
|
||||
output_stream: "TS_BOUND_UPDATE:ts_bound_update"
|
||||
}
|
||||
node {
|
||||
calculator: "MuxCalculator"
|
||||
input_stream: "INPUT:0:select_ps"
|
||||
input_stream: "INPUT:1:ts_bound_update"
|
||||
input_stream: "SELECT:select"
|
||||
output_stream: "OUTPUT:select_or_ts_bound_update"
|
||||
}
|
||||
node {
|
||||
calculator: "ToOptionalNode"
|
||||
input_stream: "TICK:select"
|
||||
input_stream: "VALUE:select_or_ts_bound_update"
|
||||
output_stream: "OUTPUT:output"
|
||||
}
|
||||
)pb");
|
||||
std::vector<Packet> output_packets;
|
||||
tool::AddVectorSink("output", &config, &output_packets);
|
||||
|
||||
CalculatorGraph graph;
|
||||
MP_ASSERT_OK(graph.Initialize(config));
|
||||
MP_ASSERT_OK(graph.StartRun({}));
|
||||
|
||||
auto send_value_fn = [&](int value, Timestamp ts) -> absl::Status {
|
||||
MP_RETURN_IF_ERROR(
|
||||
graph.AddPacketToInputStream("select", MakePacket<int>(value).At(ts)));
|
||||
return graph.WaitUntilIdle();
|
||||
};
|
||||
|
||||
MP_ASSERT_OK(send_value_fn(0, Timestamp(1)));
|
||||
ASSERT_EQ(output_packets.size(), 1);
|
||||
EXPECT_EQ(output_packets[0].Get<absl::optional<int>>(), 0);
|
||||
|
||||
MP_ASSERT_OK(send_value_fn(1, Timestamp(2)));
|
||||
ASSERT_EQ(output_packets.size(), 2);
|
||||
EXPECT_EQ(output_packets[1].Get<absl::optional<int>>(), absl::nullopt);
|
||||
|
||||
MP_ASSERT_OK(send_value_fn(0, Timestamp(3)));
|
||||
ASSERT_EQ(output_packets.size(), 3);
|
||||
EXPECT_EQ(output_packets[2].Get<absl::optional<int>>(), 0);
|
||||
|
||||
MP_ASSERT_OK(graph.CloseAllInputStreams());
|
||||
MP_ASSERT_OK(graph.WaitUntilDone());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace mediapipe
|
||||
|
||||
@@ -34,7 +34,6 @@ option java_outer_classname = "InferenceCalculatorProto";
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
message InferenceCalculatorOptions {
|
||||
extend mediapipe.CalculatorOptions {
|
||||
optional InferenceCalculatorOptions ext = 336783863;
|
||||
@@ -69,8 +68,30 @@ message InferenceCalculatorOptions {
|
||||
// Load pre-compiled serialized binary cache to accelerate init process.
|
||||
// Only available for OpenCL delegate on Android.
|
||||
// Kernel caching will only be enabled if this path is set.
|
||||
//
|
||||
// NOTE: binary cache usage may be skipped if valid serialized model,
|
||||
// specified by "serialized_model_dir", exists.
|
||||
//
|
||||
// TODO: update to cached_kernel_dir
|
||||
optional string cached_kernel_path = 2;
|
||||
|
||||
// A dir to load from and save to a pre-compiled serialized model used to
|
||||
// accelerate init process.
|
||||
//
|
||||
// NOTE: available for OpenCL delegate on Android only when
|
||||
// "use_advanced_gpu_api" is set to true and "model_token" is set
|
||||
// properly.
|
||||
//
|
||||
// NOTE: serialized model takes precedence over binary cache
|
||||
// specified by "cached_kernel_path", which still can be used if
|
||||
// serialized model is invalid or missing.
|
||||
optional string serialized_model_dir = 7;
|
||||
|
||||
// Unique token identifying the model. Used in conjunction with
|
||||
// "serialized_model_dir". It is the caller's responsibility to ensure
|
||||
// there is no clash of the tokens.
|
||||
optional string model_token = 8;
|
||||
|
||||
// Encapsulated compilation/runtime tradeoffs.
|
||||
enum InferenceUsage {
|
||||
UNSPECIFIED = 0;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "mediapipe/calculators/tensor/inference_calculator.h"
|
||||
#include "mediapipe/framework/deps/file_path.h"
|
||||
#include "mediapipe/util/tflite/config.h"
|
||||
|
||||
#if MEDIAPIPE_TFLITE_GL_INFERENCE
|
||||
@@ -49,8 +50,8 @@ class InferenceCalculatorGlImpl
|
||||
absl::Status Close(CalculatorContext* cc) override;
|
||||
|
||||
private:
|
||||
absl::Status ReadKernelsFromFile();
|
||||
absl::Status WriteKernelsToFile();
|
||||
absl::Status ReadGpuCaches();
|
||||
absl::Status SaveGpuCaches();
|
||||
absl::Status LoadModel(CalculatorContext* cc);
|
||||
absl::Status LoadDelegate(CalculatorContext* cc);
|
||||
absl::Status LoadDelegateAndAllocateTensors(CalculatorContext* cc);
|
||||
@@ -82,6 +83,8 @@ class InferenceCalculatorGlImpl
|
||||
|
||||
bool use_kernel_caching_ = false;
|
||||
std::string cached_kernel_filename_;
|
||||
bool use_serialized_model_ = false;
|
||||
std::string serialized_model_path_;
|
||||
};
|
||||
|
||||
absl::Status InferenceCalculatorGlImpl::UpdateContract(CalculatorContract* cc) {
|
||||
@@ -114,6 +117,9 @@ absl::Status InferenceCalculatorGlImpl::Open(CalculatorContext* cc) {
|
||||
tflite_gpu_runner_usage_ = delegate.gpu().usage();
|
||||
use_kernel_caching_ =
|
||||
use_advanced_gpu_api_ && delegate.gpu().has_cached_kernel_path();
|
||||
use_serialized_model_ = use_advanced_gpu_api_ &&
|
||||
delegate.gpu().has_serialized_model_dir() &&
|
||||
delegate.gpu().has_model_token();
|
||||
use_gpu_delegate_ = !use_advanced_gpu_api_;
|
||||
|
||||
if (use_kernel_caching_) {
|
||||
@@ -123,6 +129,12 @@ absl::Status InferenceCalculatorGlImpl::Open(CalculatorContext* cc) {
|
||||
".ker";
|
||||
#endif // MEDIAPIPE_ANDROID
|
||||
}
|
||||
if (use_serialized_model_) {
|
||||
#ifdef MEDIAPIPE_ANDROID
|
||||
serialized_model_path_ = mediapipe::file::JoinPath(
|
||||
delegate.gpu().serialized_model_dir(), delegate.gpu().model_token());
|
||||
#endif // MEDIAPIPE_ANDROID
|
||||
}
|
||||
|
||||
// When use_advanced_gpu_api_, model loading is handled in InitTFLiteGPURunner
|
||||
// for everything.
|
||||
@@ -210,7 +222,7 @@ absl::Status InferenceCalculatorGlImpl::Process(CalculatorContext* cc) {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status InferenceCalculatorGlImpl::WriteKernelsToFile() {
|
||||
absl::Status InferenceCalculatorGlImpl::SaveGpuCaches() {
|
||||
#ifdef MEDIAPIPE_ANDROID
|
||||
if (use_kernel_caching_) {
|
||||
// Save kernel file.
|
||||
@@ -220,12 +232,22 @@ absl::Status InferenceCalculatorGlImpl::WriteKernelsToFile() {
|
||||
MP_RETURN_IF_ERROR(
|
||||
mediapipe::file::SetContents(cached_kernel_filename_, cache_str));
|
||||
}
|
||||
if (use_serialized_model_) {
|
||||
// Save serialized model file.
|
||||
ASSIGN_OR_RETURN(std::vector<uint8_t> serialized_model_vec,
|
||||
tflite_gpu_runner_->GetSerializedModel());
|
||||
absl::string_view serialized_model(
|
||||
reinterpret_cast<char*>(serialized_model_vec.data()),
|
||||
serialized_model_vec.size());
|
||||
MP_RETURN_IF_ERROR(
|
||||
mediapipe::file::SetContents(serialized_model_path_, serialized_model));
|
||||
}
|
||||
#endif // MEDIAPIPE_ANDROID
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status InferenceCalculatorGlImpl::Close(CalculatorContext* cc) {
|
||||
MP_RETURN_IF_ERROR(WriteKernelsToFile());
|
||||
MP_RETURN_IF_ERROR(SaveGpuCaches());
|
||||
if (use_gpu_delegate_) {
|
||||
MP_RETURN_IF_ERROR(gpu_helper_.RunInGlContext([this]() -> Status {
|
||||
gpu_buffers_in_.clear();
|
||||
@@ -239,17 +261,24 @@ absl::Status InferenceCalculatorGlImpl::Close(CalculatorContext* cc) {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status InferenceCalculatorGlImpl::ReadKernelsFromFile() {
|
||||
absl::Status InferenceCalculatorGlImpl::ReadGpuCaches() {
|
||||
#ifdef MEDIAPIPE_ANDROID
|
||||
if (use_kernel_caching_) {
|
||||
if (use_kernel_caching_ && File::Exists(cached_kernel_filename_)) {
|
||||
// Load pre-compiled kernel file.
|
||||
if (mediapipe::File::Exists(cached_kernel_filename_)) {
|
||||
std::string cache_str;
|
||||
MP_RETURN_IF_ERROR(
|
||||
mediapipe::file::GetContents(cached_kernel_filename_, &cache_str));
|
||||
std::vector<uint8_t> cache_vec(cache_str.begin(), cache_str.end());
|
||||
tflite_gpu_runner_->SetSerializedBinaryCache(std::move(cache_vec));
|
||||
}
|
||||
std::string cache_str;
|
||||
MP_RETURN_IF_ERROR(
|
||||
mediapipe::file::GetContents(cached_kernel_filename_, &cache_str));
|
||||
std::vector<uint8_t> cache_vec(cache_str.begin(), cache_str.end());
|
||||
tflite_gpu_runner_->SetSerializedBinaryCache(std::move(cache_vec));
|
||||
}
|
||||
if (use_serialized_model_ && File::Exists(serialized_model_path_)) {
|
||||
// Load serialized model file.
|
||||
std::string serialized_model_str;
|
||||
MP_RETURN_IF_ERROR(
|
||||
file::GetContents(serialized_model_path_, &serialized_model_str));
|
||||
std::vector<uint8_t> serialized_model_vec(serialized_model_str.begin(),
|
||||
serialized_model_str.end());
|
||||
tflite_gpu_runner_->SetSerializedModel(std::move(serialized_model_vec));
|
||||
}
|
||||
#endif // MEDIAPIPE_ANDROID
|
||||
return absl::OkStatus();
|
||||
@@ -313,7 +342,7 @@ absl::Status InferenceCalculatorGlImpl::InitTFLiteGPURunner(
|
||||
tflite_gpu_runner_->GetOutputShapes()[i].c};
|
||||
}
|
||||
|
||||
MP_RETURN_IF_ERROR(ReadKernelsFromFile());
|
||||
MP_RETURN_IF_ERROR(ReadGpuCaches());
|
||||
|
||||
MP_RETURN_IF_ERROR(tflite_gpu_runner_->Build());
|
||||
|
||||
|
||||
@@ -24,20 +24,20 @@ message SsdAnchorsCalculatorOptions {
|
||||
optional SsdAnchorsCalculatorOptions ext = 247258239;
|
||||
}
|
||||
// Size of input images.
|
||||
required int32 input_size_width = 1;
|
||||
required int32 input_size_height = 2;
|
||||
optional int32 input_size_width = 1; // required
|
||||
optional int32 input_size_height = 2; // required
|
||||
|
||||
// Min and max scales for generating anchor boxes on feature maps.
|
||||
required float min_scale = 3;
|
||||
required float max_scale = 4;
|
||||
optional float min_scale = 3; // required
|
||||
optional float max_scale = 4; // required
|
||||
|
||||
// The offset for the center of anchors. The value is in the scale of stride.
|
||||
// E.g. 0.5 meaning 0.5 * |current_stride| in pixels.
|
||||
required float anchor_offset_x = 5 [default = 0.5];
|
||||
required float anchor_offset_y = 6 [default = 0.5];
|
||||
optional float anchor_offset_x = 5 [default = 0.5]; // required
|
||||
optional float anchor_offset_y = 6 [default = 0.5]; // required
|
||||
|
||||
// Number of output feature maps to generate the anchors on.
|
||||
required int32 num_layers = 7;
|
||||
optional int32 num_layers = 7; // required
|
||||
// Sizes of output feature maps to create anchors. Either feature_map size or
|
||||
// stride should be provided.
|
||||
repeated int32 feature_map_width = 8;
|
||||
|
||||
@@ -26,12 +26,12 @@ message TfLiteTensorsToDetectionsCalculatorOptions {
|
||||
}
|
||||
|
||||
// The number of output classes predicted by the detection model.
|
||||
required int32 num_classes = 1;
|
||||
optional int32 num_classes = 1; // required
|
||||
// The number of output boxes predicted by the detection model.
|
||||
required int32 num_boxes = 2;
|
||||
optional int32 num_boxes = 2; // required
|
||||
// The number of output values per boxes predicted by the detection model. The
|
||||
// values contain bounding boxes, keypoints, etc.
|
||||
required int32 num_coords = 3;
|
||||
optional int32 num_coords = 3; // required
|
||||
|
||||
// The offset of keypoint coordinates in the location tensor.
|
||||
optional int32 keypoint_coord_offset = 9;
|
||||
|
||||
@@ -31,7 +31,7 @@ message TfLiteTensorsToLandmarksCalculatorOptions {
|
||||
}
|
||||
|
||||
// Number of landmarks from the output of the model.
|
||||
required int32 num_landmarks = 1;
|
||||
optional int32 num_landmarks = 1; // required
|
||||
|
||||
// Size of the input image for the model. These options are used only when
|
||||
// normalized landmarks are needed. Z coordinate is scaled as X assuming
|
||||
|
||||
@@ -24,9 +24,9 @@ message TfLiteTensorsToSegmentationCalculatorOptions {
|
||||
}
|
||||
|
||||
// Dimensions of input segmentation tensor to process.
|
||||
required int32 tensor_width = 1;
|
||||
required int32 tensor_height = 2;
|
||||
required int32 tensor_channels = 3;
|
||||
optional int32 tensor_width = 1; // required
|
||||
optional int32 tensor_height = 2; // required
|
||||
optional int32 tensor_channels = 3; // required
|
||||
|
||||
// How much to use previous mask when computing current one; range [0-1].
|
||||
// This is a tradeoff between responsiveness (0.0) and accuracy (1.0).
|
||||
|
||||
Reference in New Issue
Block a user