124 lines
4.3 KiB
C++
124 lines
4.3 KiB
C++
|
// 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<cv::Point2f> 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<float>(0) / transformed_position.at<float>(2),
|
||
|
kTolerence);
|
||
|
EXPECT_NEAR(
|
||
|
(1.5f - 0.5f * std::sqrt(2) / 2.0f) / height,
|
||
|
transformed_position.at<float>(1) / transformed_position.at<float>(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
|