Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d05709f62 |
@@ -239,16 +239,6 @@ http_archive(
|
||||
repo_mapping = {"@com_google_glog" : "@com_github_glog_glog_no_gflags"},
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "darts_clone",
|
||||
build_file = "@//third_party:darts_clone.BUILD",
|
||||
sha256 = "c97f55d05c98da6fcaf7f9ecc6a6dc6bc5b18b8564465f77abff8879d446491c",
|
||||
strip_prefix = "darts-clone-e40ce4627526985a7767444b6ed6893ab6ff8983",
|
||||
urls = [
|
||||
"https://github.com/s-yata/darts-clone/archive/e40ce4627526985a7767444b6ed6893ab6ff8983.zip",
|
||||
],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "org_tensorflow_text",
|
||||
sha256 = "f64647276f7288d1b1fe4c89581d51404d0ce4ae97f2bcc4c19bd667549adca8",
|
||||
@@ -468,9 +458,9 @@ http_archive(
|
||||
)
|
||||
|
||||
# TensorFlow repo should always go after the other external dependencies.
|
||||
# TF on 2023-04-12.
|
||||
_TENSORFLOW_GIT_COMMIT = "d712c0c9e24519cc8cd3720279666720d1000eee"
|
||||
_TENSORFLOW_SHA256 = "ba98de6ea5f720071246691a1536ecd5e1b1763033e8c82a1e721a06d3dfd4c1"
|
||||
# TF on 2023-03-08.
|
||||
_TENSORFLOW_GIT_COMMIT = "24f7ee636d62e1f8d8330357f8bbd65956dfb84d"
|
||||
_TENSORFLOW_SHA256 = "7f8a96dd99215c0cdc77230d3dbce43e60102b64a89203ad04aa09b0a187a4bd"
|
||||
http_archive(
|
||||
name = "org_tensorflow",
|
||||
urls = [
|
||||
|
||||
@@ -78,7 +78,7 @@ class ConstantSidePacketCalculator : public CalculatorBase {
|
||||
} else if (packet_options.has_string_value()) {
|
||||
packet.Set<std::string>();
|
||||
} else if (packet_options.has_uint64_value()) {
|
||||
packet.Set<uint64_t>();
|
||||
packet.Set<uint64>();
|
||||
} else if (packet_options.has_classification_list_value()) {
|
||||
packet.Set<ClassificationList>();
|
||||
} else if (packet_options.has_landmark_list_value()) {
|
||||
@@ -112,7 +112,7 @@ class ConstantSidePacketCalculator : public CalculatorBase {
|
||||
} else if (packet_options.has_string_value()) {
|
||||
packet.Set(MakePacket<std::string>(packet_options.string_value()));
|
||||
} else if (packet_options.has_uint64_value()) {
|
||||
packet.Set(MakePacket<uint64_t>(packet_options.uint64_value()));
|
||||
packet.Set(MakePacket<uint64>(packet_options.uint64_value()));
|
||||
} else if (packet_options.has_classification_list_value()) {
|
||||
packet.Set(MakePacket<ClassificationList>(
|
||||
packet_options.classification_list_value()));
|
||||
|
||||
@@ -35,14 +35,14 @@ class GateCalculatorTest : public ::testing::Test {
|
||||
}
|
||||
|
||||
// Use this when ALLOW/DISALLOW input is provided as a side packet.
|
||||
void RunTimeStep(int64_t timestamp, bool stream_payload) {
|
||||
void RunTimeStep(int64 timestamp, bool stream_payload) {
|
||||
runner_->MutableInputs()->Get("", 0).packets.push_back(
|
||||
MakePacket<bool>(stream_payload).At(Timestamp(timestamp)));
|
||||
MP_ASSERT_OK(runner_->Run()) << "Calculator execution failed.";
|
||||
}
|
||||
|
||||
// Use this when ALLOW/DISALLOW input is provided as an input stream.
|
||||
void RunTimeStep(int64_t timestamp, const std::string& control_tag,
|
||||
void RunTimeStep(int64 timestamp, const std::string& control_tag,
|
||||
bool control) {
|
||||
runner_->MutableInputs()->Get("", 0).packets.push_back(
|
||||
MakePacket<bool>(true).At(Timestamp(timestamp)));
|
||||
@@ -134,9 +134,9 @@ TEST_F(GateCalculatorTest, AllowByALLOWOptionToTrue) {
|
||||
}
|
||||
)");
|
||||
|
||||
constexpr int64_t kTimestampValue0 = 42;
|
||||
constexpr int64 kTimestampValue0 = 42;
|
||||
RunTimeStep(kTimestampValue0, true);
|
||||
constexpr int64_t kTimestampValue1 = 43;
|
||||
constexpr int64 kTimestampValue1 = 43;
|
||||
RunTimeStep(kTimestampValue1, false);
|
||||
|
||||
const std::vector<Packet>& output = runner()->Outputs().Get("", 0).packets;
|
||||
@@ -159,9 +159,9 @@ TEST_F(GateCalculatorTest, DisallowByALLOWOptionSetToFalse) {
|
||||
}
|
||||
)");
|
||||
|
||||
constexpr int64_t kTimestampValue0 = 42;
|
||||
constexpr int64 kTimestampValue0 = 42;
|
||||
RunTimeStep(kTimestampValue0, true);
|
||||
constexpr int64_t kTimestampValue1 = 43;
|
||||
constexpr int64 kTimestampValue1 = 43;
|
||||
RunTimeStep(kTimestampValue1, false);
|
||||
|
||||
const std::vector<Packet>& output = runner()->Outputs().Get("", 0).packets;
|
||||
@@ -175,9 +175,9 @@ TEST_F(GateCalculatorTest, DisallowByALLOWOptionNotSet) {
|
||||
output_stream: "test_output"
|
||||
)");
|
||||
|
||||
constexpr int64_t kTimestampValue0 = 42;
|
||||
constexpr int64 kTimestampValue0 = 42;
|
||||
RunTimeStep(kTimestampValue0, true);
|
||||
constexpr int64_t kTimestampValue1 = 43;
|
||||
constexpr int64 kTimestampValue1 = 43;
|
||||
RunTimeStep(kTimestampValue1, false);
|
||||
|
||||
const std::vector<Packet>& output = runner()->Outputs().Get("", 0).packets;
|
||||
@@ -193,9 +193,9 @@ TEST_F(GateCalculatorTest, AllowByALLOWSidePacketSetToTrue) {
|
||||
)");
|
||||
runner()->MutableSidePackets()->Tag(kAllowTag) = Adopt(new bool(true));
|
||||
|
||||
constexpr int64_t kTimestampValue0 = 42;
|
||||
constexpr int64 kTimestampValue0 = 42;
|
||||
RunTimeStep(kTimestampValue0, true);
|
||||
constexpr int64_t kTimestampValue1 = 43;
|
||||
constexpr int64 kTimestampValue1 = 43;
|
||||
RunTimeStep(kTimestampValue1, false);
|
||||
|
||||
const std::vector<Packet>& output = runner()->Outputs().Get("", 0).packets;
|
||||
@@ -215,9 +215,9 @@ TEST_F(GateCalculatorTest, AllowByDisallowSidePacketSetToFalse) {
|
||||
)");
|
||||
runner()->MutableSidePackets()->Tag(kDisallowTag) = Adopt(new bool(false));
|
||||
|
||||
constexpr int64_t kTimestampValue0 = 42;
|
||||
constexpr int64 kTimestampValue0 = 42;
|
||||
RunTimeStep(kTimestampValue0, true);
|
||||
constexpr int64_t kTimestampValue1 = 43;
|
||||
constexpr int64 kTimestampValue1 = 43;
|
||||
RunTimeStep(kTimestampValue1, false);
|
||||
|
||||
const std::vector<Packet>& output = runner()->Outputs().Get("", 0).packets;
|
||||
@@ -237,9 +237,9 @@ TEST_F(GateCalculatorTest, DisallowByALLOWSidePacketSetToFalse) {
|
||||
)");
|
||||
runner()->MutableSidePackets()->Tag(kAllowTag) = Adopt(new bool(false));
|
||||
|
||||
constexpr int64_t kTimestampValue0 = 42;
|
||||
constexpr int64 kTimestampValue0 = 42;
|
||||
RunTimeStep(kTimestampValue0, true);
|
||||
constexpr int64_t kTimestampValue1 = 43;
|
||||
constexpr int64 kTimestampValue1 = 43;
|
||||
RunTimeStep(kTimestampValue1, false);
|
||||
|
||||
const std::vector<Packet>& output = runner()->Outputs().Get("", 0).packets;
|
||||
@@ -255,9 +255,9 @@ TEST_F(GateCalculatorTest, DisallowByDISALLOWSidePacketSetToTrue) {
|
||||
)");
|
||||
runner()->MutableSidePackets()->Tag(kDisallowTag) = Adopt(new bool(true));
|
||||
|
||||
constexpr int64_t kTimestampValue0 = 42;
|
||||
constexpr int64 kTimestampValue0 = 42;
|
||||
RunTimeStep(kTimestampValue0, true);
|
||||
constexpr int64_t kTimestampValue1 = 43;
|
||||
constexpr int64 kTimestampValue1 = 43;
|
||||
RunTimeStep(kTimestampValue1, false);
|
||||
|
||||
const std::vector<Packet>& output = runner()->Outputs().Get("", 0).packets;
|
||||
@@ -272,13 +272,13 @@ TEST_F(GateCalculatorTest, Allow) {
|
||||
output_stream: "test_output"
|
||||
)");
|
||||
|
||||
constexpr int64_t kTimestampValue0 = 42;
|
||||
constexpr int64 kTimestampValue0 = 42;
|
||||
RunTimeStep(kTimestampValue0, "ALLOW", true);
|
||||
constexpr int64_t kTimestampValue1 = 43;
|
||||
constexpr int64 kTimestampValue1 = 43;
|
||||
RunTimeStep(kTimestampValue1, "ALLOW", false);
|
||||
constexpr int64_t kTimestampValue2 = 44;
|
||||
constexpr int64 kTimestampValue2 = 44;
|
||||
RunTimeStep(kTimestampValue2, "ALLOW", true);
|
||||
constexpr int64_t kTimestampValue3 = 45;
|
||||
constexpr int64 kTimestampValue3 = 45;
|
||||
RunTimeStep(kTimestampValue3, "ALLOW", false);
|
||||
|
||||
const std::vector<Packet>& output = runner()->Outputs().Get("", 0).packets;
|
||||
@@ -297,13 +297,13 @@ TEST_F(GateCalculatorTest, Disallow) {
|
||||
output_stream: "test_output"
|
||||
)");
|
||||
|
||||
constexpr int64_t kTimestampValue0 = 42;
|
||||
constexpr int64 kTimestampValue0 = 42;
|
||||
RunTimeStep(kTimestampValue0, "DISALLOW", true);
|
||||
constexpr int64_t kTimestampValue1 = 43;
|
||||
constexpr int64 kTimestampValue1 = 43;
|
||||
RunTimeStep(kTimestampValue1, "DISALLOW", false);
|
||||
constexpr int64_t kTimestampValue2 = 44;
|
||||
constexpr int64 kTimestampValue2 = 44;
|
||||
RunTimeStep(kTimestampValue2, "DISALLOW", true);
|
||||
constexpr int64_t kTimestampValue3 = 45;
|
||||
constexpr int64 kTimestampValue3 = 45;
|
||||
RunTimeStep(kTimestampValue3, "DISALLOW", false);
|
||||
|
||||
const std::vector<Packet>& output = runner()->Outputs().Get("", 0).packets;
|
||||
@@ -323,13 +323,13 @@ TEST_F(GateCalculatorTest, AllowWithStateChange) {
|
||||
output_stream: "STATE_CHANGE:state_changed"
|
||||
)");
|
||||
|
||||
constexpr int64_t kTimestampValue0 = 42;
|
||||
constexpr int64 kTimestampValue0 = 42;
|
||||
RunTimeStep(kTimestampValue0, "ALLOW", false);
|
||||
constexpr int64_t kTimestampValue1 = 43;
|
||||
constexpr int64 kTimestampValue1 = 43;
|
||||
RunTimeStep(kTimestampValue1, "ALLOW", true);
|
||||
constexpr int64_t kTimestampValue2 = 44;
|
||||
constexpr int64 kTimestampValue2 = 44;
|
||||
RunTimeStep(kTimestampValue2, "ALLOW", true);
|
||||
constexpr int64_t kTimestampValue3 = 45;
|
||||
constexpr int64 kTimestampValue3 = 45;
|
||||
RunTimeStep(kTimestampValue3, "ALLOW", false);
|
||||
|
||||
const std::vector<Packet>& output =
|
||||
@@ -379,13 +379,13 @@ TEST_F(GateCalculatorTest, DisallowWithStateChange) {
|
||||
output_stream: "STATE_CHANGE:state_changed"
|
||||
)");
|
||||
|
||||
constexpr int64_t kTimestampValue0 = 42;
|
||||
constexpr int64 kTimestampValue0 = 42;
|
||||
RunTimeStep(kTimestampValue0, "DISALLOW", true);
|
||||
constexpr int64_t kTimestampValue1 = 43;
|
||||
constexpr int64 kTimestampValue1 = 43;
|
||||
RunTimeStep(kTimestampValue1, "DISALLOW", false);
|
||||
constexpr int64_t kTimestampValue2 = 44;
|
||||
constexpr int64 kTimestampValue2 = 44;
|
||||
RunTimeStep(kTimestampValue2, "DISALLOW", false);
|
||||
constexpr int64_t kTimestampValue3 = 45;
|
||||
constexpr int64 kTimestampValue3 = 45;
|
||||
RunTimeStep(kTimestampValue3, "DISALLOW", true);
|
||||
|
||||
const std::vector<Packet>& output =
|
||||
@@ -432,7 +432,7 @@ TEST_F(GateCalculatorTest, DisallowInitialNoStateTransition) {
|
||||
output_stream: "STATE_CHANGE:state_changed"
|
||||
)");
|
||||
|
||||
constexpr int64_t kTimestampValue0 = 42;
|
||||
constexpr int64 kTimestampValue0 = 42;
|
||||
RunTimeStep(kTimestampValue0, "DISALLOW", false);
|
||||
|
||||
const std::vector<Packet>& output =
|
||||
@@ -450,7 +450,7 @@ TEST_F(GateCalculatorTest, AllowInitialNoStateTransition) {
|
||||
output_stream: "STATE_CHANGE:state_changed"
|
||||
)");
|
||||
|
||||
constexpr int64_t kTimestampValue0 = 42;
|
||||
constexpr int64 kTimestampValue0 = 42;
|
||||
RunTimeStep(kTimestampValue0, "ALLOW", true);
|
||||
|
||||
const std::vector<Packet>& output =
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
namespace {
|
||||
// Reflect an integer against the lower and upper bound of an interval.
|
||||
int64_t ReflectBetween(int64_t ts, int64_t ts_min, int64_t ts_max) {
|
||||
int64 ReflectBetween(int64 ts, int64 ts_min, int64 ts_max) {
|
||||
if (ts < ts_min) return 2 * ts_min - ts - 1;
|
||||
if (ts >= ts_max) return 2 * ts_max - ts - 1;
|
||||
return ts;
|
||||
@@ -47,7 +47,7 @@ constexpr char kOptionsTag[] = "OPTIONS";
|
||||
// Returns a TimestampDiff (assuming microseconds) corresponding to the
|
||||
// given time in seconds.
|
||||
TimestampDiff TimestampDiffFromSeconds(double seconds) {
|
||||
return TimestampDiff(MathUtil::SafeRound<int64_t, double>(
|
||||
return TimestampDiff(MathUtil::SafeRound<int64, double>(
|
||||
seconds * Timestamp::kTimestampUnitsPerSecond));
|
||||
}
|
||||
} // namespace
|
||||
@@ -117,8 +117,8 @@ absl::Status PacketResamplerCalculator::Open(CalculatorContext* cc) {
|
||||
<< "The output frame rate must be smaller than "
|
||||
<< Timestamp::kTimestampUnitsPerSecond;
|
||||
|
||||
frame_time_usec_ = static_cast<int64_t>(1000000.0 / frame_rate_);
|
||||
jitter_usec_ = static_cast<int64_t>(1000000.0 * jitter_ / frame_rate_);
|
||||
frame_time_usec_ = static_cast<int64>(1000000.0 / frame_rate_);
|
||||
jitter_usec_ = static_cast<int64>(1000000.0 * jitter_ / frame_rate_);
|
||||
RET_CHECK_LE(jitter_usec_, frame_time_usec_);
|
||||
|
||||
video_header_.frame_rate = frame_rate_;
|
||||
@@ -198,18 +198,17 @@ PacketResamplerCalculator::GetSamplingStrategy(
|
||||
return absl::make_unique<JitterWithoutReflectionStrategy>(this);
|
||||
}
|
||||
|
||||
Timestamp PacketResamplerCalculator::PeriodIndexToTimestamp(
|
||||
int64_t index) const {
|
||||
Timestamp PacketResamplerCalculator::PeriodIndexToTimestamp(int64 index) const {
|
||||
CHECK_EQ(jitter_, 0.0);
|
||||
CHECK_NE(first_timestamp_, Timestamp::Unset());
|
||||
return first_timestamp_ + TimestampDiffFromSeconds(index / frame_rate_);
|
||||
}
|
||||
|
||||
int64_t PacketResamplerCalculator::TimestampToPeriodIndex(
|
||||
int64 PacketResamplerCalculator::TimestampToPeriodIndex(
|
||||
Timestamp timestamp) const {
|
||||
CHECK_EQ(jitter_, 0.0);
|
||||
CHECK_NE(first_timestamp_, Timestamp::Unset());
|
||||
return MathUtil::SafeRound<int64_t, double>(
|
||||
return MathUtil::SafeRound<int64, double>(
|
||||
(timestamp - first_timestamp_).Seconds() * frame_rate_);
|
||||
}
|
||||
|
||||
@@ -290,11 +289,11 @@ absl::Status LegacyJitterWithReflectionStrategy::Process(
|
||||
}
|
||||
|
||||
while (true) {
|
||||
const int64_t last_diff =
|
||||
const int64 last_diff =
|
||||
(next_output_timestamp_ - calculator_->last_packet_.Timestamp())
|
||||
.Value();
|
||||
RET_CHECK_GT(last_diff, 0);
|
||||
const int64_t curr_diff =
|
||||
const int64 curr_diff =
|
||||
(next_output_timestamp_ - cc->InputTimestamp()).Value();
|
||||
if (curr_diff > 0) {
|
||||
break;
|
||||
@@ -560,11 +559,11 @@ absl::Status JitterWithoutReflectionStrategy::Process(CalculatorContext* cc) {
|
||||
}
|
||||
|
||||
while (true) {
|
||||
const int64_t last_diff =
|
||||
const int64 last_diff =
|
||||
(next_output_timestamp_ - calculator_->last_packet_.Timestamp())
|
||||
.Value();
|
||||
RET_CHECK_GT(last_diff, 0);
|
||||
const int64_t curr_diff =
|
||||
const int64 curr_diff =
|
||||
(next_output_timestamp_ - cc->InputTimestamp()).Value();
|
||||
if (curr_diff > 0) {
|
||||
break;
|
||||
@@ -632,7 +631,7 @@ absl::Status NoJitterStrategy::Process(CalculatorContext* cc) {
|
||||
} else {
|
||||
// Initialize first_timestamp_ with the first packet timestamp
|
||||
// aligned to the base_timestamp_.
|
||||
int64_t first_index = MathUtil::SafeRound<int64_t, double>(
|
||||
int64 first_index = MathUtil::SafeRound<int64, double>(
|
||||
(cc->InputTimestamp() - base_timestamp_).Seconds() *
|
||||
calculator_->frame_rate_);
|
||||
calculator_->first_timestamp_ =
|
||||
@@ -647,7 +646,7 @@ absl::Status NoJitterStrategy::Process(CalculatorContext* cc) {
|
||||
}
|
||||
}
|
||||
const Timestamp received_timestamp = cc->InputTimestamp();
|
||||
const int64_t received_timestamp_idx =
|
||||
const int64 received_timestamp_idx =
|
||||
calculator_->TimestampToPeriodIndex(received_timestamp);
|
||||
// Only consider the received packet if it belongs to the current period
|
||||
// (== period_count_) or to a newer one (> period_count_).
|
||||
|
||||
@@ -97,7 +97,7 @@ class PacketThinnerCalculator : public CalculatorBase {
|
||||
cc->Inputs().Index(0).SetAny();
|
||||
cc->Outputs().Index(0).SetSameAs(&cc->Inputs().Index(0));
|
||||
if (cc->InputSidePackets().HasTag(kPeriodTag)) {
|
||||
cc->InputSidePackets().Tag(kPeriodTag).Set<int64_t>();
|
||||
cc->InputSidePackets().Tag(kPeriodTag).Set<int64>();
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
@@ -173,7 +173,7 @@ absl::Status PacketThinnerCalculator::Open(CalculatorContext* cc) {
|
||||
|
||||
if (cc->InputSidePackets().HasTag(kPeriodTag)) {
|
||||
period_ =
|
||||
TimestampDiff(cc->InputSidePackets().Tag(kPeriodTag).Get<int64_t>());
|
||||
TimestampDiff(cc->InputSidePackets().Tag(kPeriodTag).Get<int64>());
|
||||
} else {
|
||||
period_ = TimestampDiff(options.period());
|
||||
}
|
||||
@@ -300,13 +300,13 @@ Timestamp PacketThinnerCalculator::NearestSyncTimestamp(Timestamp now) const {
|
||||
|
||||
// Computation is done using int64 arithmetic. No easy way to avoid
|
||||
// since Timestamps don't support div and multiply.
|
||||
const int64_t now64 = now.Value();
|
||||
const int64_t start64 = start_time_.Value();
|
||||
const int64_t period64 = period_.Value();
|
||||
const int64 now64 = now.Value();
|
||||
const int64 start64 = start_time_.Value();
|
||||
const int64 period64 = period_.Value();
|
||||
CHECK_LE(0, period64);
|
||||
|
||||
// Round now64 to its closest interval (units of period64).
|
||||
int64_t sync64 =
|
||||
int64 sync64 =
|
||||
(now64 - start64 + period64 / 2) / period64 * period64 + start64;
|
||||
CHECK_LE(abs(now64 - sync64), period64 / 2)
|
||||
<< "start64: " << start64 << "; now64: " << now64
|
||||
|
||||
@@ -64,16 +64,16 @@ REGISTER_CALCULATOR(StringToIntCalculator);
|
||||
using StringToUintCalculator = StringToIntCalculatorTemplate<unsigned int>;
|
||||
REGISTER_CALCULATOR(StringToUintCalculator);
|
||||
|
||||
using StringToInt32Calculator = StringToIntCalculatorTemplate<int32_t>;
|
||||
using StringToInt32Calculator = StringToIntCalculatorTemplate<int32>;
|
||||
REGISTER_CALCULATOR(StringToInt32Calculator);
|
||||
|
||||
using StringToUint32Calculator = StringToIntCalculatorTemplate<uint32_t>;
|
||||
using StringToUint32Calculator = StringToIntCalculatorTemplate<uint32>;
|
||||
REGISTER_CALCULATOR(StringToUint32Calculator);
|
||||
|
||||
using StringToInt64Calculator = StringToIntCalculatorTemplate<int64_t>;
|
||||
using StringToInt64Calculator = StringToIntCalculatorTemplate<int64>;
|
||||
REGISTER_CALCULATOR(StringToInt64Calculator);
|
||||
|
||||
using StringToUint64Calculator = StringToIntCalculatorTemplate<uint64_t>;
|
||||
using StringToUint64Calculator = StringToIntCalculatorTemplate<uint64>;
|
||||
REGISTER_CALCULATOR(StringToUint64Calculator);
|
||||
|
||||
} // namespace mediapipe
|
||||
|
||||
@@ -75,16 +75,16 @@ absl::Status FindInterpolationAlgorithm(
|
||||
|
||||
void CropImageFrame(const ImageFrame& original, int col_start, int row_start,
|
||||
int crop_width, int crop_height, ImageFrame* cropped) {
|
||||
const uint8_t* src = original.PixelData();
|
||||
uint8_t* dst = cropped->MutablePixelData();
|
||||
const uint8* src = original.PixelData();
|
||||
uint8* dst = cropped->MutablePixelData();
|
||||
|
||||
int des_y = 0;
|
||||
for (int y = row_start; y < row_start + crop_height; ++y) {
|
||||
const uint8_t* src_line = src + y * original.WidthStep();
|
||||
const uint8_t* src_pixel = src_line + col_start *
|
||||
original.NumberOfChannels() *
|
||||
original.ByteDepth();
|
||||
uint8_t* dst_line = dst + des_y * cropped->WidthStep();
|
||||
const uint8* src_line = src + y * original.WidthStep();
|
||||
const uint8* src_pixel = src_line + col_start *
|
||||
original.NumberOfChannels() *
|
||||
original.ByteDepth();
|
||||
uint8* dst_line = dst + des_y * cropped->WidthStep();
|
||||
std::memcpy(
|
||||
dst_line, src_pixel,
|
||||
crop_width * cropped->NumberOfChannels() * cropped->ByteDepth());
|
||||
@@ -591,9 +591,9 @@ absl::Status ScaleImageCalculator::Process(CalculatorContext* cc) {
|
||||
const int y_size = output_width_ * output_height_;
|
||||
const int uv_size = output_width_ * output_height_ / 4;
|
||||
std::unique_ptr<uint8_t[]> yuv_data(new uint8_t[y_size + uv_size * 2]);
|
||||
uint8_t* y = yuv_data.get();
|
||||
uint8_t* u = y + y_size;
|
||||
uint8_t* v = u + uv_size;
|
||||
uint8* y = yuv_data.get();
|
||||
uint8* u = y + y_size;
|
||||
uint8* v = u + uv_size;
|
||||
RET_CHECK_EQ(0, I420Scale(yuv_image->data(0), yuv_image->stride(0),
|
||||
yuv_image->data(1), yuv_image->stride(1),
|
||||
yuv_image->data(2), yuv_image->stride(2),
|
||||
|
||||
@@ -166,7 +166,7 @@ class WarpAffineRunnerHolder<mediapipe::Image> {
|
||||
const ImageFrame image_frame(frame_ptr->Format(), frame_ptr->Width(),
|
||||
frame_ptr->Height(), frame_ptr->WidthStep(),
|
||||
const_cast<uint8_t*>(frame_ptr->PixelData()),
|
||||
[](uint8_t* data){});
|
||||
[](uint8* data){});
|
||||
ASSIGN_OR_RETURN(auto result,
|
||||
runner->Run(image_frame, matrix, size, border_mode));
|
||||
return mediapipe::Image(std::make_shared<ImageFrame>(std::move(result)));
|
||||
|
||||
@@ -101,7 +101,7 @@ void RunTest(const std::string& graph_text, const std::string& tag,
|
||||
|
||||
ImageFrame input_image(
|
||||
input.channels() == 4 ? ImageFormat::SRGBA : ImageFormat::SRGB,
|
||||
input.cols, input.rows, input.step, input.data, [](uint8_t*) {});
|
||||
input.cols, input.rows, input.step, input.data, [](uint8*) {});
|
||||
MP_ASSERT_OK(graph.AddPacketToInputStream(
|
||||
"input_image",
|
||||
MakePacket<ImageFrame>(std::move(input_image)).At(Timestamp(0))));
|
||||
|
||||
@@ -401,8 +401,8 @@ cc_library_with_tflite(
|
||||
hdrs = ["inference_calculator.h"],
|
||||
tflite_deps = [
|
||||
"//mediapipe/util/tflite:tflite_model_loader",
|
||||
"@org_tensorflow//tensorflow/lite:framework_stable",
|
||||
"@org_tensorflow//tensorflow/lite/kernels:builtin_ops",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:framework_stable",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:builtin_ops",
|
||||
],
|
||||
deps = [
|
||||
":inference_calculator_cc_proto",
|
||||
@@ -506,7 +506,7 @@ cc_library_with_tflite(
|
||||
name = "tflite_delegate_ptr",
|
||||
hdrs = ["tflite_delegate_ptr.h"],
|
||||
tflite_deps = [
|
||||
"@org_tensorflow//tensorflow/lite/c:c_api_types",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:c_api_types",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -517,8 +517,8 @@ cc_library_with_tflite(
|
||||
tflite_deps = [
|
||||
":tflite_delegate_ptr",
|
||||
"//mediapipe/util/tflite:tflite_model_loader",
|
||||
"@org_tensorflow//tensorflow/lite:framework_stable",
|
||||
"@org_tensorflow//tensorflow/lite/c:c_api_types",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:c_api_types",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:framework_stable",
|
||||
],
|
||||
deps = [
|
||||
":inference_runner",
|
||||
@@ -546,8 +546,8 @@ cc_library(
|
||||
"@com_google_absl//absl/memory",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/status:statusor",
|
||||
"@org_tensorflow//tensorflow/lite:framework_stable",
|
||||
"@org_tensorflow//tensorflow/lite/c:c_api_types",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:c_api_types",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:framework_stable",
|
||||
"@org_tensorflow//tensorflow/lite/delegates/xnnpack:xnnpack_delegate",
|
||||
] + select({
|
||||
"//conditions:default": [],
|
||||
|
||||
@@ -94,8 +94,8 @@ InferenceCalculator::GetOpResolverAsPacket(CalculatorContext* cc) {
|
||||
return kSideInCustomOpResolver(cc).As<tflite::OpResolver>();
|
||||
}
|
||||
return PacketAdopting<tflite::OpResolver>(
|
||||
std::make_unique<
|
||||
tflite::ops::builtin::BuiltinOpResolverWithoutDefaultDelegates>());
|
||||
std::make_unique<tflite_shims::ops::builtin::
|
||||
BuiltinOpResolverWithoutDefaultDelegates>());
|
||||
}
|
||||
|
||||
} // namespace api2
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "mediapipe/framework/formats/tensor.h"
|
||||
#include "mediapipe/util/tflite/tflite_model_loader.h"
|
||||
#include "tensorflow/lite/core/api/op_resolver.h"
|
||||
#include "tensorflow/lite/kernels/register.h"
|
||||
#include "tensorflow/lite/core/shims/cc/kernels/register.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace api2 {
|
||||
@@ -97,8 +97,8 @@ class InferenceCalculator : public NodeIntf {
|
||||
// Deprecated. Prefers to use "OP_RESOLVER" input side packet instead.
|
||||
// TODO: Removes the "CUSTOM_OP_RESOLVER" side input after the
|
||||
// migration.
|
||||
static constexpr SideInput<tflite::ops::builtin::BuiltinOpResolver>::Optional
|
||||
kSideInCustomOpResolver{"CUSTOM_OP_RESOLVER"};
|
||||
static constexpr SideInput<tflite_shims::ops::builtin::BuiltinOpResolver>::
|
||||
Optional kSideInCustomOpResolver{"CUSTOM_OP_RESOLVER"};
|
||||
static constexpr SideInput<tflite::OpResolver>::Optional kSideInOpResolver{
|
||||
"OP_RESOLVER"};
|
||||
static constexpr SideInput<TfLiteModelPtr>::Optional kSideInModel{"MODEL"};
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "mediapipe/calculators/tensor/inference_calculator_utils.h"
|
||||
#include "mediapipe/calculators/tensor/inference_interpreter_delegate_runner.h"
|
||||
#include "mediapipe/calculators/tensor/inference_runner.h"
|
||||
#include "tensorflow/lite/interpreter.h"
|
||||
#include "tensorflow/lite/core/shims/cc/interpreter.h"
|
||||
#if defined(MEDIAPIPE_ANDROID)
|
||||
#include "tensorflow/lite/delegates/nnapi/nnapi_delegate.h"
|
||||
#endif // ANDROID
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
#include "mediapipe/framework/formats/tensor.h"
|
||||
#include "mediapipe/framework/mediapipe_profiling.h"
|
||||
#include "mediapipe/framework/port/ret_check.h"
|
||||
#include "tensorflow/lite/c/c_api_types.h"
|
||||
#include "tensorflow/lite/interpreter.h"
|
||||
#include "tensorflow/lite/interpreter_builder.h"
|
||||
#include "tensorflow/lite/core/shims/c/c_api_types.h"
|
||||
#include "tensorflow/lite/core/shims/cc/interpreter.h"
|
||||
#include "tensorflow/lite/core/shims/cc/interpreter_builder.h"
|
||||
#include "tensorflow/lite/string_util.h"
|
||||
|
||||
#define PERFETTO_TRACK_EVENT_NAMESPACE mediapipe
|
||||
@@ -33,8 +33,8 @@ namespace mediapipe {
|
||||
|
||||
namespace {
|
||||
|
||||
using Interpreter = ::tflite::Interpreter;
|
||||
using InterpreterBuilder = ::tflite::InterpreterBuilder;
|
||||
using Interpreter = ::tflite_shims::Interpreter;
|
||||
using InterpreterBuilder = ::tflite_shims::InterpreterBuilder;
|
||||
|
||||
template <typename T>
|
||||
void CopyTensorBufferToInterpreter(const Tensor& input_tensor,
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
#include "mediapipe/calculators/tensor/tflite_delegate_ptr.h"
|
||||
#include "mediapipe/framework/api2/packet.h"
|
||||
#include "mediapipe/util/tflite/tflite_model_loader.h"
|
||||
#include "tensorflow/lite/c/c_api_types.h"
|
||||
#include "tensorflow/lite/core/api/op_resolver.h"
|
||||
#include "tensorflow/lite/core/shims/c/c_api_types.h"
|
||||
|
||||
namespace mediapipe {
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include "tensorflow/lite/c/c_api_types.h"
|
||||
#include "tensorflow/lite/core/shims/c/c_api_types.h"
|
||||
|
||||
namespace mediapipe {
|
||||
|
||||
|
||||
@@ -131,9 +131,9 @@ class FixedSizeInputStreamHandler : public DefaultInputStreamHandler {
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(erase_mutex_) {
|
||||
// Record the most recent first kept timestamp on any stream.
|
||||
for (const auto& stream : input_stream_managers_) {
|
||||
int32_t queue_size = (stream->QueueSize() >= trigger_queue_size_)
|
||||
? target_queue_size_
|
||||
: trigger_queue_size_ - 1;
|
||||
int32 queue_size = (stream->QueueSize() >= trigger_queue_size_)
|
||||
? target_queue_size_
|
||||
: trigger_queue_size_ - 1;
|
||||
if (stream->QueueSize() > queue_size) {
|
||||
kept_timestamp_ = std::max(
|
||||
kept_timestamp_, stream->GetMinTimestampAmongNLatest(queue_size + 1)
|
||||
@@ -214,8 +214,8 @@ class FixedSizeInputStreamHandler : public DefaultInputStreamHandler {
|
||||
}
|
||||
|
||||
private:
|
||||
int32_t trigger_queue_size_;
|
||||
int32_t target_queue_size_;
|
||||
int32 trigger_queue_size_;
|
||||
int32 target_queue_size_;
|
||||
bool fixed_min_size_;
|
||||
// Indicates that GetNodeReadiness has returned kReadyForProcess once, and
|
||||
// the corresponding call to FillInputSet has not yet completed.
|
||||
|
||||
@@ -67,14 +67,53 @@ absl::Status GlContext::CreateContextInternal(
|
||||
// TODO: Investigate this option in more detail, esp. on Safari.
|
||||
attrs.preserveDrawingBuffer = 0;
|
||||
|
||||
// Quick patch for -s DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR so it also
|
||||
// looks for our #canvas target in Module.canvas, where we expect it to be.
|
||||
// -s OFFSCREENCANVAS_SUPPORT=1 will no longer work with this under the new
|
||||
// event target behavior, but it was never supposed to be tapping into our
|
||||
// canvas anyways. See b/278155946 for more background.
|
||||
EM_ASM({ specialHTMLTargets["#canvas"] = Module.canvas; });
|
||||
// Since the Emscripten canvas target finding function is visible from here,
|
||||
// we hijack findCanvasEventTarget directly for enforcing old Module.canvas
|
||||
// behavior if the user desires, falling back to the new DOM element CSS
|
||||
// selector behavior next if that is specified, and finally just allowing the
|
||||
// lookup to proceed on a null target.
|
||||
// TODO: Ensure this works with all options (in particular,
|
||||
// multithreading options, like the special-case combination of USE_PTHREADS
|
||||
// and OFFSCREEN_FRAMEBUFFER)
|
||||
// clang-format off
|
||||
EM_ASM(
|
||||
let init_once = true;
|
||||
if (init_once) {
|
||||
const cachedFindCanvasEventTarget = findCanvasEventTarget;
|
||||
|
||||
if (typeof cachedFindCanvasEventTarget !== 'function') {
|
||||
if (typeof console !== 'undefined') {
|
||||
console.error('Expected Emscripten global function '
|
||||
+ '"findCanvasEventTarget" not found. WebGL context creation '
|
||||
+ 'may fail.');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
findCanvasEventTarget = function(target) {
|
||||
if (target == 0) {
|
||||
if (Module && Module.canvas) {
|
||||
return Module.canvas;
|
||||
} else if (Module && Module.canvasCssSelector) {
|
||||
return cachedFindCanvasEventTarget(Module.canvasCssSelector);
|
||||
}
|
||||
if (typeof console !== 'undefined') {
|
||||
console.warn('Module properties canvas and canvasCssSelector not ' +
|
||||
'found during WebGL context creation.');
|
||||
}
|
||||
}
|
||||
// We still go through with the find attempt, although for most use
|
||||
// cases it will not succeed, just in case the user does want to fall-
|
||||
// back.
|
||||
return cachedFindCanvasEventTarget(target);
|
||||
}; // NOLINT: Necessary semicolon.
|
||||
init_once = false;
|
||||
}
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context_handle =
|
||||
emscripten_webgl_create_context("#canvas", &attrs);
|
||||
emscripten_webgl_create_context(nullptr, &attrs);
|
||||
|
||||
// Check for failure
|
||||
if (context_handle <= 0) {
|
||||
|
||||
@@ -167,7 +167,7 @@ GpuBufferStorageYuvImage::GpuBufferStorageYuvImage(int width, int height,
|
||||
GpuBufferFormat format) {
|
||||
libyuv::FourCC fourcc = FourCCForGpuBufferFormat(format);
|
||||
int y_stride = std::ceil(1.0f * width / kDefaultDataAligment);
|
||||
auto y_data = std::make_unique<uint8_t[]>(y_stride * height);
|
||||
auto y_data = std::make_unique<uint8[]>(y_stride * height);
|
||||
switch (fourcc) {
|
||||
case libyuv::FOURCC_NV12:
|
||||
case libyuv::FOURCC_NV21: {
|
||||
@@ -175,7 +175,7 @@ GpuBufferStorageYuvImage::GpuBufferStorageYuvImage(int width, int height,
|
||||
int uv_width = 2 * std::ceil(0.5f * width);
|
||||
int uv_height = std::ceil(0.5f * height);
|
||||
int uv_stride = std::ceil(1.0f * uv_width / kDefaultDataAligment);
|
||||
auto uv_data = std::make_unique<uint8_t[]>(uv_stride * uv_height);
|
||||
auto uv_data = std::make_unique<uint8[]>(uv_stride * uv_height);
|
||||
yuv_image_ = std::make_shared<YUVImage>(
|
||||
fourcc, std::move(y_data), y_stride, std::move(uv_data), uv_stride,
|
||||
nullptr, 0, width, height);
|
||||
@@ -187,8 +187,8 @@ GpuBufferStorageYuvImage::GpuBufferStorageYuvImage(int width, int height,
|
||||
int uv_width = std::ceil(0.5f * width);
|
||||
int uv_height = std::ceil(0.5f * height);
|
||||
int uv_stride = std::ceil(1.0f * uv_width / kDefaultDataAligment);
|
||||
auto u_data = std::make_unique<uint8_t[]>(uv_stride * uv_height);
|
||||
auto v_data = std::make_unique<uint8_t[]>(uv_stride * uv_height);
|
||||
auto u_data = std::make_unique<uint8[]>(uv_stride * uv_height);
|
||||
auto v_data = std::make_unique<uint8[]>(uv_stride * uv_height);
|
||||
yuv_image_ = std::make_shared<YUVImage>(
|
||||
fourcc, std::move(y_data), y_stride, std::move(u_data), uv_stride,
|
||||
std::move(v_data), uv_stride, width, height);
|
||||
|
||||
@@ -31,8 +31,7 @@
|
||||
namespace mediapipe {
|
||||
namespace {
|
||||
|
||||
void FillImageFrameRGBA(ImageFrame& image, uint8_t r, uint8_t g, uint8_t b,
|
||||
uint8_t a) {
|
||||
void FillImageFrameRGBA(ImageFrame& image, uint8 r, uint8 g, uint8 b, uint8 a) {
|
||||
auto* data = image.MutablePixelData();
|
||||
for (int y = 0; y < image.Height(); ++y) {
|
||||
auto* row = data + image.WidthStep() * y;
|
||||
|
||||
+2
-2
@@ -70,7 +70,7 @@ class Lift2DFrameAnnotationTo3DCalculator : public CalculatorBase {
|
||||
// In a single MediaPipe session, the IDs are unique.
|
||||
// Also assign timestamp for the FrameAnnotation to be the input packet
|
||||
// timestamp.
|
||||
void AssignObjectIdAndTimestamp(int64_t timestamp_us,
|
||||
void AssignObjectIdAndTimestamp(int64 timestamp_us,
|
||||
FrameAnnotation* annotation);
|
||||
std::unique_ptr<Decoder> decoder_;
|
||||
Lift2DFrameAnnotationTo3DCalculatorOptions options_;
|
||||
@@ -159,7 +159,7 @@ absl::Status Lift2DFrameAnnotationTo3DCalculator::LoadOptions(
|
||||
}
|
||||
|
||||
void Lift2DFrameAnnotationTo3DCalculator::AssignObjectIdAndTimestamp(
|
||||
int64_t timestamp_us, FrameAnnotation* annotation) {
|
||||
int64 timestamp_us, FrameAnnotation* annotation) {
|
||||
for (auto& ann : *annotation->mutable_annotations()) {
|
||||
ann.set_object_id(GetNextObjectId());
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/common.h"
|
||||
#include "mediapipe/tasks/cc/components/containers/category.h"
|
||||
#include "mediapipe/tasks/cc/components/containers/classification_result.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -157,7 +157,7 @@ void CheckStreamingModeResults(std::vector<AudioClassifierResult> outputs) {
|
||||
}
|
||||
}
|
||||
|
||||
class CreateFromOptionsTest : public tflite::testing::Test {};
|
||||
class CreateFromOptionsTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(CreateFromOptionsTest, SucceedsForModelWithMetadata) {
|
||||
auto options = std::make_unique<AudioClassifierOptions>();
|
||||
@@ -270,7 +270,7 @@ TEST_F(CreateFromOptionsTest, FailsWithUnnecessaryCallback) {
|
||||
MediaPipeTasksStatus::kInvalidTaskGraphConfigError))));
|
||||
}
|
||||
|
||||
class ClassifyTest : public tflite::testing::Test {};
|
||||
class ClassifyTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(ClassifyTest, Succeeds) {
|
||||
auto audio_buffer = GetAudioData(k16kTestWavFilename);
|
||||
@@ -467,7 +467,7 @@ TEST_F(ClassifyTest, SucceedsWithCategoryDenylist) {
|
||||
}
|
||||
}
|
||||
|
||||
class ClassifyAsyncTest : public tflite::testing::Test {};
|
||||
class ClassifyAsyncTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(ClassifyAsyncTest, Succeeds) {
|
||||
constexpr int kSampleRateHz = 48000;
|
||||
|
||||
@@ -36,7 +36,7 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/audio/utils/test_utils.h"
|
||||
#include "mediapipe/tasks/cc/common.h"
|
||||
#include "mediapipe/tasks/cc/components/containers/embedding_result.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -66,7 +66,7 @@ Matrix GetAudioData(absl::string_view filename) {
|
||||
return matrix_mapping.matrix();
|
||||
}
|
||||
|
||||
class CreateFromOptionsTest : public tflite::testing::Test {};
|
||||
class CreateFromOptionsTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(CreateFromOptionsTest, FailsWithMissingModel) {
|
||||
auto audio_embedder =
|
||||
@@ -124,7 +124,7 @@ TEST_F(CreateFromOptionsTest, FailsWithMissingCallbackInAudioStreamMode) {
|
||||
MediaPipeTasksStatus::kInvalidTaskGraphConfigError))));
|
||||
}
|
||||
|
||||
class EmbedTest : public tflite::testing::Test {};
|
||||
class EmbedTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(EmbedTest, SucceedsWithSilentAudio) {
|
||||
auto options = std::make_unique<AudioEmbedderOptions>();
|
||||
@@ -187,7 +187,7 @@ TEST_F(EmbedTest, SucceedsWithDifferentAudios) {
|
||||
MP_EXPECT_OK(audio_embedder->Close());
|
||||
}
|
||||
|
||||
class EmbedAsyncTest : public tflite::testing::Test {
|
||||
class EmbedAsyncTest : public tflite_shims::testing::Test {
|
||||
protected:
|
||||
void RunAudioEmbedderInStreamMode(std::string audio_file_name,
|
||||
int sample_rate_hz,
|
||||
|
||||
@@ -47,7 +47,7 @@ cc_test_with_tflite(
|
||||
data = ["//mediapipe/tasks/testdata/audio:test_models"],
|
||||
tflite_deps = [
|
||||
"//mediapipe/tasks/cc/core:model_resources",
|
||||
"@org_tensorflow//tensorflow/lite:test_util",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:cc_shims_test_util",
|
||||
],
|
||||
deps = [
|
||||
":audio_tensor_specs",
|
||||
|
||||
@@ -34,7 +34,7 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/core/model_resources.h"
|
||||
#include "mediapipe/tasks/cc/core/proto/external_file.pb.h"
|
||||
#include "mediapipe/tasks/cc/metadata/metadata_extractor.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -52,7 +52,7 @@ constexpr char kModelWithMetadata[] =
|
||||
"yamnet_audio_classifier_with_metadata.tflite";
|
||||
constexpr char kModelWithoutMetadata[] = "model_without_metadata.tflite";
|
||||
|
||||
class AudioTensorSpecsTest : public tflite::testing::Test {};
|
||||
class AudioTensorSpecsTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(AudioTensorSpecsTest,
|
||||
BuildInputAudioTensorSpecsWithoutMetdataOptionsFails) {
|
||||
|
||||
@@ -63,7 +63,7 @@ cc_test(
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/status:statusor",
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
"@org_tensorflow//tensorflow/lite:test_util",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:cc_shims_test_util",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -232,6 +232,6 @@ cc_test(
|
||||
"//mediapipe/tasks/cc/components/containers/proto:embeddings_cc_proto",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/status:statusor",
|
||||
"@org_tensorflow//tensorflow/lite:test_util",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:cc_shims_test_util",
|
||||
],
|
||||
)
|
||||
|
||||
+3
-2
@@ -33,7 +33,7 @@ limitations under the License.
|
||||
#include "mediapipe/framework/timestamp.h"
|
||||
#include "mediapipe/tasks/cc/components/calculators/classification_aggregation_calculator.pb.h"
|
||||
#include "mediapipe/tasks/cc/components/containers/proto/classifications.pb.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace {
|
||||
@@ -66,7 +66,8 @@ ClassificationList MakeClassificationList(int class_index) {
|
||||
class_index));
|
||||
}
|
||||
|
||||
class ClassificationAggregationCalculatorTest : public tflite::testing::Test {
|
||||
class ClassificationAggregationCalculatorTest
|
||||
: public tflite_shims::testing::Test {
|
||||
protected:
|
||||
absl::StatusOr<OutputStreamPoller> BuildGraph(
|
||||
bool connect_timestamps = false) {
|
||||
|
||||
@@ -31,7 +31,7 @@ limitations under the License.
|
||||
#include "mediapipe/framework/port/status_matchers.h"
|
||||
#include "mediapipe/framework/timestamp.h"
|
||||
#include "mediapipe/tasks/cc/components/containers/proto/embeddings.pb.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace {
|
||||
@@ -52,7 +52,7 @@ constexpr char kTimestampsName[] = "timestamps_in";
|
||||
constexpr char kTimestampedEmbeddingsTag[] = "TIMESTAMPED_EMBEDDINGS";
|
||||
constexpr char kTimestampedEmbeddingsName[] = "timestamped_embeddings_out";
|
||||
|
||||
class EmbeddingAggregationCalculatorTest : public tflite::testing::Test {
|
||||
class EmbeddingAggregationCalculatorTest : public tflite_shims::testing::Test {
|
||||
protected:
|
||||
absl::StatusOr<OutputStreamPoller> BuildGraph(bool connect_timestamps) {
|
||||
Graph graph;
|
||||
|
||||
+3
-3
@@ -49,7 +49,7 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/core/model_resources.h"
|
||||
#include "mediapipe/tasks/cc/core/proto/external_file.pb.h"
|
||||
#include "mediapipe/util/label_map.pb.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -101,7 +101,7 @@ absl::StatusOr<std::unique_ptr<ModelResources>> CreateModelResourcesForModel(
|
||||
std::move(external_file));
|
||||
}
|
||||
|
||||
class ConfigureTest : public tflite::testing::Test {};
|
||||
class ConfigureTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(ConfigureTest, FailsWithInvalidMaxResults) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(
|
||||
@@ -417,7 +417,7 @@ TEST_F(ConfigureTest, SucceedsWithMultipleHeads) {
|
||||
)pb")));
|
||||
}
|
||||
|
||||
class PostprocessingTest : public tflite::testing::Test {
|
||||
class PostprocessingTest : public tflite_shims::testing::Test {
|
||||
protected:
|
||||
absl::StatusOr<OutputStreamPoller> BuildGraph(
|
||||
absl::string_view model_name, const proto::ClassifierOptions& options,
|
||||
|
||||
@@ -39,7 +39,7 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/components/processors/proto/embedding_postprocessing_graph_options.pb.h"
|
||||
#include "mediapipe/tasks/cc/core/model_resources.h"
|
||||
#include "mediapipe/tasks/cc/core/proto/external_file.pb.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -86,7 +86,7 @@ absl::StatusOr<std::unique_ptr<ModelResources>> CreateModelResourcesForModel(
|
||||
std::move(external_file));
|
||||
}
|
||||
|
||||
class ConfigureTest : public tflite::testing::Test {};
|
||||
class ConfigureTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(ConfigureTest, SucceedsWithQuantizedModelWithMetadata) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(
|
||||
@@ -153,7 +153,7 @@ TEST_F(ConfigureTest, SucceedsWithFloatModelWithMetadata) {
|
||||
has_quantized_outputs: false)pb")));
|
||||
}
|
||||
|
||||
class PostprocessingTest : public tflite::testing::Test {
|
||||
class PostprocessingTest : public tflite_shims::testing::Test {
|
||||
protected:
|
||||
absl::StatusOr<OutputStreamPoller> BuildGraph(
|
||||
absl::string_view model_name, const proto::EmbedderOptions& options,
|
||||
|
||||
@@ -37,7 +37,7 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/core/proto/external_file.pb.h"
|
||||
#include "mediapipe/tasks/cc/core/task_runner.h"
|
||||
#include "mediapipe/tasks/cc/vision/utils/image_utils.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -125,7 +125,7 @@ absl::StatusOr<std::unique_ptr<TaskRunner>> CreateTaskRunner(
|
||||
return TaskRunner::Create(graph.GetConfig());
|
||||
}
|
||||
|
||||
class ConfigureTest : public tflite::testing::Test {};
|
||||
class ConfigureTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(ConfigureTest, SucceedsWithQuantizedModelWithMetadata) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(
|
||||
|
||||
@@ -128,9 +128,9 @@ cc_library_with_tflite(
|
||||
srcs = ["model_resources.cc"],
|
||||
hdrs = ["model_resources.h"],
|
||||
tflite_deps = [
|
||||
"@org_tensorflow//tensorflow/lite:framework_stable",
|
||||
"@org_tensorflow//tensorflow/lite/kernels:builtin_ops",
|
||||
"@org_tensorflow//tensorflow/lite/tools:verifier",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:builtin_ops",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:framework_stable",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:verifier",
|
||||
],
|
||||
deps = [
|
||||
":external_file_handler",
|
||||
@@ -159,9 +159,9 @@ cc_test_with_tflite(
|
||||
],
|
||||
tflite_deps = [
|
||||
":model_resources",
|
||||
"@org_tensorflow//tensorflow/lite:framework_stable",
|
||||
"@org_tensorflow//tensorflow/lite:test_util",
|
||||
"@org_tensorflow//tensorflow/lite/kernels:builtin_ops",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:cc_shims_test_util",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:builtin_ops",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:framework_stable",
|
||||
],
|
||||
deps = [
|
||||
":utils",
|
||||
@@ -186,7 +186,7 @@ cc_library_with_tflite(
|
||||
hdrs = ["model_resources_cache.h"],
|
||||
tflite_deps = [
|
||||
":model_resources",
|
||||
"@org_tensorflow//tensorflow/lite/kernels:builtin_ops",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:builtin_ops",
|
||||
],
|
||||
deps = [
|
||||
":model_asset_bundle_resources",
|
||||
@@ -233,7 +233,7 @@ cc_test_with_tflite(
|
||||
":model_resources",
|
||||
":model_resources_cache",
|
||||
":model_resources_calculator",
|
||||
"@org_tensorflow//tensorflow/lite:test_util",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:cc_shims_test_util",
|
||||
],
|
||||
deps = [
|
||||
"//mediapipe/framework/port:gtest_main",
|
||||
@@ -284,7 +284,7 @@ cc_test_with_tflite(
|
||||
":task_runner",
|
||||
":model_resources",
|
||||
":model_resources_cache",
|
||||
"@org_tensorflow//tensorflow/lite:test_util",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:cc_shims_test_util",
|
||||
],
|
||||
deps = [
|
||||
"//mediapipe/calculators/core:pass_through_calculator",
|
||||
|
||||
@@ -37,8 +37,8 @@ limitations under the License.
|
||||
#include "mediapipe/util/tflite/error_reporter.h"
|
||||
#include "tensorflow/lite/core/api/error_reporter.h"
|
||||
#include "tensorflow/lite/core/api/op_resolver.h"
|
||||
#include "tensorflow/lite/model_builder.h"
|
||||
#include "tensorflow/lite/tools/verifier.h"
|
||||
#include "tensorflow/lite/core/shims/cc/model_builder.h"
|
||||
#include "tensorflow/lite/core/shims/cc/tools/verifier.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -52,7 +52,7 @@ using ::mediapipe::tasks::metadata::ModelMetadataExtractor;
|
||||
|
||||
bool ModelResources::Verifier::Verify(const char* data, int length,
|
||||
tflite::ErrorReporter* reporter) {
|
||||
return tflite::Verify(data, length, reporter);
|
||||
return tflite_shims::Verify(data, length, reporter);
|
||||
}
|
||||
|
||||
ModelResources::ModelResources(const std::string& tag,
|
||||
@@ -124,7 +124,7 @@ absl::Status ModelResources::BuildModelFromExternalFileProto() {
|
||||
// and that it uses only operators that are supported by the OpResolver
|
||||
// that was passed to the ModelResources constructor, and then builds
|
||||
// the model from the buffer.
|
||||
auto model = tflite::FlatBufferModel::VerifyAndBuildFromBuffer(
|
||||
auto model = tflite_shims::FlatBufferModel::VerifyAndBuildFromBuffer(
|
||||
buffer_data, buffer_size, &verifier_, &error_reporter_);
|
||||
if (model == nullptr) {
|
||||
static constexpr char kInvalidFlatbufferMessage[] =
|
||||
@@ -151,7 +151,8 @@ absl::Status ModelResources::BuildModelFromExternalFileProto() {
|
||||
}
|
||||
|
||||
model_packet_ = MakePacket<ModelPtr>(
|
||||
model.release(), [](tflite::FlatBufferModel* model) { delete model; });
|
||||
model.release(),
|
||||
[](tflite_shims::FlatBufferModel* model) { delete model; });
|
||||
ASSIGN_OR_RETURN(auto model_metadata_extractor,
|
||||
metadata::ModelMetadataExtractor::CreateFromModelBuffer(
|
||||
buffer_data, buffer_size));
|
||||
|
||||
@@ -32,10 +32,10 @@ limitations under the License.
|
||||
#include "mediapipe/util/tflite/error_reporter.h"
|
||||
#include "tensorflow/lite/core/api/error_reporter.h"
|
||||
#include "tensorflow/lite/core/api/op_resolver.h"
|
||||
#include "tensorflow/lite/kernels/register.h"
|
||||
#include "tensorflow/lite/model.h"
|
||||
#include "tensorflow/lite/model_builder.h"
|
||||
#include "tensorflow/lite/tools/verifier.h"
|
||||
#include "tensorflow/lite/core/shims/cc/kernels/register.h"
|
||||
#include "tensorflow/lite/core/shims/cc/model.h"
|
||||
#include "tensorflow/lite/core/shims/cc/model_builder.h"
|
||||
#include "tensorflow/lite/core/shims/cc/tools/verifier.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -51,8 +51,8 @@ class ModelResources {
|
||||
public:
|
||||
// Represents a TfLite model as a FlatBuffer.
|
||||
using ModelPtr =
|
||||
std::unique_ptr<tflite::FlatBufferModel,
|
||||
std::function<void(tflite::FlatBufferModel*)>>;
|
||||
std::unique_ptr<tflite_shims::FlatBufferModel,
|
||||
std::function<void(tflite_shims::FlatBufferModel*)>>;
|
||||
|
||||
// Takes the ownership of the provided ExternalFile proto and creates
|
||||
// ModelResources from the proto and an op resolver object. A non-empty tag
|
||||
@@ -61,7 +61,7 @@ class ModelResources {
|
||||
static absl::StatusOr<std::unique_ptr<ModelResources>> Create(
|
||||
const std::string& tag, std::unique_ptr<proto::ExternalFile> model_file,
|
||||
std::unique_ptr<tflite::OpResolver> op_resolver =
|
||||
absl::make_unique<tflite::ops::builtin::BuiltinOpResolver>());
|
||||
absl::make_unique<tflite_shims::ops::builtin::BuiltinOpResolver>());
|
||||
|
||||
// Takes the ownership of the provided ExternalFile proto and creates
|
||||
// ModelResources from the proto and an op resolver mediapipe packet. A
|
||||
|
||||
@@ -30,7 +30,7 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/core/proto/model_resources_calculator.pb.h"
|
||||
#include "mediapipe/tasks/cc/metadata/metadata_extractor.h"
|
||||
#include "tensorflow/lite/core/api/op_resolver.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -124,7 +124,7 @@ void RunGraphWithGraphService(std::unique_ptr<ModelResources> model_resources,
|
||||
|
||||
} // namespace
|
||||
|
||||
class ModelResourcesCalculatorTest : public tflite::testing::Test {};
|
||||
class ModelResourcesCalculatorTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(ModelResourcesCalculatorTest, MissingCalculatorOptions) {
|
||||
auto graph_config = ParseTextProtoOrDie<CalculatorGraphConfig>(
|
||||
|
||||
@@ -38,9 +38,9 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/metadata/metadata_extractor.h"
|
||||
#include "tensorflow/lite/c/common.h"
|
||||
#include "tensorflow/lite/core/api/op_resolver.h"
|
||||
#include "tensorflow/lite/kernels/builtin_op_kernels.h"
|
||||
#include "tensorflow/lite/core/shims/cc/kernels/builtin_op_kernels.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
#include "tensorflow/lite/mutable_op_resolver.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
|
||||
namespace tflite {
|
||||
namespace ops {
|
||||
@@ -116,7 +116,7 @@ void CheckModelResourcesPackets(const ModelResources* model_resources) {
|
||||
|
||||
} // namespace
|
||||
|
||||
class ModelResourcesTest : public tflite::testing::Test {};
|
||||
class ModelResourcesTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(ModelResourcesTest, CreateFromBinaryContent) {
|
||||
auto model_file = std::make_unique<proto::ExternalFile>();
|
||||
@@ -211,7 +211,7 @@ TEST_F(ModelResourcesTest, CreateSuccessWithCustomOpsFromFile) {
|
||||
static constexpr char kCustomOpName[] = "MY_CUSTOM_OP";
|
||||
tflite::MutableOpResolver resolver;
|
||||
resolver.AddBuiltin(::tflite::BuiltinOperator_ADD,
|
||||
::tflite::ops::builtin::Register_ADD());
|
||||
::tflite_shims::ops::builtin::Register_ADD());
|
||||
resolver.AddCustom(kCustomOpName,
|
||||
::tflite::ops::custom::Register_MY_CUSTOM_OP());
|
||||
|
||||
@@ -275,7 +275,7 @@ TEST_F(ModelResourcesTest, CreateSuccessWithCustomOpsPacket) {
|
||||
static constexpr char kCustomOpName[] = "MY_CUSTOM_OP";
|
||||
tflite::MutableOpResolver resolver;
|
||||
resolver.AddBuiltin(::tflite::BuiltinOperator_ADD,
|
||||
::tflite::ops::builtin::Register_ADD());
|
||||
::tflite_shims::ops::builtin::Register_ADD());
|
||||
resolver.AddCustom(kCustomOpName,
|
||||
::tflite::ops::custom::Register_MY_CUSTOM_OP());
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ limitations under the License.
|
||||
#include "mediapipe/framework/port/status_matchers.h"
|
||||
#include "mediapipe/tasks/cc/core/model_resources.h"
|
||||
#include "mediapipe/tasks/cc/core/proto/external_file.pb.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -112,7 +112,7 @@ CalculatorGraphConfig GetModelSidePacketsToStreamPacketsGraphConfig(
|
||||
|
||||
} // namespace
|
||||
|
||||
class TaskRunnerTest : public tflite::testing::Test {};
|
||||
class TaskRunnerTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(TaskRunnerTest, ConfigWithNoOutputStream) {
|
||||
CalculatorGraphConfig proto = ParseTextProtoOrDie<CalculatorGraphConfig>(R"pb(
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
# Copyright 2023 The MediaPipe Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
load("@flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")
|
||||
|
||||
package(default_visibility = ["//mediapipe/tasks:internal"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
filegroup(
|
||||
name = "testdata",
|
||||
srcs = glob([
|
||||
"testdata/**",
|
||||
]),
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "config_fbs",
|
||||
srcs = ["config.fbs"],
|
||||
)
|
||||
|
||||
flatbuffer_cc_library(
|
||||
name = "config",
|
||||
srcs = [
|
||||
"config.fbs",
|
||||
],
|
||||
)
|
||||
|
||||
flatbuffer_cc_library(
|
||||
name = "encoder_config",
|
||||
srcs = [
|
||||
"encoder_config.fbs",
|
||||
],
|
||||
includes = [":config_fbs"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "utils",
|
||||
hdrs = [
|
||||
"utils.h",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "double_array_trie",
|
||||
hdrs = [
|
||||
"double_array_trie.h",
|
||||
],
|
||||
deps = [
|
||||
":config",
|
||||
":utils",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "double_array_trie_builder",
|
||||
srcs = [
|
||||
"double_array_trie_builder.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"double_array_trie_builder.h",
|
||||
],
|
||||
deps = ["@darts_clone"],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "double_array_trie_test",
|
||||
srcs = [
|
||||
"double_array_trie_test.cc",
|
||||
],
|
||||
deps = [
|
||||
":double_array_trie",
|
||||
":double_array_trie_builder",
|
||||
":encoder_config",
|
||||
":utils",
|
||||
"//mediapipe/framework/port:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "sentencepiece_constants",
|
||||
hdrs = ["sentencepiece_constants.h"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "model_converter",
|
||||
srcs = [
|
||||
"model_converter.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"model_converter.h",
|
||||
],
|
||||
deps = [
|
||||
":config",
|
||||
":double_array_trie_builder",
|
||||
":encoder_config",
|
||||
":sentencepiece_constants",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/status:statusor",
|
||||
"@com_google_sentencepiece//src:sentencepiece_model_cc_proto",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "optimized_encoder",
|
||||
srcs = [
|
||||
"optimized_encoder.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"optimized_encoder.h",
|
||||
],
|
||||
deps = [
|
||||
":double_array_trie",
|
||||
":encoder_config",
|
||||
":utils",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "optimized_encoder_test",
|
||||
srcs = [
|
||||
"optimized_encoder_test.cc",
|
||||
],
|
||||
data = [
|
||||
":testdata",
|
||||
],
|
||||
deps = [
|
||||
":double_array_trie_builder",
|
||||
":encoder_config",
|
||||
":model_converter",
|
||||
":optimized_encoder",
|
||||
"//mediapipe/framework/deps:file_path",
|
||||
"//mediapipe/framework/port:gtest_main",
|
||||
"@com_google_absl//absl/flags:flag",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
"@com_google_sentencepiece//src:sentencepiece_cc_proto",
|
||||
"@com_google_sentencepiece//src:sentencepiece_processor",
|
||||
"@org_tensorflow//tensorflow/core:lib",
|
||||
],
|
||||
)
|
||||
@@ -1,25 +0,0 @@
|
||||
/* Copyright 2023 The MediaPipe Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
|
||||
namespace mediapipe.tflite_operations.sentencepiece;
|
||||
|
||||
table Trie {
|
||||
nodes: [uint32];
|
||||
}
|
||||
|
||||
|
||||
enum EncoderVersion: byte {
|
||||
SENTENCE_PIECE = 0,
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/* Copyright 2023 The MediaPipe Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_DOUBLE_ARRAY_TRIE_H_
|
||||
#define MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_DOUBLE_ARRAY_TRIE_H_
|
||||
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/config_generated.h"
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/utils.h"
|
||||
|
||||
namespace mediapipe::tflite_operations::sentencepiece {
|
||||
|
||||
// A trie node specifies a node in the tree, either an intermediate node or
|
||||
// a leaf node.
|
||||
// A leaf node contains the id as an int of the string match. This id is encoded
|
||||
// in the lower 31 bits, thus the number of distinct ids is 2^31.
|
||||
// An intermediate node has an associated label and an offset to its children.
|
||||
// The label is encoded in the least significant byte and must match the input
|
||||
// character during matching.
|
||||
|
||||
// A memory mappable trie, compatible with Darts::DoubleArray.
|
||||
class DoubleArrayTrie {
|
||||
public:
|
||||
struct Match {
|
||||
Match() {}
|
||||
Match(int id, int match_length) : id(id), match_length(match_length) {}
|
||||
int id = -1;
|
||||
int match_length = -1;
|
||||
bool empty() const { return match_length == -1; }
|
||||
bool operator==(const Match& m) const {
|
||||
return m.id == id && m.match_length == match_length;
|
||||
}
|
||||
};
|
||||
|
||||
// nodes and nodes_length specify the array of the nodes of the trie.
|
||||
explicit DoubleArrayTrie(const flatbuffers::Vector<uint32_t>* nodes)
|
||||
: nodes_(nodes) {}
|
||||
|
||||
// Finds matches that are prefixes of a string.
|
||||
template <typename callback>
|
||||
void IteratePrefixMatches(const utils::string_view& input,
|
||||
callback update_fn) const;
|
||||
|
||||
// Finds the longest prefix match of a string.
|
||||
Match LongestPrefixMatch(const utils::string_view& input) const {
|
||||
Match match;
|
||||
IteratePrefixMatches(input, [&match](const Match& m) { match = m; });
|
||||
return match;
|
||||
}
|
||||
|
||||
private:
|
||||
// Returns whether a node as a leaf as a child.
|
||||
bool has_leaf(uint32_t i) const { return ((*nodes_)[i]) & 0x100; }
|
||||
|
||||
// Returns a value associated with a node. Available when a node is a leaf.
|
||||
int value(uint32_t i) const {
|
||||
return static_cast<int>(((*nodes_)[i]) & 0x7fffffff);
|
||||
}
|
||||
|
||||
// Returns a label associated with a node.
|
||||
// A leaf node will have the MSB set and thus return an invalid label.
|
||||
int32_t label(uint32_t i) const { return ((*nodes_)[i]) & 0x800000ff; }
|
||||
|
||||
// Returns offset to children.
|
||||
int32_t offset(uint32_t i) const {
|
||||
const uint32_t node = (*nodes_)[i];
|
||||
return (node >> 10) << ((node & 0x200) >> 6);
|
||||
}
|
||||
|
||||
const flatbuffers::Vector<uint32_t>* nodes_;
|
||||
};
|
||||
|
||||
template <typename callback>
|
||||
void DoubleArrayTrie::IteratePrefixMatches(const utils::string_view& input,
|
||||
callback update_fn) const {
|
||||
if (nodes_->size() == 0) {
|
||||
return;
|
||||
}
|
||||
uint32_t pos = offset(0);
|
||||
for (int i = 0; i < input.length(); ++i) {
|
||||
pos ^= static_cast<unsigned char>(input.at(i));
|
||||
if (pos < 0 || pos >= nodes_->size() || label(pos) != input.at(i)) {
|
||||
// No match, exit.
|
||||
return;
|
||||
}
|
||||
const bool node_has_leaf = has_leaf(pos);
|
||||
pos ^= offset(pos);
|
||||
if (pos < 0 || pos >= nodes_->size()) {
|
||||
// We can get here only if the structure is corrupted.
|
||||
return;
|
||||
}
|
||||
if (node_has_leaf) {
|
||||
update_fn(Match(value(pos), i + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mediapipe::tflite_operations::sentencepiece
|
||||
|
||||
#endif // MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_DOUBLE_ARRAY_TRIE_H_
|
||||
@@ -1,75 +0,0 @@
|
||||
/* Copyright 2023 The MediaPipe Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/double_array_trie_builder.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "include/darts.h"
|
||||
|
||||
namespace mediapipe::tflite_operations::sentencepiece {
|
||||
|
||||
std::vector<uint32_t> BuildTrie(const std::vector<std::string>& data) {
|
||||
std::vector<int> ids;
|
||||
ids.reserve(data.size());
|
||||
for (int i = 0; i < data.size(); ++i) {
|
||||
ids.push_back(i);
|
||||
}
|
||||
return BuildTrie(data, ids);
|
||||
}
|
||||
|
||||
std::vector<uint32_t> BuildTrie(const std::vector<std::string>& data,
|
||||
const std::vector<int>& ids) {
|
||||
// We make strong assumptions about binary structure of trie.
|
||||
struct OneElement {
|
||||
OneElement(const std::string* key_, int index_)
|
||||
: key(key_), index(index_) {}
|
||||
const std::string* key;
|
||||
int index;
|
||||
bool operator<(const OneElement& el) const { return *key < *el.key; }
|
||||
};
|
||||
std::vector<OneElement> elements;
|
||||
elements.reserve(data.size());
|
||||
auto data_iterator = std::begin(data);
|
||||
auto ids_iterator = std::begin(ids);
|
||||
for (; data_iterator != std::end(data) && ids_iterator != std::end(ids);
|
||||
++data_iterator, ++ids_iterator) {
|
||||
elements.emplace_back(&(*data_iterator), *ids_iterator);
|
||||
}
|
||||
// Sort by keys.
|
||||
std::sort(elements.begin(), elements.end());
|
||||
|
||||
// Create vectors to build the trie.
|
||||
std::vector<const char*> strings;
|
||||
std::vector<int32_t> indexes;
|
||||
strings.reserve(data.size());
|
||||
indexes.reserve(data.size());
|
||||
for (const auto& el : elements) {
|
||||
strings.push_back(el.key->c_str());
|
||||
indexes.push_back(el.index);
|
||||
}
|
||||
auto trie = std::make_unique<Darts::DoubleArray>();
|
||||
trie->build(data.size(), const_cast<char**>(&strings[0]), nullptr,
|
||||
&indexes[0]);
|
||||
// We make strong assumptions about internal Darts trie structure:
|
||||
// - it is a vector of 32 bit signed integers
|
||||
// - the "array" is the only one structure that contains all information about
|
||||
// the trie.
|
||||
const uint32_t* trie_data = static_cast<const uint32_t*>(trie->array());
|
||||
return std::vector<uint32_t>(trie_data, trie_data + trie->size());
|
||||
}
|
||||
|
||||
} // namespace mediapipe::tflite_operations::sentencepiece
|
||||
@@ -1,32 +0,0 @@
|
||||
/* Copyright 2023 The MediaPipe Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_DOUBLE_ARRAY_TRIE_BUILDER_H_
|
||||
#define MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_DOUBLE_ARRAY_TRIE_BUILDER_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace mediapipe::tflite_operations::sentencepiece {
|
||||
|
||||
std::vector<uint32_t> BuildTrie(const std::vector<std::string>& data,
|
||||
const std::vector<int>& ids);
|
||||
|
||||
// A variant where ids are indexes in data.
|
||||
std::vector<uint32_t> BuildTrie(const std::vector<std::string>& data);
|
||||
|
||||
} // namespace mediapipe::tflite_operations::sentencepiece
|
||||
|
||||
#endif // MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_DOUBLE_ARRAY_TRIE_BUILDER_H_
|
||||
@@ -1,73 +0,0 @@
|
||||
/* Copyright 2023 The MediaPipe Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/double_array_trie.h"
|
||||
|
||||
#include "mediapipe/framework/port/gmock.h"
|
||||
#include "mediapipe/framework/port/gtest.h"
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/double_array_trie_builder.h"
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/encoder_config_generated.h"
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/utils.h"
|
||||
|
||||
namespace mediapipe::tflite_operations::sentencepiece {
|
||||
|
||||
TEST(DoubleArrayTrieTest, Match) {
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
const std::vector<std::string> test_strings = {"A", "AAX", "AA", "B"};
|
||||
const auto trie_vector = builder.CreateVector(BuildTrie(test_strings));
|
||||
TrieBuilder trie_builder(builder);
|
||||
trie_builder.add_nodes(trie_vector);
|
||||
const auto pieces = trie_builder.Finish();
|
||||
EncoderConfigBuilder ecb(builder);
|
||||
ecb.add_pieces(pieces);
|
||||
FinishEncoderConfigBuffer(builder, ecb.Finish());
|
||||
const EncoderConfig* config = GetEncoderConfig(builder.GetBufferPointer());
|
||||
DoubleArrayTrie dat(config->pieces()->nodes());
|
||||
EXPECT_EQ(dat.LongestPrefixMatch(utils::string_view("AAL")),
|
||||
DoubleArrayTrie::Match(2, 2));
|
||||
|
||||
std::vector<DoubleArrayTrie::Match> matches;
|
||||
dat.IteratePrefixMatches(
|
||||
utils::string_view("AAXL"),
|
||||
[&matches](const DoubleArrayTrie::Match& m) { matches.push_back(m); });
|
||||
EXPECT_THAT(matches, testing::ElementsAre(DoubleArrayTrie::Match(0, 1),
|
||||
DoubleArrayTrie::Match(2, 2),
|
||||
DoubleArrayTrie::Match(1, 3)));
|
||||
}
|
||||
|
||||
TEST(DoubleArrayTrieTest, ComplexMatch) {
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
const std::vector<std::string> test_strings = {"\xe2\x96\x81the", ",", "s",
|
||||
"\xe2\x96\x81Hello"};
|
||||
const std::vector<int> test_ids = {0, 5, 10, 15};
|
||||
const auto trie_vector =
|
||||
builder.CreateVector(BuildTrie(test_strings, test_ids));
|
||||
TrieBuilder trie_builder(builder);
|
||||
trie_builder.add_nodes(trie_vector);
|
||||
const auto pieces = trie_builder.Finish();
|
||||
EncoderConfigBuilder ecb(builder);
|
||||
ecb.add_pieces(pieces);
|
||||
FinishEncoderConfigBuffer(builder, ecb.Finish());
|
||||
const EncoderConfig* config = GetEncoderConfig(builder.GetBufferPointer());
|
||||
DoubleArrayTrie dat(config->pieces()->nodes());
|
||||
|
||||
std::vector<DoubleArrayTrie::Match> matches;
|
||||
dat.IteratePrefixMatches(
|
||||
utils::string_view("\xe2\x96\x81Hello"),
|
||||
[&matches](const DoubleArrayTrie::Match& m) { matches.push_back(m); });
|
||||
EXPECT_THAT(matches, testing::ElementsAre(DoubleArrayTrie::Match(15, 8)));
|
||||
}
|
||||
|
||||
} // namespace mediapipe::tflite_operations::sentencepiece
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright 2023 The MediaPipe Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
include "config.fbs";
|
||||
|
||||
namespace mediapipe.tflite_operations.sentencepiece;
|
||||
|
||||
table EncoderConfig {
|
||||
// Version of the encoder.
|
||||
version: EncoderVersion = SENTENCE_PIECE;
|
||||
start_code: int32 = 0;
|
||||
end_code: int32 = 0;
|
||||
|
||||
unknown_code: int32 = -1;
|
||||
// Weight of "unknown code" when encoding. "Penalty" because it usually has a
|
||||
// big negative weight,less than any other sentencepiece.
|
||||
unknown_penalty: float = 0;
|
||||
|
||||
// The offset for encoding, usually used when codes with low codes are reserved
|
||||
// for some special needs.
|
||||
encoding_offset: int32;
|
||||
|
||||
// String pieces for encoding.
|
||||
pieces: Trie;
|
||||
pieces_scores: [float];
|
||||
|
||||
// Normalization related parameters.
|
||||
remove_extra_whitespaces: bool;
|
||||
|
||||
// Add a whitespace prefix before encoding.
|
||||
add_dummy_prefix: bool;
|
||||
|
||||
// Escape whitespaces during encoding so the decoder can restore them exactly as
|
||||
// in the input.
|
||||
escape_whitespaces: bool;
|
||||
|
||||
// Normalization parameters.
|
||||
normalized_prefixes: Trie;
|
||||
normalized_replacements: [byte];
|
||||
}
|
||||
|
||||
root_type EncoderConfig;
|
||||
@@ -1,131 +0,0 @@
|
||||
/* Copyright 2023 The MediaPipe Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/model_converter.h"
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/double_array_trie_builder.h"
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/encoder_config_generated.h"
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/sentencepiece_constants.h"
|
||||
#include "src/sentencepiece_model.pb.h"
|
||||
|
||||
namespace mediapipe::tflite_operations::sentencepiece {
|
||||
|
||||
std::tuple<std::vector<uint32_t>, std::vector<int8_t>>
|
||||
DecodePrecompiledCharsmap(
|
||||
const ::sentencepiece::NormalizerSpec& normalizer_spec) {
|
||||
// This function "undoes" encoding done by
|
||||
// sentencepiece::normalizer::Normalizer::EncodePrecompiledCharsMap.
|
||||
const char* precompiled_map = normalizer_spec.precompiled_charsmap().data();
|
||||
const uint32_t trie_size =
|
||||
*reinterpret_cast<const uint32_t*>(precompiled_map);
|
||||
const uint32_t* trie_ptr =
|
||||
reinterpret_cast<const uint32_t*>(precompiled_map + sizeof(uint32_t));
|
||||
const int8_t* normalized_ptr = reinterpret_cast<const int8_t*>(
|
||||
precompiled_map + sizeof(uint32_t) + trie_size);
|
||||
const int normalized_size = normalizer_spec.precompiled_charsmap().length() -
|
||||
sizeof(uint32_t) - trie_size;
|
||||
return std::make_tuple(
|
||||
std::vector<uint32_t>(trie_ptr, trie_ptr + trie_size / sizeof(uint32_t)),
|
||||
std::vector<int8_t>(normalized_ptr, normalized_ptr + normalized_size));
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> ConvertSentencepieceModelToFlatBuffer(
|
||||
const std::string& model_config_str, int encoding_offset) {
|
||||
::sentencepiece::ModelProto model_config;
|
||||
if (!model_config.ParseFromString(model_config_str)) {
|
||||
return absl::InvalidArgumentError(
|
||||
"Invalid configuration, can't parse SentencePiece model config " +
|
||||
model_config.InitializationErrorString());
|
||||
}
|
||||
// Convert sentencepieces.
|
||||
std::vector<std::string> pieces;
|
||||
pieces.reserve(model_config.pieces_size());
|
||||
std::vector<float> scores;
|
||||
scores.reserve(model_config.pieces_size());
|
||||
std::vector<int> ids;
|
||||
ids.reserve(model_config.pieces_size());
|
||||
float min_score = 0.0;
|
||||
int index = 0;
|
||||
for (const auto& piece : model_config.pieces()) {
|
||||
switch (piece.type()) {
|
||||
case ::sentencepiece::ModelProto::SentencePiece::NORMAL:
|
||||
case ::sentencepiece::ModelProto::SentencePiece::USER_DEFINED:
|
||||
pieces.push_back(piece.piece());
|
||||
ids.push_back(index);
|
||||
if (piece.score() < min_score) {
|
||||
min_score = piece.score();
|
||||
}
|
||||
break;
|
||||
case ::sentencepiece::ModelProto::SentencePiece::UNKNOWN:
|
||||
case ::sentencepiece::ModelProto::SentencePiece::CONTROL:
|
||||
// Ignore unknown and control codes.
|
||||
break;
|
||||
default:
|
||||
return absl::InvalidArgumentError("Invalid SentencePiece piece type " +
|
||||
piece.piece());
|
||||
}
|
||||
scores.push_back(piece.score());
|
||||
++index;
|
||||
}
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
const auto pieces_trie_vector = builder.CreateVector(BuildTrie(pieces, ids));
|
||||
const auto pieces_score_vector = builder.CreateVector(scores);
|
||||
TrieBuilder pieces_trie_builder(builder);
|
||||
pieces_trie_builder.add_nodes(pieces_trie_vector);
|
||||
const auto pieces_trie_fbs = pieces_trie_builder.Finish();
|
||||
|
||||
// Converting normalization.
|
||||
const auto normalization =
|
||||
DecodePrecompiledCharsmap(model_config.normalizer_spec());
|
||||
const auto normalization_trie = std::get<0>(normalization);
|
||||
const auto normalization_strings = std::get<1>(normalization);
|
||||
const auto normalization_trie_vector =
|
||||
builder.CreateVector(normalization_trie);
|
||||
TrieBuilder normalization_trie_builder(builder);
|
||||
normalization_trie_builder.add_nodes(normalization_trie_vector);
|
||||
const auto normalization_trie_fbs = normalization_trie_builder.Finish();
|
||||
const auto normalization_strings_fbs =
|
||||
builder.CreateVector(normalization_strings);
|
||||
|
||||
EncoderConfigBuilder ecb(builder);
|
||||
ecb.add_version(EncoderVersion::EncoderVersion_SENTENCE_PIECE);
|
||||
ecb.add_start_code(model_config.trainer_spec().bos_id());
|
||||
ecb.add_end_code(model_config.trainer_spec().eos_id());
|
||||
ecb.add_unknown_code(model_config.trainer_spec().unk_id());
|
||||
ecb.add_unknown_penalty(min_score - kUnkPenalty);
|
||||
ecb.add_encoding_offset(encoding_offset);
|
||||
ecb.add_pieces(pieces_trie_fbs);
|
||||
ecb.add_pieces_scores(pieces_score_vector);
|
||||
ecb.add_remove_extra_whitespaces(
|
||||
model_config.normalizer_spec().remove_extra_whitespaces());
|
||||
ecb.add_add_dummy_prefix(model_config.normalizer_spec().add_dummy_prefix());
|
||||
ecb.add_escape_whitespaces(
|
||||
model_config.normalizer_spec().escape_whitespaces());
|
||||
ecb.add_normalized_prefixes(normalization_trie_fbs);
|
||||
ecb.add_normalized_replacements(normalization_strings_fbs);
|
||||
FinishEncoderConfigBuffer(builder, ecb.Finish());
|
||||
return std::string(reinterpret_cast<const char*>(builder.GetBufferPointer()),
|
||||
builder.GetSize());
|
||||
}
|
||||
|
||||
std::string ConvertSentencepieceModel(const std::string& model_string) {
|
||||
const auto result = ConvertSentencepieceModelToFlatBuffer(model_string);
|
||||
assert(result.status().ok());
|
||||
return result.value();
|
||||
}
|
||||
|
||||
} // namespace mediapipe::tflite_operations::sentencepiece
|
||||
@@ -1,33 +0,0 @@
|
||||
/* Copyright 2023 The MediaPipe Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_MODEL_CONVERTER_H_
|
||||
#define MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_MODEL_CONVERTER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/status/statusor.h"
|
||||
|
||||
namespace mediapipe::tflite_operations::sentencepiece {
|
||||
|
||||
// Converts Sentencepiece configuration to flatbuffer format.
|
||||
// encoding_offset is used by some encoders that combine different encodings.
|
||||
absl::StatusOr<std::string> ConvertSentencepieceModelToFlatBuffer(
|
||||
const std::string& model_config_str, int encoding_offset = 0);
|
||||
std::string ConvertSentencepieceModel(const std::string& model_string);
|
||||
|
||||
} // namespace mediapipe::tflite_operations::sentencepiece
|
||||
|
||||
#endif // MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_MODEL_CONVERTER_H_
|
||||
@@ -1,236 +0,0 @@
|
||||
/* Copyright 2023 The MediaPipe Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/optimized_encoder.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <tuple>
|
||||
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/double_array_trie.h"
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/encoder_config_generated.h"
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/utils.h"
|
||||
|
||||
namespace mediapipe::tflite_operations::sentencepiece {
|
||||
namespace {
|
||||
|
||||
const char kSpaceSymbol[] = "\xe2\x96\x81";
|
||||
|
||||
template <typename processing_callback>
|
||||
std::tuple<std::string, std::vector<int>> process_string(
|
||||
const std::string& input, const std::vector<int>& offsets,
|
||||
const processing_callback& pc) {
|
||||
std::string result_string;
|
||||
result_string.reserve(input.size());
|
||||
std::vector<int> result_offsets;
|
||||
result_offsets.reserve(offsets.size());
|
||||
for (int i = 0, j = 0; i < input.size();) {
|
||||
auto result = pc(input.data() + i, input.size() - i);
|
||||
auto consumed = std::get<0>(result);
|
||||
auto new_string = std::get<1>(result);
|
||||
if (consumed == 0) {
|
||||
// Skip the current byte and move forward.
|
||||
result_string.push_back(input[i]);
|
||||
result_offsets.push_back(offsets[j]);
|
||||
i++;
|
||||
j++;
|
||||
continue;
|
||||
}
|
||||
result_string.append(new_string.data(), new_string.length());
|
||||
for (int i = 0; i < new_string.length(); ++i) {
|
||||
result_offsets.push_back(offsets[j]);
|
||||
}
|
||||
j += consumed;
|
||||
i += consumed;
|
||||
}
|
||||
return std::make_tuple(result_string, result_offsets);
|
||||
}
|
||||
|
||||
inline char is_whitespace(char c) {
|
||||
return c == ' ' || c == '\t' || c == '\r' || c == '\n';
|
||||
}
|
||||
|
||||
std::tuple<int, utils::string_view> remove_extra_whitespaces(const char* data,
|
||||
int len) {
|
||||
if (len == 0 || !is_whitespace(*data)) {
|
||||
return std::make_tuple(0, utils::string_view(nullptr, 0));
|
||||
}
|
||||
int num_consumed = 1;
|
||||
for (; num_consumed < len && is_whitespace(data[num_consumed]);
|
||||
++num_consumed) {
|
||||
}
|
||||
return num_consumed > 1
|
||||
? std::make_tuple(num_consumed, utils::string_view(" ", 1))
|
||||
: std::make_tuple(0, utils::string_view(nullptr, 0));
|
||||
}
|
||||
|
||||
std::tuple<int, utils::string_view> find_replacement(
|
||||
const char* data, int len, const DoubleArrayTrie& dat,
|
||||
const flatbuffers::Vector<int8_t>& replacements) {
|
||||
const auto max_match = dat.LongestPrefixMatch(utils::string_view(data, len));
|
||||
if (!max_match.empty()) {
|
||||
// Because flatbuffer byte is signed char which is not the same as char,
|
||||
// there is the reinterpret_cast here.
|
||||
const char* replaced_string_ptr =
|
||||
reinterpret_cast<const char*>(replacements.data() + max_match.id);
|
||||
return std::make_tuple(max_match.match_length,
|
||||
utils::string_view(replaced_string_ptr));
|
||||
}
|
||||
return std::make_tuple(0, utils::string_view(nullptr, 0));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::tuple<std::string, std::vector<int>> NormalizeString(
|
||||
const std::string& in_string, const EncoderConfig& config) {
|
||||
std::vector<int> output_offsets;
|
||||
std::string result = in_string;
|
||||
output_offsets.reserve(in_string.length());
|
||||
for (int i = 0; i < in_string.length(); ++i) {
|
||||
output_offsets.push_back(i);
|
||||
}
|
||||
if (in_string.empty()) {
|
||||
return std::make_tuple(result, output_offsets);
|
||||
}
|
||||
if (config.add_dummy_prefix()) {
|
||||
result.insert(result.begin(), ' ');
|
||||
output_offsets.insert(output_offsets.begin(), 0);
|
||||
}
|
||||
// Greedely replace normalized_prefixes with normalized_replacements
|
||||
if (config.normalized_prefixes() != nullptr &&
|
||||
config.normalized_replacements() != nullptr) {
|
||||
const DoubleArrayTrie normalized_prefixes_matcher(
|
||||
config.normalized_prefixes()->nodes());
|
||||
const auto norm_replace = [&config, &normalized_prefixes_matcher](
|
||||
const char* data, int len) {
|
||||
return find_replacement(data, len, normalized_prefixes_matcher,
|
||||
*config.normalized_replacements());
|
||||
};
|
||||
std::tie(result, output_offsets) =
|
||||
process_string(result, output_offsets, norm_replace);
|
||||
}
|
||||
if (config.remove_extra_whitespaces()) {
|
||||
std::tie(result, output_offsets) =
|
||||
process_string(result, output_offsets, remove_extra_whitespaces);
|
||||
if (!result.empty() && is_whitespace(result.back())) {
|
||||
result.pop_back();
|
||||
output_offsets.pop_back();
|
||||
}
|
||||
}
|
||||
if (config.escape_whitespaces()) {
|
||||
const auto replace_whitespaces = [](const char* data, int len) {
|
||||
if (len > 0 && is_whitespace(*data)) {
|
||||
return std::make_tuple(1, utils::string_view(kSpaceSymbol));
|
||||
}
|
||||
return std::make_tuple(0, utils::string_view(nullptr, 0));
|
||||
};
|
||||
std::tie(result, output_offsets) =
|
||||
process_string(result, output_offsets, replace_whitespaces);
|
||||
}
|
||||
|
||||
return std::make_tuple(result, output_offsets);
|
||||
}
|
||||
|
||||
EncoderResult EncodeNormalizedString(const std::string& str,
|
||||
const std::vector<int>& offsets,
|
||||
const EncoderConfig& config, bool add_bos,
|
||||
bool add_eos, bool reverse) {
|
||||
const DoubleArrayTrie piece_matcher(config.pieces()->nodes());
|
||||
const flatbuffers::Vector<float>* piece_scores = config.pieces_scores();
|
||||
const int unknown_code = config.unknown_code();
|
||||
const float unknown_penalty = config.unknown_penalty();
|
||||
struct LatticeElement {
|
||||
float score = 0;
|
||||
int code = -1;
|
||||
int prev_position = -1;
|
||||
LatticeElement(float score_, int code_, int prev_position_)
|
||||
: score(score_), code(code_), prev_position(prev_position_) {}
|
||||
LatticeElement() {}
|
||||
};
|
||||
const int length = str.length();
|
||||
std::vector<LatticeElement> lattice(length + 1);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
if (i > 0 && lattice[i].prev_position < 0) {
|
||||
// This state is unreachable.
|
||||
continue;
|
||||
}
|
||||
if (unknown_code >= 0) {
|
||||
// Put unknown code.
|
||||
const float penalized_score = lattice[i].score + unknown_penalty;
|
||||
const int pos = i + 1;
|
||||
LatticeElement& current_element = lattice[pos];
|
||||
if (current_element.prev_position < 0 ||
|
||||
current_element.score < penalized_score) {
|
||||
current_element = LatticeElement(
|
||||
penalized_score, unknown_code,
|
||||
// If the current state is already reached by unknown code, merge
|
||||
// states.
|
||||
lattice[i].code == unknown_code ? lattice[i].prev_position : i);
|
||||
}
|
||||
}
|
||||
auto lattice_update = [&lattice, i,
|
||||
piece_scores](const DoubleArrayTrie::Match& m) {
|
||||
LatticeElement& target_element = lattice[i + m.match_length];
|
||||
const float score = lattice[i].score + (*piece_scores)[m.id];
|
||||
if (target_element.prev_position < 0 || target_element.score < score) {
|
||||
target_element = LatticeElement(score, m.id, i);
|
||||
}
|
||||
};
|
||||
piece_matcher.IteratePrefixMatches(
|
||||
utils::string_view(str.data() + i, length - i), lattice_update);
|
||||
}
|
||||
|
||||
EncoderResult result;
|
||||
if (add_eos) {
|
||||
result.codes.push_back(config.end_code());
|
||||
result.offsets.push_back(length);
|
||||
}
|
||||
if (lattice[length].prev_position >= 0) {
|
||||
for (int pos = length; pos > 0;) {
|
||||
auto code = lattice[pos].code;
|
||||
if (code != config.unknown_code()) {
|
||||
code += config.encoding_offset();
|
||||
}
|
||||
result.codes.push_back(code);
|
||||
pos = lattice[pos].prev_position;
|
||||
result.offsets.push_back(offsets[pos]);
|
||||
}
|
||||
}
|
||||
if (add_bos) {
|
||||
result.codes.push_back(config.start_code());
|
||||
result.offsets.push_back(0);
|
||||
}
|
||||
if (!reverse) {
|
||||
std::reverse(result.codes.begin(), result.codes.end());
|
||||
std::reverse(result.offsets.begin(), result.offsets.end());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
EncoderResult EncodeString(const std::string& string, const void* config_buffer,
|
||||
bool add_bos, bool add_eos, bool reverse) {
|
||||
// Get the config from the buffer.
|
||||
const EncoderConfig* config = GetEncoderConfig(config_buffer);
|
||||
if (config->version() != EncoderVersion::EncoderVersion_SENTENCE_PIECE) {
|
||||
EncoderResult result;
|
||||
result.type = EncoderResultType::WRONG_CONFIG;
|
||||
return result;
|
||||
}
|
||||
std::string normalized_string;
|
||||
std::vector<int> offsets;
|
||||
std::tie(normalized_string, offsets) = NormalizeString(string, *config);
|
||||
return EncodeNormalizedString(normalized_string, offsets, *config, add_bos,
|
||||
add_eos, reverse);
|
||||
}
|
||||
|
||||
} // namespace mediapipe::tflite_operations::sentencepiece
|
||||
@@ -1,46 +0,0 @@
|
||||
/* Copyright 2023 The MediaPipe Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_OPTIMIZED_ENCODER_H_
|
||||
#define MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_OPTIMIZED_ENCODER_H_
|
||||
|
||||
// Sentencepiece encoder optimized with memmapped model.
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/encoder_config_generated.h"
|
||||
|
||||
namespace mediapipe::tflite_operations::sentencepiece {
|
||||
|
||||
enum class EncoderResultType { SUCCESS = 0, WRONG_CONFIG = 1 };
|
||||
|
||||
struct EncoderResult {
|
||||
EncoderResultType type = EncoderResultType::SUCCESS;
|
||||
std::vector<int> codes;
|
||||
std::vector<int> offsets;
|
||||
};
|
||||
std::tuple<std::string, std::vector<int>> NormalizeString(
|
||||
const std::string& in_string, const EncoderConfig& config);
|
||||
|
||||
// Encodes one string and returns ids and offsets. Takes the configuration as a
|
||||
// type-erased buffer.
|
||||
EncoderResult EncodeString(const std::string& string, const void* config_buffer,
|
||||
bool add_bos, bool add_eos, bool reverse);
|
||||
|
||||
} // namespace mediapipe::tflite_operations::sentencepiece
|
||||
|
||||
#endif // MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_OPTIMIZED_ENCODER_H_
|
||||
@@ -1,171 +0,0 @@
|
||||
/* Copyright 2023 The MediaPipe Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/optimized_encoder.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "mediapipe/framework/deps/file_path.h"
|
||||
#include "mediapipe/framework/port/gmock.h"
|
||||
#include "mediapipe/framework/port/gtest.h"
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/double_array_trie_builder.h"
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/encoder_config_generated.h"
|
||||
#include "mediapipe/tasks/cc/text/custom_ops/sentencepiece/model_converter.h"
|
||||
#include "src/sentencepiece.pb.h"
|
||||
#include "src/sentencepiece_processor.h"
|
||||
#include "tensorflow/core/platform/env.h"
|
||||
|
||||
namespace mediapipe::tflite_operations::sentencepiece {
|
||||
|
||||
namespace internal {
|
||||
|
||||
tensorflow::Status TFReadFileToString(const std::string& filepath,
|
||||
std::string* data) {
|
||||
return tensorflow::ReadFileToString(tensorflow::Env::Default(), filepath,
|
||||
data);
|
||||
}
|
||||
|
||||
absl::Status StdReadFileToString(const std::string& filepath,
|
||||
std::string* data) {
|
||||
std::ifstream infile(filepath);
|
||||
if (!infile.is_open()) {
|
||||
return absl::NotFoundError(
|
||||
absl::StrFormat("Error when opening %s", filepath));
|
||||
}
|
||||
std::string contents((std::istreambuf_iterator<char>(infile)),
|
||||
(std::istreambuf_iterator<char>()));
|
||||
data->append(contents);
|
||||
infile.close();
|
||||
return absl::OkStatus();
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
namespace {
|
||||
|
||||
using ::mediapipe::file::JoinPath;
|
||||
|
||||
static char kConfigFilePath[] =
|
||||
"/mediapipe/tasks/cc/text/custom_ops/"
|
||||
"sentencepiece/testdata/sentencepiece.model";
|
||||
|
||||
TEST(OptimizedEncoder, NormalizeStringWhitestpaces) {
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
EncoderConfigBuilder ecb(builder);
|
||||
ecb.add_remove_extra_whitespaces(true);
|
||||
ecb.add_add_dummy_prefix(true);
|
||||
ecb.add_escape_whitespaces(true);
|
||||
FinishEncoderConfigBuffer(builder, ecb.Finish());
|
||||
const EncoderConfig* config = GetEncoderConfig(builder.GetBufferPointer());
|
||||
{
|
||||
const auto result = NormalizeString("x y", *config);
|
||||
const auto res_string = std::get<0>(result);
|
||||
const auto offsets = std::get<1>(result);
|
||||
EXPECT_EQ(res_string, "\xe2\x96\x81x\xe2\x96\x81y");
|
||||
EXPECT_THAT(offsets, ::testing::ElementsAre(0, 0, 0, 0, 1, 1, 1, 3));
|
||||
}
|
||||
{
|
||||
const auto result = NormalizeString("\tx y\n", *config);
|
||||
const auto res_string = std::get<0>(result);
|
||||
const auto offsets = std::get<1>(result);
|
||||
EXPECT_EQ(res_string, "\xe2\x96\x81x\xe2\x96\x81y");
|
||||
EXPECT_THAT(offsets, ::testing::ElementsAre(0, 0, 0, 1, 2, 2, 2, 4));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(OptimizedEncoder, NormalizeStringReplacement) {
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
const std::vector<std::string> norm_prefixes = {"A", "AA", "AAA", "AAAA"};
|
||||
const char norm_replacements[] = "A1\0A2\0A3\0A4";
|
||||
const auto trie_vector =
|
||||
builder.CreateVector(BuildTrie(norm_prefixes, {0, 3, 6, 9}));
|
||||
const auto norm_r = builder.CreateVector<int8_t>(
|
||||
reinterpret_cast<const signed char*>(norm_replacements),
|
||||
sizeof(norm_replacements));
|
||||
TrieBuilder trie_builder(builder);
|
||||
trie_builder.add_nodes(trie_vector);
|
||||
const auto norm_p = trie_builder.Finish();
|
||||
EncoderConfigBuilder ecb(builder);
|
||||
ecb.add_remove_extra_whitespaces(false);
|
||||
ecb.add_normalized_prefixes(norm_p);
|
||||
ecb.add_normalized_replacements(norm_r);
|
||||
FinishEncoderConfigBuffer(builder, ecb.Finish());
|
||||
const EncoderConfig* config = GetEncoderConfig(builder.GetBufferPointer());
|
||||
{
|
||||
const auto result = NormalizeString("ABAABAAABAAAA", *config);
|
||||
const auto res_string = std::get<0>(result);
|
||||
const auto offsets = std::get<1>(result);
|
||||
EXPECT_EQ(res_string, "A1BA2BA3BA4");
|
||||
EXPECT_THAT(offsets,
|
||||
::testing::ElementsAre(0, 0, 1, 2, 2, 4, 5, 5, 8, 9, 9));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(OptimizedEncoder, NormalizeStringWhitespacesRemove) {
|
||||
flatbuffers::FlatBufferBuilder builder(1024);
|
||||
const std::vector<std::string> norm_prefixes = {"A", "AA", "AAA", "AAAA",
|
||||
"X"};
|
||||
const char norm_replacements[] = "A1\0A2\0A3\0A4\0 ";
|
||||
const auto trie_vector =
|
||||
builder.CreateVector(BuildTrie(norm_prefixes, {0, 3, 6, 9, 12}));
|
||||
const auto norm_r = builder.CreateVector<int8_t>(
|
||||
reinterpret_cast<const signed char*>(norm_replacements),
|
||||
sizeof(norm_replacements));
|
||||
TrieBuilder trie_builder(builder);
|
||||
trie_builder.add_nodes(trie_vector);
|
||||
const auto norm_p = trie_builder.Finish();
|
||||
EncoderConfigBuilder ecb(builder);
|
||||
ecb.add_remove_extra_whitespaces(true);
|
||||
ecb.add_normalized_prefixes(norm_p);
|
||||
ecb.add_normalized_replacements(norm_r);
|
||||
FinishEncoderConfigBuffer(builder, ecb.Finish());
|
||||
const EncoderConfig* config = GetEncoderConfig(builder.GetBufferPointer());
|
||||
{
|
||||
const auto result = NormalizeString("XXABAABAAABAAAA", *config);
|
||||
const auto res_string = std::get<0>(result);
|
||||
const auto offsets = std::get<1>(result);
|
||||
EXPECT_EQ(res_string, " A1BA2BA3BA4");
|
||||
EXPECT_THAT(offsets,
|
||||
::testing::ElementsAre(0, 2, 2, 3, 4, 4, 6, 7, 7, 10, 11, 11));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(OptimizedEncoder, ConfigConverter) {
|
||||
std::string config;
|
||||
auto status =
|
||||
internal::TFReadFileToString(JoinPath("./", kConfigFilePath), &config);
|
||||
ASSERT_TRUE(status.ok());
|
||||
|
||||
::sentencepiece::SentencePieceProcessor processor;
|
||||
ASSERT_TRUE(processor.LoadFromSerializedProto(config).ok());
|
||||
const auto converted_model = ConvertSentencepieceModel(config);
|
||||
const std::string test_string("Hello world!\\xF0\\x9F\\x8D\\x95");
|
||||
const auto encoded =
|
||||
EncodeString(test_string, converted_model.data(), false, false, false);
|
||||
ASSERT_EQ(encoded.codes.size(), encoded.offsets.size());
|
||||
|
||||
::sentencepiece::SentencePieceText reference_encoded;
|
||||
ASSERT_TRUE(processor.Encode(test_string, &reference_encoded).ok());
|
||||
EXPECT_EQ(encoded.codes.size(), reference_encoded.pieces_size());
|
||||
for (int i = 0; i < encoded.codes.size(); ++i) {
|
||||
EXPECT_EQ(encoded.codes[i], reference_encoded.pieces(i).id());
|
||||
EXPECT_EQ(encoded.offsets[i], reference_encoded.pieces(i).begin());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mediapipe::tflite_operations::sentencepiece
|
||||
@@ -1,38 +0,0 @@
|
||||
/* Copyright 2023 The MediaPipe Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_SENTENCEPIECE_CONSTANTS_H_
|
||||
#define MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_SENTENCEPIECE_CONSTANTS_H_
|
||||
|
||||
namespace mediapipe::tflite_operations::sentencepiece {
|
||||
|
||||
// The constant is copied from
|
||||
// https://github.com/google/sentencepiece/blob/master/src/unigram_model.cc
|
||||
constexpr float kUnkPenalty = 10.0;
|
||||
|
||||
// These constants are copied from
|
||||
// https://github.com/google/sentencepiece/blob/master/src/sentencepiece_processor.cc
|
||||
//
|
||||
// Replaces white space with U+2581 (LOWER ONE EIGHT BLOCK).
|
||||
constexpr char kSpaceSymbol[] = "\xe2\x96\x81";
|
||||
|
||||
// Encodes <unk> into U+2047 (DOUBLE QUESTION MARK),
|
||||
// since this character can be useful both for user and
|
||||
// developer. We can easily figure out that <unk> is emitted.
|
||||
constexpr char kDefaultUnknownSymbol[] = " \xE2\x81\x87 ";
|
||||
|
||||
} // namespace mediapipe::tflite_operations::sentencepiece
|
||||
|
||||
#endif // MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_SENTENCEPIECE_CONSTANTS_H_
|
||||
BIN
Binary file not shown.
@@ -1,60 +0,0 @@
|
||||
/* Copyright 2023 The MediaPipe Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
|
||||
#ifndef MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_UTILS_H_
|
||||
#define MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_UTILS_H_
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
namespace mediapipe::tflite_operations::sentencepiece {
|
||||
|
||||
// AOSP and WASM doesn't support string_view,
|
||||
// we put here a minimal re-implementation.
|
||||
namespace utils {
|
||||
|
||||
class string_view {
|
||||
public:
|
||||
explicit string_view(const std::string& s)
|
||||
: str_(s.data()), len_(s.length()) {}
|
||||
string_view(const char* str, int len) : str_(str), len_(len) {}
|
||||
// A constructor from c string.
|
||||
explicit string_view(const char* s) : str_(s), len_(strlen(s)) {}
|
||||
|
||||
int length() const { return len_; }
|
||||
const char* data() const { return str_; }
|
||||
bool empty() const { return len_ == 0; }
|
||||
unsigned char at(int i) const { return str_[i]; }
|
||||
|
||||
private:
|
||||
const char* str_ = nullptr;
|
||||
const int len_ = 0;
|
||||
};
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& os, const string_view& sv) {
|
||||
os << std::string(sv.data(), sv.length());
|
||||
return os;
|
||||
}
|
||||
inline bool operator==(const string_view& view1, const string_view& view2) {
|
||||
if (view1.length() != view2.length()) {
|
||||
return false;
|
||||
}
|
||||
return memcmp(view1.data(), view2.data(), view1.length()) == 0;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
} // namespace mediapipe::tflite_operations::sentencepiece
|
||||
|
||||
#endif // MEDIAPIPE_TASKS_CC_TEXT_CUSTOM_OPS_SENTENCEPIECE_UTILS_H_
|
||||
@@ -89,7 +89,7 @@ cc_test(
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/strings:cord",
|
||||
"@com_google_sentencepiece//src:sentencepiece_processor",
|
||||
"@org_tensorflow//tensorflow/lite:test_util",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:cc_shims_test_util",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/components/containers/category.h"
|
||||
#include "mediapipe/tasks/cc/components/containers/classification_result.h"
|
||||
#include "mediapipe/tasks/cc/text/text_classifier/text_classifier_test_utils.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe::tasks::text::text_classifier {
|
||||
namespace {
|
||||
@@ -87,7 +87,7 @@ void ExpectApproximatelyEqual(const TextClassifierResult& actual,
|
||||
|
||||
} // namespace
|
||||
|
||||
class TextClassifierTest : public tflite::testing::Test {};
|
||||
class TextClassifierTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(TextClassifierTest, CreateSucceedsWithBertModel) {
|
||||
auto options = std::make_unique<TextClassifierOptions>();
|
||||
|
||||
@@ -91,6 +91,6 @@ cc_test(
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/status:statusor",
|
||||
"@com_google_sentencepiece//src:sentencepiece_processor",
|
||||
"@org_tensorflow//tensorflow/lite:test_util",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:cc_shims_test_util",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -26,7 +26,7 @@ limitations under the License.
|
||||
#include "mediapipe/framework/port/status_matchers.h"
|
||||
#include "mediapipe/tasks/cc/common.h"
|
||||
#include "mediapipe/tasks/cc/components/containers/embedding_result.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe::tasks::text::text_embedder {
|
||||
namespace {
|
||||
@@ -49,7 +49,7 @@ using ::mediapipe::file::JoinPath;
|
||||
using ::testing::HasSubstr;
|
||||
using ::testing::Optional;
|
||||
|
||||
class EmbedderTest : public tflite::testing::Test {};
|
||||
class EmbedderTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(EmbedderTest, FailsWithMissingModel) {
|
||||
auto text_embedder =
|
||||
|
||||
@@ -81,6 +81,6 @@ cc_test(
|
||||
"@com_google_absl//absl/flags:flag",
|
||||
"@com_google_absl//absl/status:statusor",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@org_tensorflow//tensorflow/lite:test_util",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:cc_shims_test_util",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -28,7 +28,7 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/components/processors/proto/text_model_type.pb.h"
|
||||
#include "mediapipe/tasks/cc/core/model_resources.h"
|
||||
#include "mediapipe/tasks/cc/core/proto/external_file.pb.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe::tasks::text::utils {
|
||||
|
||||
@@ -76,7 +76,7 @@ absl::StatusOr<TextModelType::ModelType> GetModelTypeFromFile(
|
||||
|
||||
} // namespace
|
||||
|
||||
class TextModelUtilsTest : public tflite::testing::Test {};
|
||||
class TextModelUtilsTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(TextModelUtilsTest, BertClassifierModelTest) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(auto model_type,
|
||||
|
||||
@@ -29,7 +29,7 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/core/proto/base_options.pb.h"
|
||||
#include "mediapipe/tasks/cc/core/task_runner.h"
|
||||
#include "mediapipe/tasks/cc/vision/face_landmarker/proto/face_blendshapes_graph_options.pb.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -105,7 +105,7 @@ absl::StatusOr<std::unique_ptr<TaskRunner>> CreateTaskRunner() {
|
||||
graph.GetConfig(), absl::make_unique<core::MediaPipeBuiltinOpResolver>());
|
||||
}
|
||||
|
||||
class FaceBlendshapesTest : public tflite::testing::Test {};
|
||||
class FaceBlendshapesTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(FaceBlendshapesTest, SmokeTest) {
|
||||
// Prepare graph inputs.
|
||||
|
||||
@@ -22,35 +22,29 @@ cc_library(
|
||||
name = "face_stylizer_graph",
|
||||
srcs = ["face_stylizer_graph.cc"],
|
||||
deps = [
|
||||
"//mediapipe/calculators/core:split_vector_calculator_cc_proto",
|
||||
"//mediapipe/calculators/image:image_clone_calculator_cc_proto",
|
||||
"//mediapipe/calculators/image:image_cropping_calculator",
|
||||
"//mediapipe/calculators/image:image_cropping_calculator_cc_proto",
|
||||
"//mediapipe/calculators/image:warp_affine_calculator",
|
||||
"//mediapipe/calculators/image:warp_affine_calculator_cc_proto",
|
||||
"//mediapipe/calculators/tensor:image_to_tensor_calculator_cc_proto",
|
||||
"//mediapipe/calculators/tensor:inference_calculator",
|
||||
"//mediapipe/calculators/util:detections_to_rects_calculator",
|
||||
"//mediapipe/calculators/util:face_to_rect_calculator",
|
||||
"//mediapipe/calculators/util:landmarks_to_detection_calculator_cc_proto",
|
||||
"//mediapipe/calculators/util:from_image_calculator",
|
||||
"//mediapipe/calculators/util:inverse_matrix_calculator",
|
||||
"//mediapipe/calculators/util:to_image_calculator",
|
||||
"//mediapipe/framework/api2:builder",
|
||||
"//mediapipe/framework/api2:port",
|
||||
"//mediapipe/framework/formats:image",
|
||||
"//mediapipe/framework/formats:landmark_cc_proto",
|
||||
"//mediapipe/framework/formats:rect_cc_proto",
|
||||
"//mediapipe/framework/formats:tensor",
|
||||
"//mediapipe/framework/port:status",
|
||||
"//mediapipe/gpu:gpu_origin_cc_proto",
|
||||
"//mediapipe/tasks/cc:common",
|
||||
"//mediapipe/tasks/cc/components/processors:image_preprocessing_graph",
|
||||
"//mediapipe/tasks/cc/core:model_resources_cache",
|
||||
"//mediapipe/tasks/cc/core:model_task_graph",
|
||||
"//mediapipe/tasks/cc/core/proto:external_file_cc_proto",
|
||||
"//mediapipe/tasks/cc/metadata/utils:zip_utils",
|
||||
"//mediapipe/tasks/cc/vision/face_detector/proto:face_detector_graph_options_cc_proto",
|
||||
"//mediapipe/tasks/cc/vision/face_landmarker:face_landmarker_graph",
|
||||
"//mediapipe/tasks/cc/vision/face_landmarker/proto:face_landmarker_graph_options_cc_proto",
|
||||
"//mediapipe/tasks/cc/vision/face_landmarker/proto:face_landmarks_detector_graph_options_cc_proto",
|
||||
"//mediapipe/tasks/cc/vision/face_stylizer/calculators:strip_rotation_calculator",
|
||||
"//mediapipe/tasks/cc/vision/face_stylizer/calculators:tensors_to_image_calculator",
|
||||
"//mediapipe/tasks/cc/vision/face_stylizer/calculators:tensors_to_image_calculator_cc_proto",
|
||||
"//mediapipe/tasks/cc/vision/face_stylizer/proto:face_stylizer_graph_options_cc_proto",
|
||||
"@com_google_absl//absl/memory",
|
||||
"@com_google_absl//absl/status:statusor",
|
||||
],
|
||||
alwayslink = 1,
|
||||
@@ -64,7 +58,6 @@ cc_library(
|
||||
":face_stylizer_graph", # buildcleaner:keep
|
||||
"//mediapipe/framework/api2:builder",
|
||||
"//mediapipe/framework/formats:image",
|
||||
"//mediapipe/tasks/cc:common",
|
||||
"//mediapipe/tasks/cc/core:base_options",
|
||||
"//mediapipe/tasks/cc/core:utils",
|
||||
"//mediapipe/tasks/cc/vision/core:base_vision_task_api",
|
||||
|
||||
@@ -29,7 +29,6 @@ limitations under the License.
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "mediapipe/framework/api2/builder.h"
|
||||
#include "mediapipe/framework/formats/image.h"
|
||||
#include "mediapipe/tasks/cc/common.h"
|
||||
#include "mediapipe/tasks/cc/core/utils.h"
|
||||
#include "mediapipe/tasks/cc/vision/core/running_mode.h"
|
||||
#include "mediapipe/tasks/cc/vision/core/vision_task_api_factory.h"
|
||||
@@ -114,13 +113,10 @@ absl::StatusOr<std::unique_ptr<FaceStylizer>> FaceStylizer::Create(
|
||||
Packet stylized_image_packet =
|
||||
status_or_packets.value()[kStylizedImageName];
|
||||
Packet image_packet = status_or_packets.value()[kImageOutStreamName];
|
||||
result_callback(
|
||||
stylized_image_packet.IsEmpty()
|
||||
? std::nullopt
|
||||
: std::optional<Image>(stylized_image_packet.Get<Image>()),
|
||||
image_packet.Get<Image>(),
|
||||
stylized_image_packet.Timestamp().Value() /
|
||||
kMicroSecondsPerMilliSecond);
|
||||
result_callback(stylized_image_packet.Get<Image>(),
|
||||
image_packet.Get<Image>(),
|
||||
stylized_image_packet.Timestamp().Value() /
|
||||
kMicroSecondsPerMilliSecond);
|
||||
};
|
||||
}
|
||||
return core::VisionTaskApiFactory::Create<FaceStylizer,
|
||||
@@ -132,7 +128,7 @@ absl::StatusOr<std::unique_ptr<FaceStylizer>> FaceStylizer::Create(
|
||||
std::move(packets_callback));
|
||||
}
|
||||
|
||||
absl::StatusOr<std::optional<Image>> FaceStylizer::Stylize(
|
||||
absl::StatusOr<Image> FaceStylizer::Stylize(
|
||||
mediapipe::Image image,
|
||||
std::optional<core::ImageProcessingOptions> image_processing_options) {
|
||||
if (image.UsesGpu()) {
|
||||
@@ -148,13 +144,10 @@ absl::StatusOr<std::optional<Image>> FaceStylizer::Stylize(
|
||||
ProcessImageData(
|
||||
{{kImageInStreamName, MakePacket<Image>(std::move(image))},
|
||||
{kNormRectName, MakePacket<NormalizedRect>(std::move(norm_rect))}}));
|
||||
return output_packets[kStylizedImageName].IsEmpty()
|
||||
? std::nullopt
|
||||
: std::optional<Image>(
|
||||
output_packets[kStylizedImageName].Get<Image>());
|
||||
return output_packets[kStylizedImageName].Get<Image>();
|
||||
}
|
||||
|
||||
absl::StatusOr<std::optional<Image>> FaceStylizer::StylizeForVideo(
|
||||
absl::StatusOr<Image> FaceStylizer::StylizeForVideo(
|
||||
mediapipe::Image image, int64_t timestamp_ms,
|
||||
std::optional<core::ImageProcessingOptions> image_processing_options) {
|
||||
if (image.UsesGpu()) {
|
||||
@@ -174,10 +167,7 @@ absl::StatusOr<std::optional<Image>> FaceStylizer::StylizeForVideo(
|
||||
{kNormRectName,
|
||||
MakePacket<NormalizedRect>(std::move(norm_rect))
|
||||
.At(Timestamp(timestamp_ms * kMicroSecondsPerMilliSecond))}}));
|
||||
return output_packets[kStylizedImageName].IsEmpty()
|
||||
? std::nullopt
|
||||
: std::optional<Image>(
|
||||
output_packets[kStylizedImageName].Get<Image>());
|
||||
return output_packets[kStylizedImageName].Get<Image>();
|
||||
}
|
||||
|
||||
absl::Status FaceStylizer::StylizeAsync(
|
||||
|
||||
@@ -53,8 +53,7 @@ struct FaceStylizerOptions {
|
||||
// The user-defined result callback for processing live stream data.
|
||||
// The result callback should only be specified when the running mode is set
|
||||
// to RunningMode::LIVE_STREAM.
|
||||
std::function<void(absl::StatusOr<std::optional<mediapipe::Image>>,
|
||||
const Image&, int64_t)>
|
||||
std::function<void(absl::StatusOr<mediapipe::Image>, const Image&, int64_t)>
|
||||
result_callback = nullptr;
|
||||
};
|
||||
|
||||
@@ -82,10 +81,10 @@ class FaceStylizer : tasks::vision::core::BaseVisionTaskApi {
|
||||
// running mode.
|
||||
//
|
||||
// The input image can be of any size with format RGB or RGBA.
|
||||
// When no face is detected on the input image, the method returns a
|
||||
// std::nullopt. Otherwise, returns the stylized image of the most visible
|
||||
// face. The stylized output image size is the same as the model output size.
|
||||
absl::StatusOr<std::optional<mediapipe::Image>> Stylize(
|
||||
// To ensure that the output image has reasonable quality, the stylized output
|
||||
// image size is the smaller of the model output size and the size of the
|
||||
// 'region_of_interest' specified in 'image_processing_options'.
|
||||
absl::StatusOr<mediapipe::Image> Stylize(
|
||||
mediapipe::Image image,
|
||||
std::optional<core::ImageProcessingOptions> image_processing_options =
|
||||
std::nullopt);
|
||||
@@ -107,10 +106,10 @@ class FaceStylizer : tasks::vision::core::BaseVisionTaskApi {
|
||||
// The image can be of any size with format RGB or RGBA. It's required to
|
||||
// provide the video frame's timestamp (in milliseconds). The input timestamps
|
||||
// must be monotonically increasing.
|
||||
// When no face is detected on the input image, the method returns a
|
||||
// std::nullopt. Otherwise, returns the stylized image of the most visible
|
||||
// face. The stylized output image size is the same as the model output size.
|
||||
absl::StatusOr<std::optional<mediapipe::Image>> StylizeForVideo(
|
||||
// To ensure that the output image has reasonable quality, the stylized output
|
||||
// image size is the smaller of the model output size and the size of the
|
||||
// 'region_of_interest' specified in 'image_processing_options'.
|
||||
absl::StatusOr<mediapipe::Image> StylizeForVideo(
|
||||
mediapipe::Image image, int64_t timestamp_ms,
|
||||
std::optional<core::ImageProcessingOptions> image_processing_options =
|
||||
std::nullopt);
|
||||
@@ -137,10 +136,9 @@ class FaceStylizer : tasks::vision::core::BaseVisionTaskApi {
|
||||
// increasing.
|
||||
//
|
||||
// The "result_callback" provides:
|
||||
// - When no face is detected on the input image, the method returns a
|
||||
// std::nullopt. Otherwise, returns the stylized image of the most visible
|
||||
// face. The stylized output image size is the same as the model output
|
||||
// size.
|
||||
// - The stylized image which size is the smaller of the model output size
|
||||
// and the size of the 'region_of_interest' specified in
|
||||
// 'image_processing_options'.
|
||||
// - The input timestamp in milliseconds.
|
||||
absl::Status StylizeAsync(mediapipe::Image image, int64_t timestamp_ms,
|
||||
std::optional<core::ImageProcessingOptions>
|
||||
|
||||
@@ -16,29 +16,20 @@ limitations under the License.
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "mediapipe/calculators/core/split_vector_calculator.pb.h"
|
||||
#include "mediapipe/calculators/image/image_clone_calculator.pb.h"
|
||||
#include "mediapipe/calculators/image/image_cropping_calculator.pb.h"
|
||||
#include "mediapipe/calculators/image/warp_affine_calculator.pb.h"
|
||||
#include "mediapipe/calculators/tensor/image_to_tensor_calculator.pb.h"
|
||||
#include "mediapipe/calculators/util/landmarks_to_detection_calculator.pb.h"
|
||||
#include "mediapipe/framework/api2/builder.h"
|
||||
#include "mediapipe/framework/api2/port.h"
|
||||
#include "mediapipe/framework/formats/image.h"
|
||||
#include "mediapipe/framework/formats/landmark.pb.h"
|
||||
#include "mediapipe/framework/formats/rect.pb.h"
|
||||
#include "mediapipe/framework/formats/tensor.h"
|
||||
#include "mediapipe/framework/port/status_macros.h"
|
||||
#include "mediapipe/gpu/gpu_origin.pb.h"
|
||||
#include "mediapipe/tasks/cc/common.h"
|
||||
#include "mediapipe/tasks/cc/components/processors/image_preprocessing_graph.h"
|
||||
#include "mediapipe/tasks/cc/core/model_resources_cache.h"
|
||||
#include "mediapipe/tasks/cc/core/model_task_graph.h"
|
||||
#include "mediapipe/tasks/cc/core/proto/external_file.pb.h"
|
||||
#include "mediapipe/tasks/cc/metadata/utils/zip_utils.h"
|
||||
#include "mediapipe/tasks/cc/vision/face_detector/proto/face_detector_graph_options.pb.h"
|
||||
#include "mediapipe/tasks/cc/vision/face_landmarker/proto/face_landmarker_graph_options.pb.h"
|
||||
#include "mediapipe/tasks/cc/vision/face_landmarker/proto/face_landmarks_detector_graph_options.pb.h"
|
||||
#include "mediapipe/tasks/cc/vision/face_stylizer/calculators/tensors_to_image_calculator.pb.h"
|
||||
#include "mediapipe/tasks/cc/vision/face_stylizer/proto/face_stylizer_graph_options.pb.h"
|
||||
|
||||
@@ -54,29 +45,17 @@ using ::mediapipe::api2::Output;
|
||||
using ::mediapipe::api2::builder::Graph;
|
||||
using ::mediapipe::api2::builder::Source;
|
||||
using ::mediapipe::tasks::TensorsToImageCalculatorOptions;
|
||||
using ::mediapipe::tasks::core::ModelAssetBundleResources;
|
||||
using ::mediapipe::tasks::core::ModelResources;
|
||||
using ::mediapipe::tasks::core::proto::ExternalFile;
|
||||
using ::mediapipe::tasks::metadata::SetExternalFile;
|
||||
using ::mediapipe::tasks::vision::face_landmarker::proto::
|
||||
FaceLandmarkerGraphOptions;
|
||||
using ::mediapipe::tasks::vision::face_stylizer::proto::
|
||||
FaceStylizerGraphOptions;
|
||||
|
||||
constexpr char kDetectionTag[] = "DETECTION";
|
||||
constexpr char kFaceDetectorTFLiteName[] = "face_detector.tflite";
|
||||
constexpr char kFaceLandmarksDetectorTFLiteName[] =
|
||||
"face_landmarks_detector.tflite";
|
||||
constexpr char kFaceStylizerTFLiteName[] = "face_stylizer.tflite";
|
||||
constexpr char kImageTag[] = "IMAGE";
|
||||
constexpr char kImageCpuTag[] = "IMAGE_CPU";
|
||||
constexpr char kImageGpuTag[] = "IMAGE_GPU";
|
||||
constexpr char kImageSizeTag[] = "IMAGE_SIZE";
|
||||
constexpr char kMatrixTag[] = "MATRIX";
|
||||
constexpr char kNormLandmarksTag[] = "NORM_LANDMARKS";
|
||||
constexpr char kNormRectTag[] = "NORM_RECT";
|
||||
constexpr char kOutputSizeTag[] = "OUTPUT_SIZE";
|
||||
constexpr char kSizeTag[] = "SIZE";
|
||||
constexpr char kStylizedImageTag[] = "STYLIZED_IMAGE";
|
||||
constexpr char kTensorsTag[] = "TENSORS";
|
||||
|
||||
@@ -87,76 +66,6 @@ struct FaceStylizerOutputStreams {
|
||||
Source<Image> original_image;
|
||||
};
|
||||
|
||||
// Sets the base options in the sub tasks.
|
||||
absl::Status SetSubTaskBaseOptions(const ModelAssetBundleResources& resources,
|
||||
FaceStylizerGraphOptions* options,
|
||||
ExternalFile* face_stylizer_external_file,
|
||||
bool is_copy) {
|
||||
auto* face_detector_graph_options =
|
||||
options->mutable_face_landmarker_graph_options()
|
||||
->mutable_face_detector_graph_options();
|
||||
if (!face_detector_graph_options->base_options().has_model_asset()) {
|
||||
ASSIGN_OR_RETURN(const auto face_detector_file,
|
||||
resources.GetFile(kFaceDetectorTFLiteName));
|
||||
SetExternalFile(face_detector_file,
|
||||
face_detector_graph_options->mutable_base_options()
|
||||
->mutable_model_asset(),
|
||||
is_copy);
|
||||
}
|
||||
face_detector_graph_options->mutable_base_options()
|
||||
->mutable_acceleration()
|
||||
->CopyFrom(options->base_options().acceleration());
|
||||
face_detector_graph_options->mutable_base_options()->set_use_stream_mode(
|
||||
options->base_options().use_stream_mode());
|
||||
auto* face_landmarks_detector_graph_options =
|
||||
options->mutable_face_landmarker_graph_options()
|
||||
->mutable_face_landmarks_detector_graph_options();
|
||||
if (!face_landmarks_detector_graph_options->base_options()
|
||||
.has_model_asset()) {
|
||||
ASSIGN_OR_RETURN(const auto face_landmarks_detector_file,
|
||||
resources.GetFile(kFaceLandmarksDetectorTFLiteName));
|
||||
SetExternalFile(
|
||||
face_landmarks_detector_file,
|
||||
face_landmarks_detector_graph_options->mutable_base_options()
|
||||
->mutable_model_asset(),
|
||||
is_copy);
|
||||
}
|
||||
face_landmarks_detector_graph_options->mutable_base_options()
|
||||
->mutable_acceleration()
|
||||
->CopyFrom(options->base_options().acceleration());
|
||||
face_landmarks_detector_graph_options->mutable_base_options()
|
||||
->set_use_stream_mode(options->base_options().use_stream_mode());
|
||||
|
||||
ASSIGN_OR_RETURN(const auto face_stylizer_file,
|
||||
resources.GetFile(kFaceStylizerTFLiteName));
|
||||
SetExternalFile(face_stylizer_file, face_stylizer_external_file, is_copy);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void ConfigureSplitNormalizedLandmarkListVectorCalculator(
|
||||
mediapipe::SplitVectorCalculatorOptions* options) {
|
||||
auto* vector_range = options->add_ranges();
|
||||
vector_range->set_begin(0);
|
||||
vector_range->set_end(1);
|
||||
options->set_element_only(true);
|
||||
}
|
||||
|
||||
void ConfigureLandmarksToDetectionCalculator(
|
||||
LandmarksToDetectionCalculatorOptions* options) {
|
||||
// left eye
|
||||
options->add_selected_landmark_indices(33);
|
||||
// left eye
|
||||
options->add_selected_landmark_indices(133);
|
||||
// right eye
|
||||
options->add_selected_landmark_indices(263);
|
||||
// right eye
|
||||
options->add_selected_landmark_indices(362);
|
||||
// mouth
|
||||
options->add_selected_landmark_indices(61);
|
||||
// mouth
|
||||
options->add_selected_landmark_indices(291);
|
||||
}
|
||||
|
||||
void ConfigureTensorsToImageCalculator(
|
||||
const ImageToTensorCalculatorOptions& image_to_tensor_options,
|
||||
TensorsToImageCalculatorOptions* tensors_to_image_options) {
|
||||
@@ -180,7 +89,7 @@ void ConfigureTensorsToImageCalculator(
|
||||
} // namespace
|
||||
|
||||
// A "mediapipe.tasks.vision.face_stylizer.FaceStylizerGraph" performs face
|
||||
// stylization on the detected face image.
|
||||
// stylization.
|
||||
//
|
||||
// Inputs:
|
||||
// IMAGE - Image
|
||||
@@ -205,7 +114,7 @@ void ConfigureTensorsToImageCalculator(
|
||||
// {
|
||||
// base_options {
|
||||
// model_asset {
|
||||
// file_name: "face_stylizer.task"
|
||||
// file_name: "face_stylization.tflite"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
@@ -215,94 +124,25 @@ class FaceStylizerGraph : public core::ModelTaskGraph {
|
||||
public:
|
||||
absl::StatusOr<CalculatorGraphConfig> GetConfig(
|
||||
SubgraphContext* sc) override {
|
||||
ASSIGN_OR_RETURN(
|
||||
const auto* model_asset_bundle_resources,
|
||||
CreateModelAssetBundleResources<FaceStylizerGraphOptions>(sc));
|
||||
// Copies the file content instead of passing the pointer of file in
|
||||
// memory if the subgraph model resource service is not available.
|
||||
auto face_stylizer_external_file = absl::make_unique<ExternalFile>();
|
||||
MP_RETURN_IF_ERROR(SetSubTaskBaseOptions(
|
||||
*model_asset_bundle_resources,
|
||||
sc->MutableOptions<FaceStylizerGraphOptions>(),
|
||||
face_stylizer_external_file.get(),
|
||||
!sc->Service(::mediapipe::tasks::core::kModelResourcesCacheService)
|
||||
.IsAvailable()));
|
||||
ASSIGN_OR_RETURN(const auto* model_resources,
|
||||
CreateModelResources<FaceStylizerGraphOptions>(sc));
|
||||
Graph graph;
|
||||
ASSIGN_OR_RETURN(
|
||||
auto face_landmark_lists,
|
||||
BuildFaceLandmarkerGraph(
|
||||
sc->MutableOptions<FaceStylizerGraphOptions>()
|
||||
->mutable_face_landmarker_graph_options(),
|
||||
auto output_streams,
|
||||
BuildFaceStylizerGraph(
|
||||
sc->Options<FaceStylizerGraphOptions>(), *model_resources,
|
||||
graph[Input<Image>(kImageTag)],
|
||||
graph[Input<NormalizedRect>::Optional(kNormRectTag)], graph));
|
||||
ASSIGN_OR_RETURN(
|
||||
const auto* model_resources,
|
||||
CreateModelResources(sc, std::move(face_stylizer_external_file)));
|
||||
ASSIGN_OR_RETURN(
|
||||
auto output_streams,
|
||||
BuildFaceStylizerGraph(sc->Options<FaceStylizerGraphOptions>(),
|
||||
*model_resources, graph[Input<Image>(kImageTag)],
|
||||
face_landmark_lists, graph));
|
||||
output_streams.stylized_image >> graph[Output<Image>(kStylizedImageTag)];
|
||||
output_streams.original_image >> graph[Output<Image>(kImageTag)];
|
||||
return graph.GetConfig();
|
||||
}
|
||||
|
||||
private:
|
||||
absl::StatusOr<Source<std::vector<NormalizedLandmarkList>>>
|
||||
BuildFaceLandmarkerGraph(FaceLandmarkerGraphOptions* face_landmarker_options,
|
||||
Source<Image> image_in,
|
||||
Source<NormalizedRect> norm_rect_in, Graph& graph) {
|
||||
auto& landmarker_graph = graph.AddNode(
|
||||
"mediapipe.tasks.vision.face_landmarker.FaceLandmarkerGraph");
|
||||
|
||||
if (face_landmarker_options->face_detector_graph_options()
|
||||
.has_num_faces() &&
|
||||
face_landmarker_options->face_detector_graph_options().num_faces() !=
|
||||
1) {
|
||||
return CreateStatusWithPayload(
|
||||
absl::StatusCode::kInvalidArgument,
|
||||
"Face stylizer currently only supports one face.",
|
||||
MediaPipeTasksStatus::kInvalidArgumentError);
|
||||
}
|
||||
face_landmarker_options->mutable_face_detector_graph_options()
|
||||
->set_num_faces(1);
|
||||
image_in >> landmarker_graph.In(kImageTag);
|
||||
norm_rect_in >> landmarker_graph.In(kNormRectTag);
|
||||
landmarker_graph.GetOptions<FaceLandmarkerGraphOptions>().Swap(
|
||||
face_landmarker_options);
|
||||
return landmarker_graph.Out(kNormLandmarksTag)
|
||||
.Cast<std::vector<NormalizedLandmarkList>>();
|
||||
}
|
||||
|
||||
absl::StatusOr<FaceStylizerOutputStreams> BuildFaceStylizerGraph(
|
||||
const FaceStylizerGraphOptions& task_options,
|
||||
const ModelResources& model_resources, Source<Image> image_in,
|
||||
Source<std::vector<NormalizedLandmarkList>> face_landmark_lists,
|
||||
Graph& graph) {
|
||||
auto& split_face_landmark_list =
|
||||
graph.AddNode("SplitNormalizedLandmarkListVectorCalculator");
|
||||
ConfigureSplitNormalizedLandmarkListVectorCalculator(
|
||||
&split_face_landmark_list
|
||||
.GetOptions<mediapipe::SplitVectorCalculatorOptions>());
|
||||
face_landmark_lists >> split_face_landmark_list.In("");
|
||||
auto face_landmarks = split_face_landmark_list.Out("");
|
||||
|
||||
auto& landmarks_to_detection =
|
||||
graph.AddNode("LandmarksToDetectionCalculator");
|
||||
ConfigureLandmarksToDetectionCalculator(
|
||||
&landmarks_to_detection
|
||||
.GetOptions<LandmarksToDetectionCalculatorOptions>());
|
||||
face_landmarks >> landmarks_to_detection.In(kNormLandmarksTag);
|
||||
auto face_detection = landmarks_to_detection.Out(kDetectionTag);
|
||||
|
||||
auto& get_image_size = graph.AddNode("ImagePropertiesCalculator");
|
||||
image_in >> get_image_size.In(kImageTag);
|
||||
auto image_size = get_image_size.Out(kSizeTag);
|
||||
auto& face_to_rect = graph.AddNode("FaceToRectCalculator");
|
||||
face_detection >> face_to_rect.In(kDetectionTag);
|
||||
image_size >> face_to_rect.In(kImageSizeTag);
|
||||
auto face_rect = face_to_rect.Out(kNormRectTag);
|
||||
Source<NormalizedRect> norm_rect_in, Graph& graph) {
|
||||
// Adds preprocessing calculators and connects them to the graph input image
|
||||
// stream.
|
||||
auto& preprocessing = graph.AddNode(
|
||||
@@ -323,8 +163,10 @@ class FaceStylizerGraph : public core::ModelTaskGraph {
|
||||
image_to_tensor_options.set_border_mode(
|
||||
mediapipe::ImageToTensorCalculatorOptions::BORDER_ZERO);
|
||||
image_in >> preprocessing.In(kImageTag);
|
||||
face_rect >> preprocessing.In(kNormRectTag);
|
||||
norm_rect_in >> preprocessing.In(kNormRectTag);
|
||||
auto preprocessed_tensors = preprocessing.Out(kTensorsTag);
|
||||
auto transform_matrix = preprocessing.Out(kMatrixTag);
|
||||
auto image_size = preprocessing.Out(kImageSizeTag);
|
||||
|
||||
// Adds inference subgraph and connects its input stream to the output
|
||||
// tensors produced by the ImageToTensorCalculator.
|
||||
@@ -342,12 +184,53 @@ class FaceStylizerGraph : public core::ModelTaskGraph {
|
||||
model_output_tensors >> tensors_to_image.In(kTensorsTag);
|
||||
auto tensor_image = tensors_to_image.Out(kImageTag);
|
||||
|
||||
auto& image_converter = graph.AddNode("ImageCloneCalculator");
|
||||
image_converter.GetOptions<mediapipe::ImageCloneCalculatorOptions>()
|
||||
.set_output_on_gpu(false);
|
||||
tensor_image >> image_converter.In("");
|
||||
auto& inverse_matrix = graph.AddNode("InverseMatrixCalculator");
|
||||
transform_matrix >> inverse_matrix.In(kMatrixTag);
|
||||
auto inverse_transform_matrix = inverse_matrix.Out(kMatrixTag);
|
||||
|
||||
return {{/*stylized_image=*/image_converter.Out("").Cast<Image>(),
|
||||
auto& warp_affine = graph.AddNode("WarpAffineCalculator");
|
||||
auto& warp_affine_options =
|
||||
warp_affine.GetOptions<WarpAffineCalculatorOptions>();
|
||||
warp_affine_options.set_border_mode(
|
||||
WarpAffineCalculatorOptions::BORDER_ZERO);
|
||||
warp_affine_options.set_gpu_origin(mediapipe::GpuOrigin_Mode_TOP_LEFT);
|
||||
tensor_image >> warp_affine.In(kImageTag);
|
||||
inverse_transform_matrix >> warp_affine.In(kMatrixTag);
|
||||
image_size >> warp_affine.In(kOutputSizeTag);
|
||||
auto image_to_crop = warp_affine.Out(kImageTag);
|
||||
|
||||
// The following calculators are for cropping and resizing the output image
|
||||
// based on the roi and the model output size. As the WarpAffineCalculator
|
||||
// rotates the image based on the transform matrix, the rotation info in the
|
||||
// rect proto is stripped to prevent the ImageCroppingCalculator from
|
||||
// performing extra rotation.
|
||||
auto& strip_rotation =
|
||||
graph.AddNode("mediapipe.tasks.StripRotationCalculator");
|
||||
norm_rect_in >> strip_rotation.In(kNormRectTag);
|
||||
auto norm_rect_no_rotation = strip_rotation.Out(kNormRectTag);
|
||||
auto& from_image = graph.AddNode("FromImageCalculator");
|
||||
image_to_crop >> from_image.In(kImageTag);
|
||||
auto& image_cropping = graph.AddNode("ImageCroppingCalculator");
|
||||
auto& image_cropping_opts =
|
||||
image_cropping.GetOptions<ImageCroppingCalculatorOptions>();
|
||||
image_cropping_opts.set_output_max_width(
|
||||
image_to_tensor_options.output_tensor_width());
|
||||
image_cropping_opts.set_output_max_height(
|
||||
image_to_tensor_options.output_tensor_height());
|
||||
norm_rect_no_rotation >> image_cropping.In(kNormRectTag);
|
||||
auto& to_image = graph.AddNode("ToImageCalculator");
|
||||
// ImageCroppingCalculator currently doesn't support mediapipe::Image, the
|
||||
// graph selects its cpu or gpu path based on the image preprocessing
|
||||
// backend.
|
||||
if (use_gpu) {
|
||||
from_image.Out(kImageGpuTag) >> image_cropping.In(kImageGpuTag);
|
||||
image_cropping.Out(kImageGpuTag) >> to_image.In(kImageGpuTag);
|
||||
} else {
|
||||
from_image.Out(kImageCpuTag) >> image_cropping.In(kImageTag);
|
||||
image_cropping.Out(kImageTag) >> to_image.In(kImageCpuTag);
|
||||
}
|
||||
|
||||
return {{/*stylized_image=*/to_image.Out(kImageTag).Cast<Image>(),
|
||||
/*original_image=*/preprocessing.Out(kImageTag).Cast<Image>()}};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -27,6 +27,5 @@ mediapipe_proto_library(
|
||||
"//mediapipe/framework:calculator_options_proto",
|
||||
"//mediapipe/framework:calculator_proto",
|
||||
"//mediapipe/tasks/cc/core/proto:base_options_proto",
|
||||
"//mediapipe/tasks/cc/vision/face_landmarker/proto:face_landmarker_graph_options_proto",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -20,7 +20,6 @@ package mediapipe.tasks.vision.face_stylizer.proto;
|
||||
import "mediapipe/framework/calculator.proto";
|
||||
import "mediapipe/framework/calculator_options.proto";
|
||||
import "mediapipe/tasks/cc/core/proto/base_options.proto";
|
||||
import "mediapipe/tasks/cc/vision/face_landmarker/proto/face_landmarker_graph_options.proto";
|
||||
|
||||
option java_package = "com.google.mediapipe.tasks.vision.facestylizer.proto";
|
||||
option java_outer_classname = "FaceStylizerGraphOptionsProto";
|
||||
@@ -32,8 +31,4 @@ message FaceStylizerGraphOptions {
|
||||
// Base options for configuring face stylizer, such as specifying the TfLite
|
||||
// model file with metadata, accelerator options, etc.
|
||||
optional core.proto.BaseOptions base_options = 1;
|
||||
|
||||
// Options for face landmarker graph.
|
||||
optional vision.face_landmarker.proto.FaceLandmarkerGraphOptions
|
||||
face_landmarker_graph_options = 2;
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ absl::StatusOr<GestureRecognizerResult> GestureRecognizer::Recognize(
|
||||
}
|
||||
|
||||
absl::StatusOr<GestureRecognizerResult> GestureRecognizer::RecognizeForVideo(
|
||||
mediapipe::Image image, int64_t timestamp_ms,
|
||||
mediapipe::Image image, int64 timestamp_ms,
|
||||
std::optional<core::ImageProcessingOptions> image_processing_options) {
|
||||
if (image.UsesGpu()) {
|
||||
return CreateStatusWithPayload(
|
||||
@@ -289,7 +289,7 @@ absl::StatusOr<GestureRecognizerResult> GestureRecognizer::RecognizeForVideo(
|
||||
}
|
||||
|
||||
absl::Status GestureRecognizer::RecognizeAsync(
|
||||
mediapipe::Image image, int64_t timestamp_ms,
|
||||
mediapipe::Image image, int64 timestamp_ms,
|
||||
std::optional<core::ImageProcessingOptions> image_processing_options) {
|
||||
if (image.UsesGpu()) {
|
||||
return CreateStatusWithPayload(
|
||||
|
||||
@@ -43,7 +43,7 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/vision/hand_landmarker/proto/hand_landmarks_detector_graph_options.pb.h"
|
||||
#include "mediapipe/tasks/cc/vision/utils/image_utils.h"
|
||||
#include "tensorflow/lite/c/common.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -137,7 +137,7 @@ absl::StatusOr<std::unique_ptr<TaskRunner>> CreateTaskRunner() {
|
||||
graph.GetConfig(), absl::make_unique<core::MediaPipeBuiltinOpResolver>());
|
||||
}
|
||||
|
||||
class HandLandmarkerTest : public tflite::testing::Test {};
|
||||
class HandLandmarkerTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(HandLandmarkerTest, Succeeds) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(
|
||||
|
||||
@@ -41,7 +41,7 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/vision/core/image_processing_options.h"
|
||||
#include "mediapipe/tasks/cc/vision/hand_landmarker/hand_landmarker_result.h"
|
||||
#include "mediapipe/tasks/cc/vision/utils/image_utils.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
|
||||
@@ -146,7 +146,7 @@ absl::StatusOr<std::unique_ptr<TaskRunner>> CreateSingleHandTaskRunner(
|
||||
|
||||
return TaskRunner::Create(
|
||||
graph.GetConfig(),
|
||||
absl::make_unique<tflite::ops::builtin::BuiltinOpResolver>());
|
||||
absl::make_unique<tflite_shims::ops::builtin::BuiltinOpResolver>());
|
||||
}
|
||||
|
||||
// Helper function to create a Multi Hand Landmark TaskRunner.
|
||||
@@ -188,7 +188,7 @@ absl::StatusOr<std::unique_ptr<TaskRunner>> CreateMultiHandTaskRunner(
|
||||
|
||||
return TaskRunner::Create(
|
||||
graph.GetConfig(),
|
||||
absl::make_unique<tflite::ops::builtin::BuiltinOpResolver>());
|
||||
absl::make_unique<tflite_shims::ops::builtin::BuiltinOpResolver>());
|
||||
}
|
||||
|
||||
NormalizedLandmarkList GetExpectedLandmarkList(absl::string_view filename) {
|
||||
|
||||
@@ -39,9 +39,9 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/vision/core/running_mode.h"
|
||||
#include "mediapipe/tasks/cc/vision/utils/image_utils.h"
|
||||
#include "tensorflow/lite/core/api/op_resolver.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
#include "tensorflow/lite/kernels/builtin_op_kernels.h"
|
||||
#include "tensorflow/lite/mutable_op_resolver.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -148,7 +148,7 @@ class MobileNetQuantizedOpResolverMissingOps
|
||||
const MobileNetQuantizedOpResolverMissingOps& r) = delete;
|
||||
};
|
||||
|
||||
class CreateTest : public tflite::testing::Test {};
|
||||
class CreateTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(CreateTest, SucceedsWithSelectiveOpResolver) {
|
||||
auto options = std::make_unique<ImageClassifierOptions>();
|
||||
@@ -265,7 +265,7 @@ TEST_F(CreateTest, FailsWithMissingCallbackInLiveStreamMode) {
|
||||
MediaPipeTasksStatus::kInvalidTaskGraphConfigError))));
|
||||
}
|
||||
|
||||
class ImageModeTest : public tflite::testing::Test {};
|
||||
class ImageModeTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(ImageModeTest, FailsWithCallingWrongMethod) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(
|
||||
@@ -605,7 +605,7 @@ TEST_F(ImageModeTest, FailsWithInvalidImageProcessingOptions) {
|
||||
MediaPipeTasksStatus::kImageProcessingInvalidArgumentError))));
|
||||
}
|
||||
|
||||
class VideoModeTest : public tflite::testing::Test {};
|
||||
class VideoModeTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(VideoModeTest, FailsWithCallingWrongMethod) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(
|
||||
@@ -707,7 +707,7 @@ TEST_F(VideoModeTest, SucceedsWithRegionOfInterest) {
|
||||
MP_ASSERT_OK(image_classifier->Close());
|
||||
}
|
||||
|
||||
class LiveStreamModeTest : public tflite::testing::Test {};
|
||||
class LiveStreamModeTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(LiveStreamModeTest, FailsWithCallingWrongMethod) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(
|
||||
|
||||
@@ -30,9 +30,9 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/vision/core/running_mode.h"
|
||||
#include "mediapipe/tasks/cc/vision/utils/image_utils.h"
|
||||
#include "tensorflow/lite/core/api/op_resolver.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
#include "tensorflow/lite/kernels/builtin_op_kernels.h"
|
||||
#include "tensorflow/lite/mutable_op_resolver.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -103,7 +103,7 @@ class MobileNetV3OpResolverMissingOps : public ::tflite::MutableOpResolver {
|
||||
delete;
|
||||
};
|
||||
|
||||
class CreateTest : public tflite::testing::Test {};
|
||||
class CreateTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(CreateTest, SucceedsWithSelectiveOpResolver) {
|
||||
auto options = std::make_unique<ImageEmbedderOptions>();
|
||||
@@ -181,7 +181,7 @@ TEST_F(CreateTest, FailsWithMissingCallbackInLiveStreamMode) {
|
||||
MediaPipeTasksStatus::kInvalidTaskGraphConfigError))));
|
||||
}
|
||||
|
||||
class ImageModeTest : public tflite::testing::Test {};
|
||||
class ImageModeTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(ImageModeTest, FailsWithCallingWrongMethod) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(
|
||||
@@ -410,7 +410,7 @@ TEST_F(ImageModeTest, SucceedsWithRegionOfInterestAndRotation) {
|
||||
EXPECT_LE(abs(similarity - expected_similarity), kSimilarityTolerancy);
|
||||
}
|
||||
|
||||
class VideoModeTest : public tflite::testing::Test {};
|
||||
class VideoModeTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(VideoModeTest, FailsWithCallingWrongMethod) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(
|
||||
@@ -494,7 +494,7 @@ TEST_F(VideoModeTest, Succeeds) {
|
||||
MP_ASSERT_OK(image_embedder->Close());
|
||||
}
|
||||
|
||||
class LiveStreamModeTest : public tflite::testing::Test {};
|
||||
class LiveStreamModeTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(LiveStreamModeTest, FailsWithCallingWrongMethod) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(
|
||||
|
||||
@@ -39,9 +39,9 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/vision/image_segmenter/image_segmenter_result.h"
|
||||
#include "mediapipe/tasks/cc/vision/image_segmenter/proto/image_segmenter_graph_options.pb.h"
|
||||
#include "mediapipe/tasks/cc/vision/utils/image_utils.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
#include "tensorflow/lite/kernels/builtin_op_kernels.h"
|
||||
#include "tensorflow/lite/mutable_op_resolver.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -180,7 +180,7 @@ class DeepLabOpResolver : public ::tflite::MutableOpResolver {
|
||||
DeepLabOpResolver(const DeepLabOpResolver& r) = delete;
|
||||
};
|
||||
|
||||
class CreateFromOptionsTest : public tflite::testing::Test {};
|
||||
class CreateFromOptionsTest : public tflite_shims::testing::Test {};
|
||||
|
||||
class DeepLabOpResolverMissingOps : public ::tflite::MutableOpResolver {
|
||||
public:
|
||||
@@ -268,7 +268,7 @@ TEST(GetLabelsTest, SucceedsWithLabelsInModel) {
|
||||
}
|
||||
}
|
||||
|
||||
class ImageModeTest : public tflite::testing::Test {};
|
||||
class ImageModeTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(ImageModeTest, SucceedsWithCategoryMask) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(
|
||||
@@ -521,7 +521,7 @@ TEST_F(ImageModeTest, SucceedsHairSegmentation) {
|
||||
SimilarToFloatMask(expected_mask_float, kGoldenMaskSimilarity));
|
||||
}
|
||||
|
||||
class VideoModeTest : public tflite::testing::Test {};
|
||||
class VideoModeTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(VideoModeTest, FailsWithCallingWrongMethod) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(
|
||||
@@ -581,7 +581,7 @@ TEST_F(VideoModeTest, Succeeds) {
|
||||
MP_ASSERT_OK(segmenter->Close());
|
||||
}
|
||||
|
||||
class LiveStreamModeTest : public tflite::testing::Test {};
|
||||
class LiveStreamModeTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(LiveStreamModeTest, FailsWithCallingWrongMethod) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(Image image, DecodeImageFromFile(JoinPath(
|
||||
|
||||
@@ -39,9 +39,9 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/vision/image_segmenter/calculators/tensors_to_segmentation_calculator.pb.h"
|
||||
#include "mediapipe/tasks/cc/vision/image_segmenter/proto/image_segmenter_graph_options.pb.h"
|
||||
#include "mediapipe/tasks/cc/vision/utils/image_utils.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
#include "tensorflow/lite/kernels/builtin_op_kernels.h"
|
||||
#include "tensorflow/lite/mutable_op_resolver.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "testing/base/public/gmock.h"
|
||||
|
||||
namespace mediapipe {
|
||||
@@ -124,7 +124,7 @@ MATCHER_P3(SimilarToUint8Mask, expected_mask, similarity_threshold,
|
||||
similarity_threshold;
|
||||
}
|
||||
|
||||
class CreateFromOptionsTest : public tflite::testing::Test {};
|
||||
class CreateFromOptionsTest : public tflite_shims::testing::Test {};
|
||||
|
||||
class DeepLabOpResolverMissingOps : public ::tflite::MutableOpResolver {
|
||||
public:
|
||||
@@ -261,7 +261,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
[](const ::testing::TestParamInfo<SucceedSegmentationWithRoi::ParamType>&
|
||||
info) { return info.param.test_name; });
|
||||
|
||||
class ImageModeTest : public tflite::testing::Test {};
|
||||
class ImageModeTest : public tflite_shims::testing::Test {};
|
||||
|
||||
// TODO: fix this unit test after image segmenter handled post
|
||||
// processing correctly with rotated image.
|
||||
|
||||
@@ -43,9 +43,9 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/vision/utils/image_utils.h"
|
||||
#include "tensorflow/lite/c/common.h"
|
||||
#include "tensorflow/lite/core/api/op_resolver.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
#include "tensorflow/lite/kernels/builtin_op_kernels.h"
|
||||
#include "tensorflow/lite/mutable_op_resolver.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
|
||||
namespace tflite {
|
||||
namespace ops {
|
||||
@@ -159,7 +159,7 @@ class MobileSsdQuantizedOpResolver : public ::tflite::MutableOpResolver {
|
||||
MobileSsdQuantizedOpResolver(const MobileSsdQuantizedOpResolver& r) = delete;
|
||||
};
|
||||
|
||||
class CreateFromOptionsTest : public tflite::testing::Test {};
|
||||
class CreateFromOptionsTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(CreateFromOptionsTest, SucceedsWithSelectiveOpResolver) {
|
||||
auto options = std::make_unique<ObjectDetectorOptions>();
|
||||
@@ -332,7 +332,7 @@ TEST_F(CreateFromOptionsTest, InputTensorSpecsForEfficientDetModel) {
|
||||
// TODO: Add NumThreadsTest back after having an
|
||||
// "acceleration configuration" field in the ObjectDetectorOptions.
|
||||
|
||||
class ImageModeTest : public tflite::testing::Test {};
|
||||
class ImageModeTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(ImageModeTest, FailsWithCallingWrongMethod) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(Image image, DecodeImageFromFile(JoinPath(
|
||||
@@ -618,7 +618,7 @@ TEST_F(ImageModeTest, FailsWithRegionOfInterest) {
|
||||
MediaPipeTasksStatus::kImageProcessingInvalidArgumentError))));
|
||||
}
|
||||
|
||||
class VideoModeTest : public tflite::testing::Test {};
|
||||
class VideoModeTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(VideoModeTest, FailsWithCallingWrongMethod) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(Image image, DecodeImageFromFile(JoinPath(
|
||||
@@ -673,7 +673,7 @@ TEST_F(VideoModeTest, Succeeds) {
|
||||
MP_ASSERT_OK(object_detector->Close());
|
||||
}
|
||||
|
||||
class LiveStreamModeTest : public tflite::testing::Test {};
|
||||
class LiveStreamModeTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(LiveStreamModeTest, FailsWithCallingWrongMethod) {
|
||||
MP_ASSERT_OK_AND_ASSIGN(Image image, DecodeImageFromFile(JoinPath(
|
||||
|
||||
@@ -97,10 +97,8 @@ cc_library(
|
||||
"//mediapipe/tasks/cc/core:model_task_graph",
|
||||
"//mediapipe/tasks/cc/vision/pose_landmarker/proto:pose_landmarks_detector_graph_options_cc_proto",
|
||||
"//mediapipe/tasks/cc/vision/utils:image_tensor_specs",
|
||||
"//mediapipe/util:graph_builder_utils",
|
||||
"@com_google_absl//absl/status:statusor",
|
||||
],
|
||||
alwayslink = 1,
|
||||
)
|
||||
|
||||
cc_library(
|
||||
|
||||
@@ -73,12 +73,14 @@ constexpr int kMicroSecondsPerMilliSecond = 1000;
|
||||
// limit the number of frames in flight.
|
||||
CalculatorGraphConfig CreateGraphConfig(
|
||||
std::unique_ptr<PoseLandmarkerGraphOptionsProto> options,
|
||||
bool enable_flow_limiting, bool output_segmentation_masks) {
|
||||
bool enable_flow_limiting) {
|
||||
api2::builder::Graph graph;
|
||||
auto& subgraph = graph.AddNode(kPoseLandmarkerGraphTypeName);
|
||||
subgraph.GetOptions<PoseLandmarkerGraphOptionsProto>().Swap(options.get());
|
||||
graph.In(kImageTag).SetName(kImageInStreamName);
|
||||
graph.In(kNormRectTag).SetName(kNormRectStreamName);
|
||||
subgraph.Out(kSegmentationMaskTag).SetName(kSegmentationMaskStreamName) >>
|
||||
graph.Out(kSegmentationMaskTag);
|
||||
subgraph.Out(kNormLandmarksTag).SetName(kNormLandmarksStreamName) >>
|
||||
graph.Out(kNormLandmarksTag);
|
||||
subgraph.Out(kPoseWorldLandmarksTag).SetName(kPoseWorldLandmarksStreamName) >>
|
||||
@@ -87,10 +89,6 @@ CalculatorGraphConfig CreateGraphConfig(
|
||||
.SetName(kPoseAuxiliaryLandmarksStreamName) >>
|
||||
graph.Out(kPoseAuxiliaryLandmarksTag);
|
||||
subgraph.Out(kImageTag).SetName(kImageOutStreamName) >> graph.Out(kImageTag);
|
||||
if (output_segmentation_masks) {
|
||||
subgraph.Out(kSegmentationMaskTag).SetName(kSegmentationMaskStreamName) >>
|
||||
graph.Out(kSegmentationMaskTag);
|
||||
}
|
||||
if (enable_flow_limiting) {
|
||||
return tasks::core::AddFlowLimiterCalculator(
|
||||
graph, subgraph, {kImageTag, kNormRectTag}, kNormLandmarksTag);
|
||||
@@ -189,8 +187,7 @@ absl::StatusOr<std::unique_ptr<PoseLandmarker>> PoseLandmarker::Create(
|
||||
PoseLandmarkerGraphOptionsProto>(
|
||||
CreateGraphConfig(
|
||||
std::move(options_proto),
|
||||
options->running_mode == core::RunningMode::LIVE_STREAM,
|
||||
options->output_segmentation_masks),
|
||||
options->running_mode == core::RunningMode::LIVE_STREAM),
|
||||
std::move(options->base_options.op_resolver), options->running_mode,
|
||||
std::move(packets_callback))));
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ struct PoseLandmarkerOutputs {
|
||||
Source<std::vector<NormalizedLandmarkList>> auxiliary_landmark_lists;
|
||||
Source<std::vector<NormalizedRect>> pose_rects_next_frame;
|
||||
Source<std::vector<Detection>> pose_detections;
|
||||
std::optional<Source<std::vector<Image>>> segmentation_masks;
|
||||
Source<std::vector<Image>> segmentation_masks;
|
||||
Source<Image> image;
|
||||
};
|
||||
|
||||
@@ -183,8 +183,8 @@ absl::Status SetSubTaskBaseOptions(const ModelAssetBundleResources& resources,
|
||||
// input_stream: "IMAGE:image_in"
|
||||
// input_stream: "NORM_RECT:norm_rect"
|
||||
// output_stream: "NORM_LANDMARKS:pose_landmarks"
|
||||
// output_stream: "WORLD_LANDMARKS:world_landmarks"
|
||||
// output_stream: "AUXILIARY_LANDMARKS:auxiliary_landmarks"
|
||||
// output_stream: "LANDMARKS:world_landmarks"
|
||||
// output_stream: "NORM_LANDMAKRS:auxiliary_landmarks"
|
||||
// output_stream: "POSE_RECTS_NEXT_FRAME:pose_rects_next_frame"
|
||||
// output_stream: "POSE_RECTS:pose_rects"
|
||||
// output_stream: "SEGMENTATION_MASK:segmentation_masks"
|
||||
@@ -212,8 +212,6 @@ class PoseLandmarkerGraph : public core::ModelTaskGraph {
|
||||
absl::StatusOr<CalculatorGraphConfig> GetConfig(
|
||||
SubgraphContext* sc) override {
|
||||
Graph graph;
|
||||
bool output_segmentation_masks =
|
||||
HasOutput(sc->OriginalNode(), kSegmentationMaskTag);
|
||||
if (sc->Options<PoseLandmarkerGraphOptions>()
|
||||
.base_options()
|
||||
.has_model_asset()) {
|
||||
@@ -228,12 +226,12 @@ class PoseLandmarkerGraph : public core::ModelTaskGraph {
|
||||
!sc->Service(::mediapipe::tasks::core::kModelResourcesCacheService)
|
||||
.IsAvailable()));
|
||||
}
|
||||
ASSIGN_OR_RETURN(auto outs,
|
||||
BuildPoseLandmarkerGraph(
|
||||
*sc->MutableOptions<PoseLandmarkerGraphOptions>(),
|
||||
graph[Input<Image>(kImageTag)],
|
||||
graph[Input<NormalizedRect>::Optional(kNormRectTag)],
|
||||
graph, output_segmentation_masks));
|
||||
ASSIGN_OR_RETURN(
|
||||
auto outs,
|
||||
BuildPoseLandmarkerGraph(
|
||||
*sc->MutableOptions<PoseLandmarkerGraphOptions>(),
|
||||
graph[Input<Image>(kImageTag)],
|
||||
graph[Input<NormalizedRect>::Optional(kNormRectTag)], graph));
|
||||
outs.landmark_lists >>
|
||||
graph[Output<std::vector<NormalizedLandmarkList>>(kNormLandmarksTag)];
|
||||
outs.world_landmark_lists >>
|
||||
@@ -243,13 +241,11 @@ class PoseLandmarkerGraph : public core::ModelTaskGraph {
|
||||
kAuxiliaryLandmarksTag)];
|
||||
outs.pose_rects_next_frame >>
|
||||
graph[Output<std::vector<NormalizedRect>>(kPoseRectsNextFrameTag)];
|
||||
outs.segmentation_masks >>
|
||||
graph[Output<std::vector<Image>>(kSegmentationMaskTag)];
|
||||
outs.pose_detections >>
|
||||
graph[Output<std::vector<Detection>>(kDetectionsTag)];
|
||||
outs.image >> graph[Output<Image>(kImageTag)];
|
||||
if (outs.segmentation_masks) {
|
||||
*outs.segmentation_masks >>
|
||||
graph[Output<std::vector<Image>>(kSegmentationMaskTag)];
|
||||
}
|
||||
|
||||
// TODO remove when support is fixed.
|
||||
// As mediapipe GraphBuilder currently doesn't support configuring
|
||||
@@ -276,8 +272,7 @@ class PoseLandmarkerGraph : public core::ModelTaskGraph {
|
||||
// graph: the mediapipe graph instance to be updated.
|
||||
absl::StatusOr<PoseLandmarkerOutputs> BuildPoseLandmarkerGraph(
|
||||
PoseLandmarkerGraphOptions& tasks_options, Source<Image> image_in,
|
||||
Source<NormalizedRect> norm_rect_in, Graph& graph,
|
||||
bool output_segmentation_masks) {
|
||||
Source<NormalizedRect> norm_rect_in, Graph& graph) {
|
||||
const int max_num_poses =
|
||||
tasks_options.pose_detector_graph_options().num_poses();
|
||||
|
||||
@@ -312,12 +307,9 @@ class PoseLandmarkerGraph : public core::ModelTaskGraph {
|
||||
auto pose_rects_for_next_frame =
|
||||
pose_landmarks_detector_graph.Out(kPoseRectsNextFrameTag)
|
||||
.Cast<std::vector<NormalizedRect>>();
|
||||
std::optional<Source<std::vector<Image>>> segmentation_masks;
|
||||
if (output_segmentation_masks) {
|
||||
segmentation_masks =
|
||||
pose_landmarks_detector_graph.Out(kSegmentationMaskTag)
|
||||
.Cast<std::vector<Image>>();
|
||||
}
|
||||
auto segmentation_masks =
|
||||
pose_landmarks_detector_graph.Out(kSegmentationMaskTag)
|
||||
.Cast<std::vector<Image>>();
|
||||
|
||||
if (tasks_options.base_options().use_stream_mode()) {
|
||||
auto& previous_loopback = graph.AddNode("PreviousLoopbackCalculator");
|
||||
|
||||
@@ -37,7 +37,6 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/core/model_task_graph.h"
|
||||
#include "mediapipe/tasks/cc/vision/pose_landmarker/proto/pose_landmarks_detector_graph_options.pb.h"
|
||||
#include "mediapipe/tasks/cc/vision/utils/image_tensor_specs.h"
|
||||
#include "mediapipe/util/graph_builder_utils.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -49,7 +48,6 @@ using ::mediapipe::api2::Input;
|
||||
using ::mediapipe::api2::Output;
|
||||
using ::mediapipe::api2::builder::Graph;
|
||||
using ::mediapipe::api2::builder::Source;
|
||||
using ::mediapipe::api2::builder::Stream;
|
||||
using ::mediapipe::tasks::core::ModelResources;
|
||||
using ::mediapipe::tasks::vision::pose_landmarker::proto::
|
||||
PoseLandmarksDetectorGraphOptions;
|
||||
@@ -91,7 +89,7 @@ struct SinglePoseLandmarkerOutputs {
|
||||
Source<NormalizedRect> pose_rect_next_frame;
|
||||
Source<bool> pose_presence;
|
||||
Source<float> pose_presence_score;
|
||||
std::optional<Source<Image>> segmentation_mask;
|
||||
Source<Image> segmentation_mask;
|
||||
};
|
||||
|
||||
struct PoseLandmarkerOutputs {
|
||||
@@ -101,7 +99,7 @@ struct PoseLandmarkerOutputs {
|
||||
Source<std::vector<NormalizedRect>> pose_rects_next_frame;
|
||||
Source<std::vector<bool>> presences;
|
||||
Source<std::vector<float>> presence_scores;
|
||||
std::optional<Source<std::vector<Image>>> segmentation_masks;
|
||||
Source<std::vector<Image>> segmentation_masks;
|
||||
};
|
||||
|
||||
absl::Status SanityCheckOptions(
|
||||
@@ -271,18 +269,16 @@ class SinglePoseLandmarksDetectorGraph : public core::ModelTaskGraph {
|
||||
public:
|
||||
absl::StatusOr<CalculatorGraphConfig> GetConfig(
|
||||
SubgraphContext* sc) override {
|
||||
bool output_segmentation_mask =
|
||||
HasOutput(sc->OriginalNode(), kSegmentationMaskTag);
|
||||
ASSIGN_OR_RETURN(
|
||||
const auto* model_resources,
|
||||
CreateModelResources<PoseLandmarksDetectorGraphOptions>(sc));
|
||||
Graph graph;
|
||||
ASSIGN_OR_RETURN(auto pose_landmark_detection_outs,
|
||||
BuildSinglePoseLandmarksDetectorGraph(
|
||||
sc->Options<PoseLandmarksDetectorGraphOptions>(),
|
||||
*model_resources, graph[Input<Image>(kImageTag)],
|
||||
graph[Input<NormalizedRect>::Optional(kNormRectTag)],
|
||||
graph, output_segmentation_mask));
|
||||
ASSIGN_OR_RETURN(
|
||||
auto pose_landmark_detection_outs,
|
||||
BuildSinglePoseLandmarksDetectorGraph(
|
||||
sc->Options<PoseLandmarksDetectorGraphOptions>(), *model_resources,
|
||||
graph[Input<Image>(kImageTag)],
|
||||
graph[Input<NormalizedRect>::Optional(kNormRectTag)], graph));
|
||||
pose_landmark_detection_outs.pose_landmarks >>
|
||||
graph[Output<NormalizedLandmarkList>(kLandmarksTag)];
|
||||
pose_landmark_detection_outs.world_pose_landmarks >>
|
||||
@@ -295,10 +291,8 @@ class SinglePoseLandmarksDetectorGraph : public core::ModelTaskGraph {
|
||||
graph[Output<bool>(kPresenceTag)];
|
||||
pose_landmark_detection_outs.pose_presence_score >>
|
||||
graph[Output<float>(kPresenceScoreTag)];
|
||||
if (pose_landmark_detection_outs.segmentation_mask) {
|
||||
*pose_landmark_detection_outs.segmentation_mask >>
|
||||
graph[Output<Image>(kSegmentationMaskTag)];
|
||||
}
|
||||
pose_landmark_detection_outs.segmentation_mask >>
|
||||
graph[Output<Image>(kSegmentationMaskTag)];
|
||||
|
||||
return graph.GetConfig();
|
||||
}
|
||||
@@ -308,8 +302,7 @@ class SinglePoseLandmarksDetectorGraph : public core::ModelTaskGraph {
|
||||
BuildSinglePoseLandmarksDetectorGraph(
|
||||
const PoseLandmarksDetectorGraphOptions& subgraph_options,
|
||||
const ModelResources& model_resources, Source<Image> image_in,
|
||||
Source<NormalizedRect> pose_rect, Graph& graph,
|
||||
bool output_segmentation_mask) {
|
||||
Source<NormalizedRect> pose_rect, Graph& graph) {
|
||||
MP_RETURN_IF_ERROR(SanityCheckOptions(subgraph_options));
|
||||
|
||||
auto& preprocessing = graph.AddNode(
|
||||
@@ -387,6 +380,17 @@ class SinglePoseLandmarksDetectorGraph : public core::ModelTaskGraph {
|
||||
auto raw_landmarks =
|
||||
tensors_to_landmarks[Output<NormalizedLandmarkList>(kNormLandmarksTag)];
|
||||
|
||||
// Decodes the segmentation tensor into a mask image with pixel values in
|
||||
// [0, 1] (1 for person and 0 for background).
|
||||
auto& tensors_to_segmentation =
|
||||
graph.AddNode("TensorsToSegmentationCalculator");
|
||||
ConfigureTensorsToSegmentationCalculator(
|
||||
&tensors_to_segmentation
|
||||
.GetOptions<mediapipe::TensorsToSegmentationCalculatorOptions>());
|
||||
ensured_segmentation_tensors >> tensors_to_segmentation.In(kTensorsTag);
|
||||
auto raw_segmentation_mask =
|
||||
tensors_to_segmentation[Output<Image>(kMaskTag)];
|
||||
|
||||
// Refines landmarks with the heatmap tensor.
|
||||
auto& refine_landmarks_from_heatmap =
|
||||
graph.AddNode("RefineLandmarksFromHeatmapCalculator");
|
||||
@@ -489,34 +493,20 @@ class SinglePoseLandmarksDetectorGraph : public core::ModelTaskGraph {
|
||||
auto world_projected_landmarks =
|
||||
world_landmarks_projection.Out(kLandmarksTag).Cast<LandmarkList>();
|
||||
|
||||
std::optional<Stream<Image>> segmentation_mask;
|
||||
if (output_segmentation_mask) {
|
||||
// Decodes the segmentation tensor into a mask image with pixel values in
|
||||
// [0, 1] (1 for person and 0 for background).
|
||||
auto& tensors_to_segmentation =
|
||||
graph.AddNode("TensorsToSegmentationCalculator");
|
||||
ConfigureTensorsToSegmentationCalculator(
|
||||
&tensors_to_segmentation.GetOptions<
|
||||
mediapipe::TensorsToSegmentationCalculatorOptions>());
|
||||
ensured_segmentation_tensors >> tensors_to_segmentation.In(kTensorsTag);
|
||||
auto raw_segmentation_mask =
|
||||
tensors_to_segmentation[Output<Image>(kMaskTag)];
|
||||
// Calculates the inverse transformation matrix.
|
||||
auto& inverse_matrix = graph.AddNode("InverseMatrixCalculator");
|
||||
matrix >> inverse_matrix.In(kMatrixTag);
|
||||
auto inverted_matrix = inverse_matrix.Out(kMatrixTag);
|
||||
|
||||
// Calculates the inverse transformation matrix.
|
||||
auto& inverse_matrix = graph.AddNode("InverseMatrixCalculator");
|
||||
matrix >> inverse_matrix.In(kMatrixTag);
|
||||
auto inverted_matrix = inverse_matrix.Out(kMatrixTag);
|
||||
|
||||
// Projects the segmentation mask from the letterboxed ROI back to the
|
||||
// full image.
|
||||
auto& warp_affine = graph.AddNode("WarpAffineCalculator");
|
||||
ConfigureWarpAffineCalculator(
|
||||
&warp_affine.GetOptions<mediapipe::WarpAffineCalculatorOptions>());
|
||||
image_size >> warp_affine.In(kOutputSizeTag);
|
||||
inverted_matrix >> warp_affine.In(kMatrixTag);
|
||||
raw_segmentation_mask >> warp_affine.In(kImageTag);
|
||||
segmentation_mask = warp_affine.Out(kImageTag).Cast<Image>();
|
||||
}
|
||||
// Projects the segmentation mask from the letterboxed ROI back to the full
|
||||
// image.
|
||||
auto& warp_affine = graph.AddNode("WarpAffineCalculator");
|
||||
ConfigureWarpAffineCalculator(
|
||||
&warp_affine.GetOptions<mediapipe::WarpAffineCalculatorOptions>());
|
||||
image_size >> warp_affine.In(kOutputSizeTag);
|
||||
inverted_matrix >> warp_affine.In(kMatrixTag);
|
||||
raw_segmentation_mask >> warp_affine.In(kImageTag);
|
||||
auto projected_segmentation_mask = warp_affine.Out(kImageTag).Cast<Image>();
|
||||
|
||||
// Calculate region of interest based on auxiliary landmarks, to be used
|
||||
// in the next frame. Consists of LandmarksToDetection +
|
||||
@@ -551,7 +541,7 @@ class SinglePoseLandmarksDetectorGraph : public core::ModelTaskGraph {
|
||||
/* pose_rect_next_frame= */ pose_rect_next_frame,
|
||||
/* pose_presence= */ pose_presence,
|
||||
/* pose_presence_score= */ pose_presence_score,
|
||||
/* segmentation_mask= */ segmentation_mask,
|
||||
/* segmentation_mask= */ projected_segmentation_mask,
|
||||
}};
|
||||
}
|
||||
};
|
||||
@@ -623,15 +613,12 @@ class MultiplePoseLandmarksDetectorGraph : public core::ModelTaskGraph {
|
||||
absl::StatusOr<CalculatorGraphConfig> GetConfig(
|
||||
SubgraphContext* sc) override {
|
||||
Graph graph;
|
||||
bool output_segmentation_masks =
|
||||
HasOutput(sc->OriginalNode(), kSegmentationMaskTag);
|
||||
ASSIGN_OR_RETURN(
|
||||
auto pose_landmark_detection_outputs,
|
||||
BuildPoseLandmarksDetectorGraph(
|
||||
sc->Options<PoseLandmarksDetectorGraphOptions>(),
|
||||
graph[Input<Image>(kImageTag)],
|
||||
graph[Input<std::vector<NormalizedRect>>(kNormRectTag)], graph,
|
||||
output_segmentation_masks));
|
||||
graph[Input<std::vector<NormalizedRect>>(kNormRectTag)], graph));
|
||||
pose_landmark_detection_outputs.landmark_lists >>
|
||||
graph[Output<std::vector<NormalizedLandmarkList>>(kLandmarksTag)];
|
||||
pose_landmark_detection_outputs.world_landmark_lists >>
|
||||
@@ -644,10 +631,8 @@ class MultiplePoseLandmarksDetectorGraph : public core::ModelTaskGraph {
|
||||
graph[Output<std::vector<bool>>(kPresenceTag)];
|
||||
pose_landmark_detection_outputs.presence_scores >>
|
||||
graph[Output<std::vector<float>>(kPresenceScoreTag)];
|
||||
if (pose_landmark_detection_outputs.segmentation_masks) {
|
||||
*pose_landmark_detection_outputs.segmentation_masks >>
|
||||
graph[Output<std::vector<Image>>(kSegmentationMaskTag)];
|
||||
}
|
||||
pose_landmark_detection_outputs.segmentation_masks >>
|
||||
graph[Output<std::vector<Image>>(kSegmentationMaskTag)];
|
||||
|
||||
return graph.GetConfig();
|
||||
}
|
||||
@@ -656,8 +641,7 @@ class MultiplePoseLandmarksDetectorGraph : public core::ModelTaskGraph {
|
||||
absl::StatusOr<PoseLandmarkerOutputs> BuildPoseLandmarksDetectorGraph(
|
||||
const PoseLandmarksDetectorGraphOptions& subgraph_options,
|
||||
Source<Image> image_in,
|
||||
Source<std::vector<NormalizedRect>> multi_pose_rects, Graph& graph,
|
||||
bool output_segmentation_masks) {
|
||||
Source<std::vector<NormalizedRect>> multi_pose_rects, Graph& graph) {
|
||||
auto& begin_loop_multi_pose_rects =
|
||||
graph.AddNode("BeginLoopNormalizedRectCalculator");
|
||||
image_in >> begin_loop_multi_pose_rects.In("CLONE");
|
||||
@@ -680,6 +664,7 @@ class MultiplePoseLandmarksDetectorGraph : public core::ModelTaskGraph {
|
||||
pose_landmark_subgraph.Out(kPoseRectNextFrameTag);
|
||||
auto presence = pose_landmark_subgraph.Out(kPresenceTag);
|
||||
auto presence_score = pose_landmark_subgraph.Out(kPresenceScoreTag);
|
||||
auto segmentation_mask = pose_landmark_subgraph.Out(kSegmentationMaskTag);
|
||||
|
||||
auto& end_loop_landmarks =
|
||||
graph.AddNode("EndLoopNormalizedLandmarkListVectorCalculator");
|
||||
@@ -723,16 +708,11 @@ class MultiplePoseLandmarksDetectorGraph : public core::ModelTaskGraph {
|
||||
auto presence_scores =
|
||||
end_loop_presence_score[Output<std::vector<float>>(kIterableTag)];
|
||||
|
||||
std::optional<Stream<std::vector<Image>>> segmentation_masks_vector;
|
||||
if (output_segmentation_masks) {
|
||||
auto segmentation_mask = pose_landmark_subgraph.Out(kSegmentationMaskTag);
|
||||
auto& end_loop_segmentation_mask =
|
||||
graph.AddNode("EndLoopImageCalculator");
|
||||
batch_end >> end_loop_segmentation_mask.In(kBatchEndTag);
|
||||
segmentation_mask >> end_loop_segmentation_mask.In(kItemTag);
|
||||
segmentation_masks_vector =
|
||||
end_loop_segmentation_mask[Output<std::vector<Image>>(kIterableTag)];
|
||||
}
|
||||
auto& end_loop_segmentation_mask = graph.AddNode("EndLoopImageCalculator");
|
||||
batch_end >> end_loop_segmentation_mask.In(kBatchEndTag);
|
||||
segmentation_mask >> end_loop_segmentation_mask.In(kItemTag);
|
||||
auto segmentation_masks =
|
||||
end_loop_segmentation_mask[Output<std::vector<Image>>(kIterableTag)];
|
||||
|
||||
return {{
|
||||
/* landmark_lists= */ landmark_lists,
|
||||
@@ -741,7 +721,7 @@ class MultiplePoseLandmarksDetectorGraph : public core::ModelTaskGraph {
|
||||
/* pose_rects_next_frame= */ pose_rects_next_frame,
|
||||
/* presences= */ presences,
|
||||
/* presence_scores= */ presence_scores,
|
||||
/* segmentation_masks= */ segmentation_masks_vector,
|
||||
/* segmentation_masks= */ segmentation_masks,
|
||||
}};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -143,7 +143,7 @@ absl::StatusOr<std::unique_ptr<TaskRunner>> CreateSinglePoseTaskRunner(
|
||||
|
||||
return TaskRunner::Create(
|
||||
graph.GetConfig(),
|
||||
absl::make_unique<tflite::ops::builtin::BuiltinOpResolver>());
|
||||
absl::make_unique<tflite_shims::ops::builtin::BuiltinOpResolver>());
|
||||
}
|
||||
|
||||
// Helper function to create a Multi Pose Landmark TaskRunner.
|
||||
@@ -189,7 +189,7 @@ absl::StatusOr<std::unique_ptr<TaskRunner>> CreateMultiPoseTaskRunner(
|
||||
|
||||
return TaskRunner::Create(
|
||||
graph.GetConfig(),
|
||||
absl::make_unique<tflite::ops::builtin::BuiltinOpResolver>());
|
||||
absl::make_unique<tflite_shims::ops::builtin::BuiltinOpResolver>());
|
||||
}
|
||||
|
||||
NormalizedLandmarkList GetExpectedLandmarkList(absl::string_view filename) {
|
||||
|
||||
@@ -50,7 +50,7 @@ cc_test_with_tflite(
|
||||
tflite_deps = [
|
||||
":image_tensor_specs",
|
||||
"//mediapipe/tasks/cc/core:model_resources",
|
||||
"@org_tensorflow//tensorflow/lite:test_util",
|
||||
"@org_tensorflow//tensorflow/lite/core/shims:cc_shims_test_util",
|
||||
],
|
||||
deps = [
|
||||
"//mediapipe/framework/deps:file_path",
|
||||
|
||||
@@ -35,7 +35,7 @@ limitations under the License.
|
||||
#include "mediapipe/tasks/cc/core/proto/external_file.pb.h"
|
||||
#include "mediapipe/tasks/cc/metadata/metadata_extractor.h"
|
||||
#include "mediapipe/tasks/metadata/metadata_schema_generated.h"
|
||||
#include "tensorflow/lite/test_util.h"
|
||||
#include "tensorflow/lite/core/shims/cc/shims_test_util.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace tasks {
|
||||
@@ -69,7 +69,7 @@ constexpr char kMobileNetMetadata[] =
|
||||
constexpr char kMobileNetQuantizedPartialMetadata[] =
|
||||
"mobilenet_v1_0.25_224_quant_without_subgraph_metadata.tflite";
|
||||
|
||||
class ImageTensorSpecsTest : public tflite::testing::Test {};
|
||||
class ImageTensorSpecsTest : public tflite_shims::testing::Test {};
|
||||
|
||||
TEST_F(ImageTensorSpecsTest, BuildInputImageTensorSpecsWorks) {
|
||||
auto model_file = std::make_unique<core::proto::ExternalFile>();
|
||||
|
||||
@@ -90,7 +90,7 @@ NS_SWIFT_NAME(ClassificationResult)
|
||||
* amount of data to process might exceed the maximum size that the model can process: to solve
|
||||
* this, the input data is split into multiple chunks starting at different timestamps.
|
||||
*/
|
||||
@property(nonatomic, readonly) NSInteger timestampInMilliseconds;
|
||||
@property(nonatomic, readonly) NSInteger timestampMs;
|
||||
|
||||
/**
|
||||
* Initializes a new `MPPClassificationResult` with the given array of classifications and time
|
||||
@@ -98,15 +98,14 @@ NS_SWIFT_NAME(ClassificationResult)
|
||||
*
|
||||
* @param classifications An Array of `MPPClassifications` objects containing the predicted
|
||||
* categories for each head of the model.
|
||||
* @param timestampInMilliseconds The timestamp (in milliseconds) of the start of the chunk of data
|
||||
* @param timestampMs The timestamp (in milliseconds) of the start of the chunk of data
|
||||
* corresponding to these results.
|
||||
*
|
||||
* @return An instance of `MPPClassificationResult` initialized with the given array of
|
||||
* classifications and timestamp (in milliseconds).
|
||||
* classifications and timestampMs.
|
||||
*/
|
||||
- (instancetype)initWithClassifications:(NSArray<MPPClassifications *> *)classifications
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
timestampMs:(NSInteger)timestampMs NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
|
||||
@@ -38,11 +38,11 @@
|
||||
@implementation MPPClassificationResult
|
||||
|
||||
- (instancetype)initWithClassifications:(NSArray<MPPClassifications *> *)classifications
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds {
|
||||
timestampMs:(NSInteger)timestampMs {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_classifications = classifications;
|
||||
_timestampInMilliseconds = timestampInMilliseconds;
|
||||
_timestampMs = timestampMs;
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
@@ -33,7 +33,7 @@ NS_SWIFT_NAME(EmbeddingResult)
|
||||
* cases, the amount of data to process might exceed the maximum size that the model can process. To
|
||||
* solve this, the input data is split into multiple chunks starting at different timestamps.
|
||||
*/
|
||||
@property(nonatomic, readonly) NSInteger timestampInMilliseconds;
|
||||
@property(nonatomic, readonly) NSInteger timestampMs;
|
||||
|
||||
/**
|
||||
* Initializes a new `MPPEmbedding` with the given array of embeddings and timestamp (in
|
||||
@@ -41,14 +41,14 @@ NS_SWIFT_NAME(EmbeddingResult)
|
||||
*
|
||||
* @param embeddings An Array of `MPPEmbedding` objects containing the embedding results for each
|
||||
* head of the model.
|
||||
* @param timestampInMilliseconds The optional timestamp (in milliseconds) of the start of the chunk
|
||||
* of data corresponding to these results. Pass `0` if timestamp is absent.
|
||||
* @param timestampMs The optional timestamp (in milliseconds) of the start of the chunk of data
|
||||
* corresponding to these results. Pass `0` if timestamp is absent.
|
||||
*
|
||||
* @return An instance of `MPPEmbeddingResult` initialized with the given array of embeddings and
|
||||
* timestamp (in milliseconds).
|
||||
* timestampMs.
|
||||
*/
|
||||
- (instancetype)initWithEmbeddings:(NSArray<MPPEmbedding *> *)embeddings
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds NS_DESIGNATED_INITIALIZER;
|
||||
timestampMs:(NSInteger)timestampMs NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
@implementation MPPEmbeddingResult
|
||||
|
||||
- (instancetype)initWithEmbeddings:(NSArray<MPPEmbedding *> *)embeddings
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds {
|
||||
timestampMs:(NSInteger)timestampMs {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_embeddings = embeddings;
|
||||
_timestampInMilliseconds = timestampInMilliseconds;
|
||||
_timestampMs = timestampMs;
|
||||
}
|
||||
|
||||
return self;
|
||||
|
||||
+3
-3
@@ -55,13 +55,13 @@ using ClassificationResultProto =
|
||||
[classifications addObject:[MPPClassifications classificationsWithProto:classificationsProto]];
|
||||
}
|
||||
|
||||
NSInteger timestampInMilliseconds = 0;
|
||||
NSInteger timestampMs = 0;
|
||||
if (classificationResultProto.has_timestamp_ms()) {
|
||||
timestampInMilliseconds = (NSInteger)classificationResultProto.timestamp_ms();
|
||||
timestampMs = (NSInteger)classificationResultProto.timestamp_ms();
|
||||
}
|
||||
|
||||
return [[MPPClassificationResult alloc] initWithClassifications:classifications
|
||||
timestampInMilliseconds:timestampInMilliseconds];
|
||||
timestampMs:timestampMs];
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
+3
-4
@@ -31,13 +31,12 @@ using EmbeddingResultProto = ::mediapipe::tasks::components::containers::proto::
|
||||
[embeddings addObject:[MPPEmbedding embeddingWithProto:embeddingProto]];
|
||||
}
|
||||
|
||||
NSInteger timestampInMilliseconds = 0;
|
||||
NSInteger timestampMs = 0;
|
||||
if (embeddingResultProto.has_timestamp_ms()) {
|
||||
timestampInMilliseconds = (NSInteger)embeddingResultProto.timestamp_ms();
|
||||
timestampMs = (NSInteger)embeddingResultProto.timestamp_ms();
|
||||
}
|
||||
|
||||
return [[MPPEmbeddingResult alloc] initWithEmbeddings:embeddings
|
||||
timestampInMilliseconds:timestampInMilliseconds];
|
||||
return [[MPPEmbeddingResult alloc] initWithEmbeddings:embeddings timestampMs:timestampMs];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -26,12 +26,11 @@ NS_SWIFT_NAME(TaskResult)
|
||||
/**
|
||||
* Timestamp that is associated with the task result object.
|
||||
*/
|
||||
@property(nonatomic, assign, readonly) NSInteger timestampInMilliseconds;
|
||||
@property(nonatomic, assign, readonly) NSInteger timestampMs;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
- (instancetype)initWithTimestampInMilliseconds:(NSInteger)timestampInMilliseconds
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithTimestampMs:(NSInteger)timestampMs NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -16,16 +16,16 @@
|
||||
|
||||
@implementation MPPTaskResult
|
||||
|
||||
- (instancetype)initWithTimestampInMilliseconds:(NSInteger)timestampInMilliseconds {
|
||||
- (instancetype)initWithTimestampMs:(NSInteger)timestampMs {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_timestampInMilliseconds = timestampInMilliseconds;
|
||||
_timestampMs = timestampMs;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone {
|
||||
return [[MPPTaskResult alloc] initWithTimestampInMilliseconds:self.timestampInMilliseconds];
|
||||
return [[MPPTaskResult alloc] initWithTimestampMs:self.timestampMs];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -487,7 +487,7 @@ static NSString *const kExpectedErrorDomain = @"com.google.mediapipe.tasks";
|
||||
|
||||
NSError *liveStreamApiCallError;
|
||||
XCTAssertFalse([imageClassifier classifyAsyncImage:image
|
||||
timestampInMilliseconds:0
|
||||
timestampMs:0
|
||||
error:&liveStreamApiCallError]);
|
||||
|
||||
NSError *expectedLiveStreamApiCallError =
|
||||
@@ -501,9 +501,7 @@ static NSString *const kExpectedErrorDomain = @"com.google.mediapipe.tasks";
|
||||
AssertEqualErrors(liveStreamApiCallError, expectedLiveStreamApiCallError);
|
||||
|
||||
NSError *videoApiCallError;
|
||||
XCTAssertFalse([imageClassifier classifyVideoFrame:image
|
||||
timestampInMilliseconds:0
|
||||
error:&videoApiCallError]);
|
||||
XCTAssertFalse([imageClassifier classifyVideoFrame:image timestampMs:0 error:&videoApiCallError]);
|
||||
|
||||
NSError *expectedVideoApiCallError =
|
||||
[NSError errorWithDomain:kExpectedErrorDomain
|
||||
@@ -526,7 +524,7 @@ static NSString *const kExpectedErrorDomain = @"com.google.mediapipe.tasks";
|
||||
|
||||
NSError *liveStreamApiCallError;
|
||||
XCTAssertFalse([imageClassifier classifyAsyncImage:image
|
||||
timestampInMilliseconds:0
|
||||
timestampMs:0
|
||||
error:&liveStreamApiCallError]);
|
||||
|
||||
NSError *expectedLiveStreamApiCallError =
|
||||
@@ -577,9 +575,7 @@ static NSString *const kExpectedErrorDomain = @"com.google.mediapipe.tasks";
|
||||
AssertEqualErrors(imageApiCallError, expectedImageApiCallError);
|
||||
|
||||
NSError *videoApiCallError;
|
||||
XCTAssertFalse([imageClassifier classifyVideoFrame:image
|
||||
timestampInMilliseconds:0
|
||||
error:&videoApiCallError]);
|
||||
XCTAssertFalse([imageClassifier classifyVideoFrame:image timestampMs:0 error:&videoApiCallError]);
|
||||
|
||||
NSError *expectedVideoApiCallError =
|
||||
[NSError errorWithDomain:kExpectedErrorDomain
|
||||
@@ -605,7 +601,7 @@ static NSString *const kExpectedErrorDomain = @"com.google.mediapipe.tasks";
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
MPPImageClassifierResult *imageClassifierResult = [imageClassifier classifyVideoFrame:image
|
||||
timestampInMilliseconds:i
|
||||
timestampMs:i
|
||||
error:nil];
|
||||
[self assertImageClassifierResult:imageClassifierResult
|
||||
hasExpectedCategoriesCount:maxResults
|
||||
@@ -634,10 +630,10 @@ static NSString *const kExpectedErrorDomain = @"com.google.mediapipe.tasks";
|
||||
|
||||
MPPImage *image = [self imageWithFileInfo:kBurgerImage];
|
||||
|
||||
XCTAssertTrue([imageClassifier classifyAsyncImage:image timestampInMilliseconds:1 error:nil]);
|
||||
XCTAssertTrue([imageClassifier classifyAsyncImage:image timestampMs:1 error:nil]);
|
||||
|
||||
NSError *error;
|
||||
XCTAssertFalse([imageClassifier classifyAsyncImage:image timestampInMilliseconds:0 error:&error]);
|
||||
XCTAssertFalse([imageClassifier classifyAsyncImage:image timestampMs:0 error:&error]);
|
||||
|
||||
NSError *expectedError =
|
||||
[NSError errorWithDomain:kExpectedErrorDomain
|
||||
@@ -672,7 +668,7 @@ static NSString *const kExpectedErrorDomain = @"com.google.mediapipe.tasks";
|
||||
MPPImage *image = [self imageWithFileInfo:kBurgerImage];
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
XCTAssertTrue([imageClassifier classifyAsyncImage:image timestampInMilliseconds:i error:nil]);
|
||||
XCTAssertTrue([imageClassifier classifyAsyncImage:image timestampMs:i error:nil]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,13 +31,13 @@ NS_SWIFT_NAME(TextClassifierResult)
|
||||
*
|
||||
* @param classificationResult The `MPPClassificationResult` instance containing one set of results
|
||||
* per classifier head.
|
||||
* @param timestampInMilliseconds The timestamp (in milliseconds) for this result.
|
||||
* @param timestampMs The timestamp for this result.
|
||||
*
|
||||
* @return An instance of `MPPTextClassifierResult` initialized with the given
|
||||
* `MPPClassificationResult` and timestamp (in milliseconds).
|
||||
*/
|
||||
- (instancetype)initWithClassificationResult:(MPPClassificationResult *)classificationResult
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds;
|
||||
timestampMs:(NSInteger)timestampMs;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
@implementation MPPTextClassifierResult
|
||||
|
||||
- (instancetype)initWithClassificationResult:(MPPClassificationResult *)classificationResult
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds {
|
||||
self = [super initWithTimestampInMilliseconds:timestampInMilliseconds];
|
||||
timestampMs:(NSInteger)timestampMs {
|
||||
self = [super initWithTimestampMs:timestampMs];
|
||||
if (self) {
|
||||
_classificationResult = classificationResult;
|
||||
}
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ using ::mediapipe::Packet;
|
||||
|
||||
return [[MPPTextClassifierResult alloc]
|
||||
initWithClassificationResult:classificationResult
|
||||
timestampInMilliseconds:(NSInteger)(packet.Timestamp().Value() /
|
||||
timestampMs:(NSInteger)(packet.Timestamp().Value() /
|
||||
kMicroSecondsPerMilliSecond)];
|
||||
}
|
||||
|
||||
|
||||
@@ -31,13 +31,13 @@ NS_SWIFT_NAME(TextEmbedderResult)
|
||||
*
|
||||
* @param embeddingResult The `MPPEmbeddingResult` instance containing one set of results
|
||||
* per classifier head.
|
||||
* @param timestampInMilliseconds The timestamp (in millisecondss) for this result.
|
||||
* @param timestampMs The timestamp for this result.
|
||||
*
|
||||
* @return An instance of `MPPTextEmbedderResult` initialized with the given
|
||||
* `MPPEmbeddingResult` and timestamp (in milliseconds).
|
||||
*/
|
||||
- (instancetype)initWithEmbeddingResult:(MPPEmbeddingResult *)embeddingResult
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds;
|
||||
timestampMs:(NSInteger)timestampMs;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
@implementation MPPTextEmbedderResult
|
||||
|
||||
- (instancetype)initWithEmbeddingResult:(MPPEmbeddingResult *)embeddingResult
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds {
|
||||
self = [super initWithTimestampInMilliseconds:timestampInMilliseconds];
|
||||
timestampMs:(NSInteger)timestampMs {
|
||||
self = [super initWithTimestampMs:timestampMs];
|
||||
if (self) {
|
||||
_embeddingResult = embeddingResult;
|
||||
}
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ using ::mediapipe::Packet;
|
||||
|
||||
return [[MPPTextEmbedderResult alloc]
|
||||
initWithEmbeddingResult:embeddingResult
|
||||
timestampInMilliseconds:(NSInteger)(packet.Timestamp().Value() /
|
||||
timestampMs:(NSInteger)(packet.Timestamp().Value() /
|
||||
kMicroSecondsPerMilliSecond)];
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
* timestamp.
|
||||
*
|
||||
* @param image The image to send to the MediaPipe graph.
|
||||
* @param timestampInMilliseconds The timestamp (in milliseconds) to assign to the packet.
|
||||
* @param timestampMs The timestamp (in milliseconds) to assign to the packet.
|
||||
* @param error Pointer to the memory location where errors if any should be saved. If @c NULL, no
|
||||
* error will be saved.
|
||||
*
|
||||
@@ -49,7 +49,7 @@
|
||||
* occurred during the conversion.
|
||||
*/
|
||||
+ (mediapipe::Packet)createPacketWithMPPImage:(MPPImage *)image
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds
|
||||
timestampMs:(NSInteger)timestampMs
|
||||
error:(NSError **)error;
|
||||
|
||||
/**
|
||||
@@ -66,11 +66,11 @@
|
||||
* specified timestamp.
|
||||
*
|
||||
* @param image The `NormalizedRect` to send to the MediaPipe graph.
|
||||
* @param timestampInMilliseconds The timestamp (in milliseconds) to assign to the packet.
|
||||
* @param timestampMs The timestamp (in milliseconds) to assign to the packet.
|
||||
*
|
||||
* @return The MediaPipe packet containing the normalized rect.
|
||||
*/
|
||||
+ (mediapipe::Packet)createPacketWithNormalizedRect:(mediapipe::NormalizedRect &)normalizedRect
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds;
|
||||
timestampMs:(NSInteger)timestampMs;
|
||||
|
||||
@end
|
||||
|
||||
@@ -42,7 +42,7 @@ using ::mediapipe::Timestamp;
|
||||
}
|
||||
|
||||
+ (Packet)createPacketWithMPPImage:(MPPImage *)image
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds
|
||||
timestampMs:(NSInteger)timestampMs
|
||||
error:(NSError **)error {
|
||||
std::unique_ptr<ImageFrame> imageFrame = [image imageFrameWithError:error];
|
||||
|
||||
@@ -51,7 +51,7 @@ using ::mediapipe::Timestamp;
|
||||
}
|
||||
|
||||
return MakePacket<Image>(std::move(imageFrame))
|
||||
.At(Timestamp(int64(timestampInMilliseconds * kMicroSecondsPerMilliSecond)));
|
||||
.At(Timestamp(int64(timestampMs * kMicroSecondsPerMilliSecond)));
|
||||
}
|
||||
|
||||
+ (Packet)createPacketWithNormalizedRect:(NormalizedRect &)normalizedRect {
|
||||
@@ -59,9 +59,9 @@ using ::mediapipe::Timestamp;
|
||||
}
|
||||
|
||||
+ (Packet)createPacketWithNormalizedRect:(NormalizedRect &)normalizedRect
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds {
|
||||
timestampMs:(NSInteger)timestampMs {
|
||||
return MakePacket<NormalizedRect>(std::move(normalizedRect))
|
||||
.At(Timestamp(int64(timestampInMilliseconds * kMicroSecondsPerMilliSecond)));
|
||||
.At(Timestamp(int64(timestampMs * kMicroSecondsPerMilliSecond)));
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
handedness:(NSArray<NSArray<MPPCategory *> *> *)handedness
|
||||
gestures:(NSArray<NSArray<MPPCategory *> *> *)gestures
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds {
|
||||
self = [super initWithTimestampInMilliseconds:timestampInMilliseconds];
|
||||
self = [super initWithTimestampMs:timestampInMilliseconds];
|
||||
if (self) {
|
||||
_landmarks = landmarks;
|
||||
_worldLandmarks = worldLandmarks;
|
||||
|
||||
@@ -122,17 +122,17 @@ NS_SWIFT_NAME(ImageClassifier)
|
||||
* `MPPRunningModeVideo`.
|
||||
*
|
||||
* @param image The `MPPImage` on which image classification is to be performed.
|
||||
* @param timestampInMilliseconds The video frame's timestamp (in milliseconds). The input
|
||||
* timestamps must be monotonically increasing.
|
||||
* @param timestampMs The video frame's timestamp (in milliseconds). The input timestamps must be
|
||||
* monotonically increasing.
|
||||
* @param error An optional error parameter populated when there is an error in performing image
|
||||
* classification on the input video frame.
|
||||
*
|
||||
* @return An `MPPImageClassifierResult` object that contains a list of image classifications.
|
||||
*/
|
||||
- (nullable MPPImageClassifierResult *)classifyVideoFrame:(MPPImage *)image
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds
|
||||
timestampMs:(NSInteger)timestampMs
|
||||
error:(NSError **)error
|
||||
NS_SWIFT_NAME(classify(videoFrame:timestampInMilliseconds:));
|
||||
NS_SWIFT_NAME(classify(videoFrame:timestampMs:));
|
||||
|
||||
/**
|
||||
* Performs image classification on the provided video frame of type `MPPImage` cropped to the
|
||||
@@ -145,8 +145,8 @@ NS_SWIFT_NAME(ImageClassifier)
|
||||
*
|
||||
* @param image A live stream image data of type `MPPImage` on which image classification is to be
|
||||
* performed.
|
||||
* @param timestampInMilliseconds The video frame's timestamp (in milliseconds). The input
|
||||
* timestamps must be monotonically increasing.
|
||||
* @param timestampMs The video frame's timestamp (in milliseconds). The input timestamps must be
|
||||
* monotonically increasing.
|
||||
* @param roi A `CGRect` specifying the region of interest within the video frame of type
|
||||
* `MPPImage`, on which image classification should be performed.
|
||||
* @param error An optional error parameter populated when there is an error in performing image
|
||||
@@ -155,10 +155,10 @@ NS_SWIFT_NAME(ImageClassifier)
|
||||
* @return An `MPPImageClassifierResult` object that contains a list of image classifications.
|
||||
*/
|
||||
- (nullable MPPImageClassifierResult *)classifyVideoFrame:(MPPImage *)image
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds
|
||||
timestampMs:(NSInteger)timestampMs
|
||||
regionOfInterest:(CGRect)roi
|
||||
error:(NSError **)error
|
||||
NS_SWIFT_NAME(classify(videoFrame:timestampInMilliseconds:regionOfInterest:));
|
||||
NS_SWIFT_NAME(classify(videoFrame:timestampMs:regionOfInterest:));
|
||||
|
||||
/**
|
||||
* Sends live stream image data of type `MPPImage` to perform image classification using the whole
|
||||
@@ -172,17 +172,16 @@ NS_SWIFT_NAME(ImageClassifier)
|
||||
*
|
||||
* @param image A live stream image data of type `MPPImage` on which image classification is to be
|
||||
* performed.
|
||||
* @param timestampInMilliseconds The timestamp (in milliseconds) which indicates when the input
|
||||
* image is sent to the image classifier. The input timestamps must be monotonically increasing.
|
||||
* @param timestampMs The timestamp (in milliseconds) which indicates when the input image is sent
|
||||
* to the image classifier. The input timestamps must be monotonically increasing.
|
||||
* @param error An optional error parameter populated when there is an error in performing image
|
||||
* classification on the input live stream image data.
|
||||
*
|
||||
* @return `YES` if the image was sent to the task successfully, otherwise `NO`.
|
||||
*/
|
||||
- (BOOL)classifyAsyncImage:(MPPImage *)image
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds
|
||||
error:(NSError **)error
|
||||
NS_SWIFT_NAME(classifyAsync(image:timestampInMilliseconds:));
|
||||
timestampMs:(NSInteger)timestampMs
|
||||
error:(NSError **)error NS_SWIFT_NAME(classifyAsync(image:timestampMs:));
|
||||
|
||||
/**
|
||||
* Sends live stream image data of type `MPPImage` to perform image classification, cropped to the
|
||||
@@ -196,8 +195,8 @@ NS_SWIFT_NAME(ImageClassifier)
|
||||
*
|
||||
* @param image A live stream image data of type `MPPImage` on which image classification is to be
|
||||
* performed.
|
||||
* @param timestampInMilliseconds The timestamp (in milliseconds) which indicates when the input
|
||||
* image is sent to the image classifier. The input timestamps must be monotonically increasing.
|
||||
* @param timestampMs The timestamp (in milliseconds) which indicates when the input image is sent
|
||||
* to the image classifier. The input timestamps must be monotonically increasing.
|
||||
* @param roi A `CGRect` specifying the region of interest within the given live stream image data
|
||||
* of type `MPPImage`, on which image classification should be performed.
|
||||
* @param error An optional error parameter populated when there is an error in performing image
|
||||
@@ -206,10 +205,10 @@ NS_SWIFT_NAME(ImageClassifier)
|
||||
* @return `YES` if the image was sent to the task successfully, otherwise `NO`.
|
||||
*/
|
||||
- (BOOL)classifyAsyncImage:(MPPImage *)image
|
||||
timestampInMilliseconds:(NSInteger)timestampInMilliseconds
|
||||
regionOfInterest:(CGRect)roi
|
||||
error:(NSError **)error
|
||||
NS_SWIFT_NAME(classifyAsync(image:timestampInMilliseconds:regionOfInterest:));
|
||||
timestampMs:(NSInteger)timestampMs
|
||||
regionOfInterest:(CGRect)roi
|
||||
error:(NSError **)error
|
||||
NS_SWIFT_NAME(classifyAsync(image:timestampMs:regionOfInterest:));
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user