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,
 | 
					    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(
 | 
					cc_library(
 | 
				
			||||||
    name = "tensors_dequantization_calculator",
 | 
					    name = "tensors_dequantization_calculator",
 | 
				
			||||||
    srcs = ["tensors_dequantization_calculator.cc"],
 | 
					    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