// Copyright 2020 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/modules/objectron/calculators/box_util.h" #include "mediapipe/framework/port/gmock.h" #include "mediapipe/framework/port/gtest.h" #include "mediapipe/framework/port/opencv_core_inc.h" #include "mediapipe/util/tracking/box_tracker.pb.h" namespace mediapipe { namespace { TEST(BoxUtilTest, TestComputeBoundingRect) { std::vector points{ cv::Point2f(0.35f, 0.25f), cv::Point2f(0.3f, 0.3f), cv::Point2f(0.2f, 0.4f), cv::Point2f(0.3f, 0.1f), cv::Point2f(0.2f, 0.2f), cv::Point2f(0.5f, 0.3f), cv::Point2f(0.4f, 0.4f), cv::Point2f(0.5f, 0.1f), cv::Point2f(0.4f, 0.2f)}; TimedBoxProto box; ComputeBoundingRect(points, &box); EXPECT_FLOAT_EQ(0.1f, box.top()); EXPECT_FLOAT_EQ(0.4f, box.bottom()); EXPECT_FLOAT_EQ(0.2f, box.left()); EXPECT_FLOAT_EQ(0.5f, box.right()); } TEST(BoxUtilTest, TestComputeBoxIoU) { TimedBoxProto box1; box1.set_top(0.2f); box1.set_bottom(0.6f); box1.set_left(0.1f); box1.set_right(0.3f); box1.set_rotation(0.0f); TimedBoxProto box2 = box1; box2.set_rotation(/*pi/2*/ 1.570796f); const float box_area = (box1.bottom() - box1.top()) * (box1.right() - box1.left()); const float box_intersection = (box1.right() - box1.left()) * (box1.right() - box1.left()); const float expected_iou = box_intersection / (box_area * 2 - box_intersection); EXPECT_NEAR(expected_iou, ComputeBoxIoU(box1, box2), 3e-5f); TimedBoxProto box3; box3.set_top(0.2f); box3.set_bottom(0.6f); box3.set_left(0.5f); box3.set_right(0.7f); EXPECT_NEAR(0.0f, ComputeBoxIoU(box1, box3), 3e-5f); } TEST(BoxUtilTest, TestPerspectiveTransformBetweenBoxes) { TimedBoxProto box1; const float height = 4.0f; const float width = 3.0f; box1.set_top(1.0f / height); box1.set_bottom(2.0f / height); box1.set_left(1.0f / width); box1.set_right(2.0f / width); TimedBoxProto box2; box2.set_top(1.0f / height); box2.set_bottom(2.0f / height); box2.set_left(1.0f / width); box2.set_right(2.0f / width); box2.set_rotation(/*pi/4*/ -0.785398f); cv::Mat transform = PerspectiveTransformBetweenBoxes(box1, box2, width / height); const float kTolerence = 1e-5f; const cv::Vec3f original_position(1.5f / width, 1.0f / height, 1.0f); const cv::Mat transformed_position = transform * cv::Mat(original_position); EXPECT_NEAR( (1.5f - 0.5f * std::sqrt(2) / 2.0f) / width, transformed_position.at(0) / transformed_position.at(2), kTolerence); EXPECT_NEAR( (1.5f - 0.5f * std::sqrt(2) / 2.0f) / height, transformed_position.at(1) / transformed_position.at(2), kTolerence); } TEST(BoxUtilTest, TestMapPoint) { const float height = 4.0f; const float width = 3.0f; TimedBoxProto box1; box1.set_top(1.0f / height); box1.set_bottom(2.0f / height); box1.set_left(1.0f / width); box1.set_right(2.0f / width); TimedBoxProto box2; box2.set_top(1.0f / height); box2.set_bottom(2.0f / height); box2.set_left(1.0f / width); box2.set_right(2.0f / width); box2.set_rotation(/*pi/4*/ -0.785398f); cv::Point2f src_point1(1.2f / width, 1.4f / height); cv::Point2f src_point2(1.3f / width, 1.8f / height); const float distance1 = std::sqrt(0.1 * 0.1 + 0.4 * 0.4); cv::Point2f dst_point1 = MapPoint(box1, box2, src_point1, width, height); cv::Point2f dst_point2 = MapPoint(box1, box2, src_point2, width, height); const float distance2 = std::sqrt((dst_point1.x * width - dst_point2.x * width) * (dst_point1.x * width - dst_point2.x * width) + (dst_point1.y * height - dst_point2.y * height) * (dst_point1.y * height - dst_point2.y * height)); EXPECT_NEAR(distance1, distance2, 1e-5f); } } // namespace } // namespace mediapipe