Initial test for TensorsToSegmentationCalculator
This test is a pass-through with no modification of the input tensor. CPU test. PiperOrigin-RevId: 574210865
This commit is contained in:
parent
dd215e00f5
commit
de1b1b6b97
|
@ -1450,6 +1450,30 @@ cc_library(
|
|||
alwayslink = 1,
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "tensors_to_segmentation_calculator_test",
|
||||
srcs = ["tensors_to_segmentation_calculator_test.cc"],
|
||||
deps = [
|
||||
":tensors_to_segmentation_calculator",
|
||||
":tensors_to_segmentation_calculator_cc_proto",
|
||||
"//mediapipe/framework:calculator_framework",
|
||||
"//mediapipe/framework:calculator_runner",
|
||||
"//mediapipe/framework:packet",
|
||||
"//mediapipe/framework:timestamp",
|
||||
"//mediapipe/framework/formats:image",
|
||||
"//mediapipe/framework/formats:image_format_cc_proto",
|
||||
"//mediapipe/framework/formats:image_opencv",
|
||||
"//mediapipe/framework/formats:rect_cc_proto",
|
||||
"//mediapipe/framework/formats:tensor",
|
||||
"//mediapipe/framework/port:gtest_main",
|
||||
"//mediapipe/framework/port:parse_text_proto",
|
||||
"@com_google_absl//absl/log",
|
||||
"@com_google_absl//absl/log:absl_log",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "tensors_dequantization_calculator",
|
||||
srcs = ["tensors_dequantization_calculator.cc"],
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
// Copyright 2023 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 <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/log/absl_log.h"
|
||||
#include "absl/log/log.h"
|
||||
#include "absl/strings/substitute.h"
|
||||
#include "mediapipe/calculators/tensor/tensors_to_segmentation_calculator.pb.h"
|
||||
#include "mediapipe/framework/calculator_framework.h"
|
||||
#include "mediapipe/framework/calculator_runner.h"
|
||||
#include "mediapipe/framework/formats/image.h"
|
||||
#include "mediapipe/framework/formats/image_format.pb.h"
|
||||
#include "mediapipe/framework/formats/image_opencv.h"
|
||||
#include "mediapipe/framework/formats/rect.pb.h"
|
||||
#include "mediapipe/framework/formats/tensor.h"
|
||||
#include "mediapipe/framework/packet.h"
|
||||
#include "mediapipe/framework/port/gtest.h"
|
||||
#include "mediapipe/framework/port/parse_text_proto.h"
|
||||
#include "mediapipe/framework/port/status_matchers.h"
|
||||
#include "mediapipe/framework/timestamp.h"
|
||||
|
||||
namespace mediapipe {
|
||||
namespace {
|
||||
|
||||
using ::testing::SizeIs;
|
||||
using ::testing::TestWithParam;
|
||||
using Options = mediapipe::TensorsToSegmentationCalculatorOptions;
|
||||
|
||||
std::string ActivationTypeToString(Options::Activation activation) {
|
||||
switch (activation) {
|
||||
case Options::NONE:
|
||||
return "NONE";
|
||||
case Options::SIGMOID:
|
||||
return "SIGMOID";
|
||||
case Options::SOFTMAX:
|
||||
return "SOFTMAX";
|
||||
default:
|
||||
ABSL_LOG(FATAL) << "Unknown activation type: " << activation;
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
struct FormattingTestCase {
|
||||
std::string test_name;
|
||||
std::vector<float> inputs;
|
||||
std::vector<float> expected_outputs;
|
||||
Options::Activation activation;
|
||||
int rows;
|
||||
int cols;
|
||||
int channels;
|
||||
};
|
||||
|
||||
using TensorsToSegmentationCalculatorTest = TestWithParam<FormattingTestCase>;
|
||||
|
||||
// Currently only useable for tests with no output resize.
|
||||
TEST_P(TensorsToSegmentationCalculatorTest, ParameterizedTests) {
|
||||
const FormattingTestCase& test_case = GetParam();
|
||||
std::vector<float> inputs = test_case.inputs;
|
||||
std::vector<float> expected_outputs = test_case.expected_outputs;
|
||||
Options::Activation activation = test_case.activation;
|
||||
int rows = test_case.rows;
|
||||
int cols = test_case.cols;
|
||||
int channels = test_case.channels;
|
||||
|
||||
std::string string_config = absl::Substitute(
|
||||
R"pb(
|
||||
input_stream: "tensors"
|
||||
input_stream: "size"
|
||||
node {
|
||||
calculator: "TensorsToSegmentationCalculator"
|
||||
input_stream: "TENSORS:tensors"
|
||||
input_stream: "OUTPUT_SIZE:size"
|
||||
output_stream: "MASK:image_as_mask"
|
||||
options: {
|
||||
[mediapipe.TensorsToSegmentationCalculatorOptions.ext] {
|
||||
activation: $0
|
||||
}
|
||||
}
|
||||
}
|
||||
)pb",
|
||||
ActivationTypeToString(activation));
|
||||
auto graph_config =
|
||||
mediapipe::ParseTextProtoOrDie<CalculatorGraphConfig>(string_config);
|
||||
|
||||
std::vector<Packet> output_packets;
|
||||
tool::AddVectorSink("image_as_mask", &graph_config, &output_packets);
|
||||
|
||||
CalculatorGraph graph;
|
||||
MP_ASSERT_OK(graph.Initialize(graph_config));
|
||||
MP_ASSERT_OK(graph.StartRun({}));
|
||||
|
||||
auto tensors = std::make_unique<std::vector<Tensor>>();
|
||||
tensors->emplace_back(Tensor::ElementType::kFloat32,
|
||||
Tensor::Shape{1, rows, cols, channels});
|
||||
|
||||
// We scope the tensor's GetCpuWriteView() call so that its lock is released
|
||||
// before we pass it into the graph.
|
||||
{
|
||||
auto view = tensors->back().GetCpuWriteView();
|
||||
float* tensor_buffer = view.buffer<float>();
|
||||
for (int i = 0; i < inputs.size(); ++i) {
|
||||
tensor_buffer[i] = inputs[i];
|
||||
}
|
||||
MP_ASSERT_OK(graph.AddPacketToInputStream(
|
||||
"tensors", mediapipe::Adopt(tensors.release()).At(Timestamp(0))));
|
||||
}
|
||||
MP_ASSERT_OK(graph.AddPacketToInputStream(
|
||||
"size",
|
||||
mediapipe::Adopt(new std::pair<int, int>(rows, cols)).At(Timestamp(0))));
|
||||
MP_ASSERT_OK(graph.WaitUntilIdle());
|
||||
|
||||
ASSERT_THAT(output_packets, SizeIs(1));
|
||||
const Image& image_as_mask = output_packets[0].Get<Image>();
|
||||
std::shared_ptr<cv::Mat> result_mat = formats::MatView(&image_as_mask);
|
||||
EXPECT_EQ(result_mat->rows, rows);
|
||||
EXPECT_EQ(result_mat->cols, cols);
|
||||
EXPECT_EQ(result_mat->channels(), channels);
|
||||
|
||||
// Compare the real result with the expected result.
|
||||
cv::Mat expected_result = cv::Mat(
|
||||
rows, cols, CV_32FC1, const_cast<float*>(expected_outputs.data()));
|
||||
cv::Mat diff;
|
||||
cv::absdiff(*result_mat, expected_result, diff);
|
||||
double max_val;
|
||||
cv::minMaxLoc(diff, nullptr, &max_val);
|
||||
// Expects the maximum absolute pixel-by-pixel difference is less than 1e-5.
|
||||
// This delta is for passthorugh accuracy only.
|
||||
EXPECT_LE(max_val, 1e-5);
|
||||
|
||||
MP_ASSERT_OK(graph.CloseInputStream("tensors"));
|
||||
MP_ASSERT_OK(graph.CloseInputStream("size"));
|
||||
MP_ASSERT_OK(graph.WaitUntilDone());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
TensorsToSegmentationCalculatorTests, TensorsToSegmentationCalculatorTest,
|
||||
testing::ValuesIn<FormattingTestCase>({
|
||||
{/*test_name=*/"NoActivationAndNoOutputResize",
|
||||
/*inputs=*/
|
||||
{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0,
|
||||
14.0, 15.0, 16.0},
|
||||
/*expected_outputs=*/
|
||||
{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0,
|
||||
14.0, 15.0, 16.0},
|
||||
/*activation=*/Options::NONE,
|
||||
/*rows=*/4,
|
||||
/*cols=*/4,
|
||||
/*channels=*/1},
|
||||
}),
|
||||
[](const testing::TestParamInfo<
|
||||
TensorsToSegmentationCalculatorTest::ParamType>& info) {
|
||||
return info.param.test_name;
|
||||
});
|
||||
|
||||
} // namespace
|
||||
} // namespace mediapipe
|
Loading…
Reference in New Issue
Block a user