add utils.cpp and testcase
authorPeng Li <seudut@gmail.com>
Sun, 22 Jul 2018 13:21:15 +0000 (21:21 +0800)
committerPeng Li <seudut@gmail.com>
Sun, 22 Jul 2018 13:26:17 +0000 (21:26 +0800)
include/Utils.h [new file with mode: 0644]
include/hungarian.h
src/MultiTracker.cpp
src/Tracker.cpp
src/Utils.cpp [new file with mode: 0644]
src/hungarian.cpp
test/SConscript
test/TestHungarian.cpp
test/TestUtils.cpp [new file with mode: 0644]

diff --git a/include/Utils.h b/include/Utils.h
new file mode 100644 (file)
index 0000000..3bf893e
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _UTILS_H_
+#define _UTILS_H_
+
+#include <eigen3/Eigen/Dense>
+#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_
index df1f354..034aebe 100644 (file)
 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_
index c87395e..f3a7cad 100644 (file)
@@ -3,6 +3,7 @@
 #include <algorithm>
 #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<double> similarity(const PatchPtr p1, const PatchPtr p2)
 {
     std::vector<double> feature;
@@ -79,7 +61,7 @@ static std::vector<double> 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;
 }
index 99a4e28..8e5caaf 100644 (file)
@@ -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_<float>(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_<float>::eye(4, 4);
     this->kf.measurementNoiseCov = 1e-1 * Mat_<float>::ones(2, 2);
     this->kf.errorCovPost = 1. * Mat_<float>::ones(4, 4);
-
-
 }
 
 Tracker::~Tracker()
diff --git a/src/Utils.cpp b/src/Utils.cpp
new file mode 100644 (file)
index 0000000..c174e28
--- /dev/null
@@ -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;
+
+}
index e8f49e3..fffb1f3 100644 (file)
@@ -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));
-}
index ff200bc..1ca3bdc 100644 (file)
@@ -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"))
 
index 55620a9..0ab52a0 100644 (file)
@@ -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<int> sv = {1, 2, 3, 4, 5, 6};
-    VectorXi v1;
-    VectorXi b = Eigen::Map<VectorXi>(sv.data(), sv.size());
-    std::cout << b << std::endl;
-    std::vector<float> f1_hog = { 0.1, 0.2, 0,3};
-//                                    Eigen::Map<Eigen::VectorXd>(f2_hog.data(), f2_hog.size())
-
-    //VectorXd mf = Map<VectorXd, 0, InnerStride<2> >(sv.data(), sv.size());
-    std::vector<double> sd = {1, 2, 3, 4, 5, 6};
-    VectorXd mm = Map<VectorXd>(sd.data(), sd.size());
-    VectorXd xd = Map<VectorXd, 0, InnerStride<2> >(sd.data(), sd.size());
-    cout << Map<VectorXd, 0, InnerStride<2> >(sd.data(), sd.size()) << endl;
-
-    int array[12];
-    for(int i = 0; i < 12; ++i) array[i] = i;
-    cout << Map<VectorXi, 0, InnerStride<2> >(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 (file)
index 0000000..40acc4f
--- /dev/null
@@ -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
+}