From d06c701dfc59f196bac017708b626f0daa92973f Mon Sep 17 00:00:00 2001 From: Peng Li Date: Sun, 22 Jul 2018 21:21:15 +0800 Subject: [PATCH] add utils.cpp and testcase --- include/Utils.h | 25 ++++++++++++++ include/hungarian.h | 8 ----- src/MultiTracker.cpp | 22 ++----------- src/Tracker.cpp | 5 +-- src/Utils.cpp | 45 ++++++++++++++++++++++++++ src/hungarian.cpp | 11 ------- test/SConscript | 1 + test/TestHungarian.cpp | 62 ----------------------------------- test/TestUtils.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 162 insertions(+), 105 deletions(-) create mode 100644 include/Utils.h create mode 100644 src/Utils.cpp create mode 100644 test/TestUtils.cpp diff --git a/include/Utils.h b/include/Utils.h new file mode 100644 index 0000000..3bf893e --- /dev/null +++ b/include/Utils.h @@ -0,0 +1,25 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +#include +#include "Detector.h" + + +// Computes the consine distance between u and v +// https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.cosine.html#scipy.spatial.distance.cosine +double distance_cosine(const Eigen::VectorXd& u, const Eigen::VectorXd& v); + +// Computes the Euclidean distance between u and v +// https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.euclidean.html#scipy.spatial.distance.euclidean +double distance_euclidean(const Eigen::VectorXd& u, const Eigen::VectorXd& v); + + + +// Convert coordinates in Detection (center_x, center_y, w, h) to cv::Rect (x, y, w, h) +cv::Rect getRectInDetection(const suanzi::Detection& d); + + +// Calculate the IOU (Intersection Over Union) of two Detection +double calc_iou_ratio(const cv::Rect& r1, const cv::Rect& r2); + +#endif // _UTILS_H_ diff --git a/include/hungarian.h b/include/hungarian.h index df1f354..034aebe 100644 --- a/include/hungarian.h +++ b/include/hungarian.h @@ -13,12 +13,4 @@ int linear_sum_assignment(const Eigen::MatrixXi& cost_matrix, Eigen::VectorXi& row_ind, Eigen::VectorXi& col_ind); -// Computes the consine distance between u and v -// https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.cosine.html#scipy.spatial.distance.cosine -double distance_cosine(const Eigen::VectorXd& u, const Eigen::VectorXd& v); - -// Computes the Euclidean distance between u and v -// https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.euclidean.html#scipy.spatial.distance.euclidean -double distance_euclidean(const Eigen::VectorXd& u, const Eigen::VectorXd& v); - #endif // _HUNGARIAN_H_ diff --git a/src/MultiTracker.cpp b/src/MultiTracker.cpp index c87395e..f3a7cad 100644 --- a/src/MultiTracker.cpp +++ b/src/MultiTracker.cpp @@ -3,6 +3,7 @@ #include #include "hungarian.h" #include "Logger.h" +#include "Utils.h" using namespace suanzi; using namespace cv; @@ -31,25 +32,6 @@ MultiTracker::~MultiTracker() trackers.clear(); } -static Rect getRectInDetection(const Detection& d) -{ - Rect r; - r.x = d.center_x - d.width / 2; - r.y = d.center_y - d.height / 2; - r.width = d.width; - r.height = d.height; - return r; -} - -static double calc_iou_ratio(const Detection& d1, const Detection& d2) -{ - Rect r1 = getRectInDetection (d1); - Rect r2 = getRectInDetection (d2); - Rect r_inner = r1 & r1; - Rect r_union = r1 | r2; - return 1.0 * r_inner.area() / r_union.area(); -} - static std::vector similarity(const PatchPtr p1, const PatchPtr p2) { std::vector feature; @@ -79,7 +61,7 @@ static std::vector similarity(const PatchPtr p1, const PatchPtr p2) double center_distance = sqrt(pow((d1.center_x - d2.center_x), 2) + pow((d1.center_y - d2.center_y), 2)); feature.push_back(center_distance / (d1.width + d1.height + d2.width + d2.height) * 4); - feature.push_back(calc_iou_ratio(d1, d2)); + feature.push_back(calc_iou_ratio(getRectInDetection(d1), getRectInDetection(d2))); return feature; } diff --git a/src/Tracker.cpp b/src/Tracker.cpp index 99a4e28..8e5caaf 100644 --- a/src/Tracker.cpp +++ b/src/Tracker.cpp @@ -10,8 +10,7 @@ Tracker::Tracker(const cv::Mat& image,int id) : id(id) status = TrackerStatus::Fire; preStatus = TrackerStatus::Fire; - // TODO - // init KalmanFilter + // TODO: Kalman filter this->kf.transitionMatrix = (Mat_(4, 4) << 1, 0, 1, 0, 0, 1, 0, 1, @@ -25,8 +24,6 @@ Tracker::Tracker(const cv::Mat& image,int id) : id(id) this->kf.processNoiseCov = 1e-5 * Mat_::eye(4, 4); this->kf.measurementNoiseCov = 1e-1 * Mat_::ones(2, 2); this->kf.errorCovPost = 1. * Mat_::ones(4, 4); - - } Tracker::~Tracker() diff --git a/src/Utils.cpp b/src/Utils.cpp new file mode 100644 index 0000000..c174e28 --- /dev/null +++ b/src/Utils.cpp @@ -0,0 +1,45 @@ +#include "Utils.h" + +using namespace suanzi; +using namespace cv; + +double distance_cosine(const Eigen::VectorXd& u, const Eigen::VectorXd& v) +{ + return (1 - u.dot(v) / std::sqrt(u.dot(u) * v.dot(v))); +} + +double distance_euclidean(const Eigen::VectorXd& u, const Eigen::VectorXd& v) +{ + Eigen::VectorXd d = u - v; + return std::sqrt(d.dot(d)); +} + + +Rect getRectInDetection(const Detection& d) +{ + Rect r; + r.x = d.center_x - d.width / 2; + r.y = d.center_y - d.height / 2; + r.width = d.width; + r.height = d.height; + return r; +} + +double calc_iou_ratio(const Rect& r1, const Rect& r2) +{ + double iou; + Rect r_inner = r1 & r2; + Rect r_union = r1 | r2; + if (r_inner.area() > 0){ + iou = 1.0 * r_inner.area() / r_union.area(); + }else{ + Rect rr; + rr.x = min(r1.x + r1.width, r2.x + r2.width); + rr.y = min(r1.y + r1.height, r2.y + r2.height); + rr.width = max(r1.x, r2.x) - rr.x; + rr.height = max(r1.y, r2.y) - rr.y; + iou = -1.0 * rr.area() / r_union.area(); + } + return iou; + +} diff --git a/src/hungarian.cpp b/src/hungarian.cpp index e8f49e3..fffb1f3 100644 --- a/src/hungarian.cpp +++ b/src/hungarian.cpp @@ -307,14 +307,3 @@ int step_six(Hungary& state) return 4; } -//////////////////////////////////////////////////////////////////////////////// -double distance_cosine(const VectorXd& u, const VectorXd& v) -{ - return (1 - u.dot(v) / std::sqrt(u.dot(u) * v.dot(v))); -} - -double distance_euclidean(const VectorXd& u, const VectorXd& v) -{ - VectorXd d = u - v; - return std::sqrt(d.dot(d)); -} diff --git a/test/SConscript b/test/SConscript index ff200bc..1ca3bdc 100644 --- a/test/SConscript +++ b/test/SConscript @@ -13,6 +13,7 @@ else: env1.Append(LIBPATH = ['#third_party/googletest/lib']) env1['LIBS'] = ['tracker', 'gtest', 'pthread'] +env1.ParseConfig("pkg-config --libs opencv") obj = env1.Object(Glob("*.cpp")) diff --git a/test/TestHungarian.cpp b/test/TestHungarian.cpp index 55620a9..0ab52a0 100644 --- a/test/TestHungarian.cpp +++ b/test/TestHungarian.cpp @@ -54,65 +54,3 @@ TEST(Hungarian, 0x0) int ret = linear_sum_assignment(C, row_ind, col_ind); EXPECT_EQ(ret, 0); } - - -TEST(Distance, consine) -{ - Vector3d u, v; - u << 1, 0, 0; - v << 0, 1, 0; - double d = distance_cosine(u, v); - EXPECT_DOUBLE_EQ(d, 1.0); - - u << 100, 0, 0; - v << 0, 1, 0; - d = distance_cosine(u, v); - EXPECT_DOUBLE_EQ(d, 1.0); - - u << 1, 1, 0; - v << 0, 1, 0; - d = distance_cosine(u, v); - EXPECT_TRUE(std::abs(d - 0.2928932) < 0.0001); -} - -TEST(Distance, euclidean) -{ - Vector3d u, v; - u << 1, 0, 0; - v << 0, 1, 0; - double d = distance_euclidean(u, v); - EXPECT_TRUE(std::abs(d - 1.41421356) < 0.0001); - - u << 1, 1, 0; - v << 0, 1, 0; - d = distance_euclidean(u, v); - EXPECT_DOUBLE_EQ(d, 1.0); -} - -TEST(Distance, vector) -{ - std::vector sv = {1, 2, 3, 4, 5, 6}; - VectorXi v1; - VectorXi b = Eigen::Map(sv.data(), sv.size()); - std::cout << b << std::endl; - std::vector f1_hog = { 0.1, 0.2, 0,3}; -// Eigen::Map(f2_hog.data(), f2_hog.size()) - - //VectorXd mf = Map >(sv.data(), sv.size()); - std::vector sd = {1, 2, 3, 4, 5, 6}; - VectorXd mm = Map(sd.data(), sd.size()); - VectorXd xd = Map >(sd.data(), sd.size()); - cout << Map >(sd.data(), sd.size()) << endl; - - int array[12]; - for(int i = 0; i < 12; ++i) array[i] = i; - cout << Map >(sv.data(), sv.size()) // the inner stride has already been passed as template parameter - << endl; - - - //Vector3d v = Vector3d::Random(); - //std::cout << v << std::endl; - -} - - diff --git a/test/TestUtils.cpp b/test/TestUtils.cpp new file mode 100644 index 0000000..40acc4f --- /dev/null +++ b/test/TestUtils.cpp @@ -0,0 +1,88 @@ +#include "gtest/gtest.h" +#include "Utils.h" + +using namespace std; +using namespace Eigen; +using namespace suanzi; +using namespace cv; + +TEST(Distance, consine) +{ + Vector3d u, v; + u << 1, 0, 0; + v << 0, 1, 0; + double d = distance_cosine(u, v); + EXPECT_DOUBLE_EQ(d, 1.0); + + u << 100, 0, 0; + v << 0, 1, 0; + d = distance_cosine(u, v); + EXPECT_DOUBLE_EQ(d, 1.0); + + u << 1, 1, 0; + v << 0, 1, 0; + d = distance_cosine(u, v); + EXPECT_TRUE(std::abs(d - 0.2928932) < 0.0001); +} + +TEST(Distance, euclidean) +{ + Vector3d u, v; + u << 1, 0, 0; + v << 0, 1, 0; + double d = distance_euclidean(u, v); + EXPECT_TRUE(std::abs(d - 1.41421356) < 0.0001); + + u << 1, 1, 0; + v << 0, 1, 0; + d = distance_euclidean(u, v); + EXPECT_DOUBLE_EQ(d, 1.0); +} + +TEST(MultiTracker, getRectInDetection) +{ + Detection d; + d.center_x = 5; + d.center_y = 5; + d.height = 10; + d.width = 10; + + Rect r = getRectInDetection(d); + EXPECT_EQ(r.x, 0); + EXPECT_EQ(r.y, 0); + EXPECT_EQ(r.width, 10); + EXPECT_EQ(r.height, 10); +} + +TEST(MultiTracker, calc_iou_ratio1) +{ + Rect r1 (0, 0, 10, 10); + Rect r2 (0, 0, 10, 10); + double iou = calc_iou_ratio(r1, r2); + cout << "iou = " << iou << endl; + double expect = 1.0; + EXPECT_GE (iou, 0); // > 0 + EXPECT_TRUE(abs(iou - expect) < 0.001); // Expect is 1.0 +} + +TEST(MultiTracker, calc_iou_ratio2) +{ + Rect r1 (0, 0, 10, 10); + Rect r2 (10, 10, 10, 10); + double iou = calc_iou_ratio(r1, r2); + cout << "iou = " << iou << endl; + double expect = 0; + EXPECT_EQ (iou, 0.0); // = 0 + EXPECT_TRUE(abs(iou - expect) < 0.001); // Expect is = 0 +} + +TEST(MultiTracker, calc_iou_ratio3) +{ + Rect r1 (0, 0, 10, 10); + Rect r2 (20, 20, 10, 10); + double iou = calc_iou_ratio(r1, r2); + cout << "iou = " << iou << endl; + double expect = -(1.0 / 9); + EXPECT_LT (iou, 0.0); // < 0 + EXPECT_TRUE(abs(iou - expect) < 0.0001); // Expect is < -0.111 +} -- 2.11.0