2019-08-17 03:49:25 +02:00
|
|
|
// Copyright 2019 The MediaPipe Authors.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
#include "mediapipe/calculators/util/thresholding_calculator.pb.h"
|
|
|
|
#include "mediapipe/framework/calculator_framework.h"
|
|
|
|
|
|
|
|
namespace mediapipe {
|
|
|
|
|
2021-07-28 03:20:05 +02:00
|
|
|
constexpr char kThresholdTag[] = "THRESHOLD";
|
|
|
|
constexpr char kRejectTag[] = "REJECT";
|
|
|
|
constexpr char kAcceptTag[] = "ACCEPT";
|
|
|
|
constexpr char kFlagTag[] = "FLAG";
|
|
|
|
constexpr char kFloatTag[] = "FLOAT";
|
|
|
|
|
2019-08-17 03:49:25 +02:00
|
|
|
// Applies a threshold on a stream of numeric values and outputs a flag and/or
|
|
|
|
// accept/reject stream. The threshold can be specified by one of the following:
|
|
|
|
// 1) Input stream.
|
|
|
|
// 2) Input side packet.
|
|
|
|
// 3) Calculator option.
|
|
|
|
//
|
|
|
|
// Input:
|
|
|
|
// FLOAT: A float, which will be cast to double to be compared with a
|
|
|
|
// threshold of double type.
|
|
|
|
// THRESHOLD(optional): A double specifying the threshold at current timestamp.
|
|
|
|
//
|
|
|
|
// Output:
|
|
|
|
// FLAG(optional): A boolean indicating if the input value is larger than the
|
|
|
|
// threshold.
|
|
|
|
// ACCEPT(optional): A packet will be sent if the value is larger than the
|
|
|
|
// threshold.
|
|
|
|
// REJECT(optional): A packet will be sent if the value is no larger than the
|
|
|
|
// threshold.
|
|
|
|
//
|
|
|
|
// Usage example:
|
|
|
|
// node {
|
|
|
|
// calculator: "ThresholdingCalculator"
|
|
|
|
// input_stream: "FLOAT:score"
|
|
|
|
// output_stream: "ACCEPT:accept"
|
|
|
|
// output_stream: "REJECT:reject"
|
|
|
|
// options: {
|
|
|
|
// [mediapipe.ThresholdingCalculatorOptions.ext] {
|
|
|
|
// threshold: 0.1
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
class ThresholdingCalculator : public CalculatorBase {
|
|
|
|
public:
|
2021-02-27 09:21:16 +01:00
|
|
|
static absl::Status GetContract(CalculatorContract* cc);
|
|
|
|
absl::Status Open(CalculatorContext* cc) override;
|
2019-08-17 03:49:25 +02:00
|
|
|
|
2021-02-27 09:21:16 +01:00
|
|
|
absl::Status Process(CalculatorContext* cc) override;
|
2019-08-17 03:49:25 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
double threshold_{};
|
|
|
|
};
|
|
|
|
REGISTER_CALCULATOR(ThresholdingCalculator);
|
|
|
|
|
2021-02-27 09:21:16 +01:00
|
|
|
absl::Status ThresholdingCalculator::GetContract(CalculatorContract* cc) {
|
2021-07-28 03:20:05 +02:00
|
|
|
RET_CHECK(cc->Inputs().HasTag(kFloatTag));
|
|
|
|
cc->Inputs().Tag(kFloatTag).Set<float>();
|
2019-08-17 03:49:25 +02:00
|
|
|
|
2021-07-28 03:20:05 +02:00
|
|
|
if (cc->Outputs().HasTag(kFlagTag)) {
|
|
|
|
cc->Outputs().Tag(kFlagTag).Set<bool>();
|
2019-08-17 03:49:25 +02:00
|
|
|
}
|
2021-07-28 03:20:05 +02:00
|
|
|
if (cc->Outputs().HasTag(kAcceptTag)) {
|
|
|
|
cc->Outputs().Tag(kAcceptTag).Set<bool>();
|
2019-08-17 03:49:25 +02:00
|
|
|
}
|
2021-07-28 03:20:05 +02:00
|
|
|
if (cc->Outputs().HasTag(kRejectTag)) {
|
|
|
|
cc->Outputs().Tag(kRejectTag).Set<bool>();
|
2019-08-17 03:49:25 +02:00
|
|
|
}
|
2021-07-28 03:20:05 +02:00
|
|
|
if (cc->Inputs().HasTag(kThresholdTag)) {
|
|
|
|
cc->Inputs().Tag(kThresholdTag).Set<double>();
|
2019-08-17 03:49:25 +02:00
|
|
|
}
|
2021-07-28 03:20:05 +02:00
|
|
|
if (cc->InputSidePackets().HasTag(kThresholdTag)) {
|
|
|
|
cc->InputSidePackets().Tag(kThresholdTag).Set<double>();
|
|
|
|
RET_CHECK(!cc->Inputs().HasTag(kThresholdTag))
|
2019-08-17 03:49:25 +02:00
|
|
|
<< "Using both the threshold input side packet and input stream is not "
|
|
|
|
"supported.";
|
|
|
|
}
|
|
|
|
|
2021-02-27 09:21:16 +01:00
|
|
|
return absl::OkStatus();
|
2019-08-17 03:49:25 +02:00
|
|
|
}
|
|
|
|
|
2021-02-27 09:21:16 +01:00
|
|
|
absl::Status ThresholdingCalculator::Open(CalculatorContext* cc) {
|
2019-08-17 03:49:25 +02:00
|
|
|
cc->SetOffset(TimestampDiff(0));
|
|
|
|
|
|
|
|
const auto& options =
|
|
|
|
cc->Options<::mediapipe::ThresholdingCalculatorOptions>();
|
|
|
|
if (options.has_threshold()) {
|
2021-07-28 03:20:05 +02:00
|
|
|
RET_CHECK(!cc->Inputs().HasTag(kThresholdTag))
|
2019-08-17 03:49:25 +02:00
|
|
|
<< "Using both the threshold option and input stream is not supported.";
|
2021-07-28 03:20:05 +02:00
|
|
|
RET_CHECK(!cc->InputSidePackets().HasTag(kThresholdTag))
|
2019-08-17 03:49:25 +02:00
|
|
|
<< "Using both the threshold option and input side packet is not "
|
|
|
|
"supported.";
|
|
|
|
threshold_ = options.threshold();
|
|
|
|
}
|
|
|
|
|
2021-07-28 03:20:05 +02:00
|
|
|
if (cc->InputSidePackets().HasTag(kThresholdTag)) {
|
|
|
|
threshold_ = cc->InputSidePackets().Tag(kThresholdTag).Get<double>();
|
2019-08-17 03:49:25 +02:00
|
|
|
}
|
2021-02-27 09:21:16 +01:00
|
|
|
return absl::OkStatus();
|
2019-08-17 03:49:25 +02:00
|
|
|
}
|
|
|
|
|
2021-02-27 09:21:16 +01:00
|
|
|
absl::Status ThresholdingCalculator::Process(CalculatorContext* cc) {
|
2021-07-28 03:20:05 +02:00
|
|
|
if (cc->Inputs().HasTag(kThresholdTag) &&
|
|
|
|
!cc->Inputs().Tag(kThresholdTag).IsEmpty()) {
|
|
|
|
threshold_ = cc->Inputs().Tag(kThresholdTag).Get<double>();
|
2019-08-17 03:49:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool accept = false;
|
2021-07-28 03:20:05 +02:00
|
|
|
RET_CHECK(!cc->Inputs().Tag(kFloatTag).IsEmpty());
|
|
|
|
accept = static_cast<double>(cc->Inputs().Tag(kFloatTag).Get<float>()) >
|
|
|
|
threshold_;
|
2019-08-17 03:49:25 +02:00
|
|
|
|
2021-07-28 03:20:05 +02:00
|
|
|
if (cc->Outputs().HasTag(kFlagTag)) {
|
|
|
|
cc->Outputs().Tag(kFlagTag).AddPacket(
|
2019-08-17 03:49:25 +02:00
|
|
|
MakePacket<bool>(accept).At(cc->InputTimestamp()));
|
|
|
|
}
|
|
|
|
|
2021-07-28 03:20:05 +02:00
|
|
|
if (accept && cc->Outputs().HasTag(kAcceptTag)) {
|
|
|
|
cc->Outputs()
|
|
|
|
.Tag(kAcceptTag)
|
|
|
|
.AddPacket(MakePacket<bool>(true).At(cc->InputTimestamp()));
|
2019-08-17 03:49:25 +02:00
|
|
|
}
|
2021-07-28 03:20:05 +02:00
|
|
|
if (!accept && cc->Outputs().HasTag(kRejectTag)) {
|
|
|
|
cc->Outputs()
|
|
|
|
.Tag(kRejectTag)
|
|
|
|
.AddPacket(MakePacket<bool>(false).At(cc->InputTimestamp()));
|
2019-08-17 03:49:25 +02:00
|
|
|
}
|
|
|
|
|
2021-02-27 09:21:16 +01:00
|
|
|
return absl::OkStatus();
|
2019-08-17 03:49:25 +02:00
|
|
|
}
|
|
|
|
} // namespace mediapipe
|