--- /dev/null
+#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_
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_
#include <algorithm>
#include "hungarian.h"
#include "Logger.h"
+#include "Utils.h"
using namespace suanzi;
using namespace cv;
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;
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;
}
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,
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()
--- /dev/null
+#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;
+
+}
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));
-}
env1.Append(LIBPATH = ['#third_party/googletest/lib'])
env1['LIBS'] = ['tracker', 'gtest', 'pthread']
+env1.ParseConfig("pkg-config --libs opencv")
obj = env1.Object(Glob("*.cpp"))
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;
-
-}
-
-
--- /dev/null
+#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
+}