[
  {
    "path": "README.md",
    "content": "# bytetrack-opencv-onnxruntime\n使用OpenCV部署YOLOX+ByteTrack目标跟踪，包含C++和Python两个版本的程序。\n\n\n使用ONNXRuntime部署YOLOX+ByteTrack目标跟踪，包含C++和Python两个版本的程序。\n\n由于.onnx文件超过25M，无法直接上传。.onnx文件和测试文件sample.mp4\n在百度云盘，链接: https://pan.baidu.com/s/1dYz_Ru5EgFg_DZhdDHH-Sg  密码: iwtm\n\n安装eigen库和编译C++程序的指令，详情请看文件夹里的readme\n\n运行python程序之前，需要先安装依赖库。如果在安装cython_bbox失败，\n请参见文章 https://www.jianshu.com/p/51f7f7f8b262\n"
  },
  {
    "path": "onnxruntime/README.md",
    "content": "# ByteTrack-onnxruntime\n\n#### 安装\n\n首先确保你的机器安装了opencv和onnxruntime，接下来安装 `eigen`\n\n```shell\nunzip eigen-3.3.9.zip\ncd eigen-3.3.9\nmkdir build\ncd build\ncmake ..\nsudo make install\n```\n\n#### 编译C++程序\n\n```\nmkdir build\ncd build && rm -rf *\ncmake .. && make\n```\n\n#### 运行\n\npython版本：\n\n```\npython main.py\n```\n\nC++版本：\n\n```\n./bytetrack-onnxrun-cpp /home/ByteTrack/sample.mp4\n```\n\n"
  },
  {
    "path": "onnxruntime/cpp/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\nproject(bytetrack-onnxrun-cpp)\nset(CMAKE_CXX_STANDARD 11)\n\nfind_package(OpenCV REQUIRED)\nset(onnxruntime_INCLUDE_DIRS /opt/onnxruntime-linux-x64-1.6.0/include)\ninclude_directories(${onnxruntime_INCLUDE_DIRS})\ninclude_directories(include)\ninclude_directories(/usr/local/include/eigen3)\ninclude_directories(${OpenCV_INCLUDE_DIRS})\nfile(GLOB My_Source_Files src/*.cpp)\nadd_executable(bytetrack-onnxrun-cpp ${My_Source_Files})\ntarget_link_libraries(bytetrack-onnxrun-cpp ${OpenCV_LIBS} /opt/onnxruntime-linux-x64-1.6.0/lib/libonnxruntime.so)"
  },
  {
    "path": "onnxruntime/cpp/include/BYTETracker.h",
    "content": "#pragma once\r\n\r\n#include \"STrack.h\"\r\n\r\nstruct Object\r\n{\r\n    cv::Rect_<float> rect;\r\n    int label;\r\n    float prob;\r\n};\r\n\r\nclass BYTETracker\r\n{\r\npublic:\r\n\tBYTETracker(int frame_rate = 30, int track_buffer = 30);\r\n\t~BYTETracker();\r\n\r\n\tvector<STrack> update(const vector<Object>& objects);\r\n\tScalar get_color(int idx);\r\n\r\nprivate:\r\n\tvector<STrack*> joint_stracks(vector<STrack*> &tlista, vector<STrack> &tlistb);\r\n\tvector<STrack> joint_stracks(vector<STrack> &tlista, vector<STrack> &tlistb);\r\n\r\n\tvector<STrack> sub_stracks(vector<STrack> &tlista, vector<STrack> &tlistb);\r\n\tvoid remove_duplicate_stracks(vector<STrack> &resa, vector<STrack> &resb, vector<STrack> &stracksa, vector<STrack> &stracksb);\r\n\r\n\tvoid linear_assignment(vector<vector<float> > &cost_matrix, int cost_matrix_size, int cost_matrix_size_size, float thresh,\r\n\t\tvector<vector<int> > &matches, vector<int> &unmatched_a, vector<int> &unmatched_b);\r\n\tvector<vector<float> > iou_distance(vector<STrack*> &atracks, vector<STrack> &btracks, int &dist_size, int &dist_size_size);\r\n\tvector<vector<float> > iou_distance(vector<STrack> &atracks, vector<STrack> &btracks);\r\n\tvector<vector<float> > ious(vector<vector<float> > &atlbrs, vector<vector<float> > &btlbrs);\r\n\r\n\tdouble lapjv(const vector<vector<float> > &cost, vector<int> &rowsol, vector<int> &colsol, \r\n\t\tbool extend_cost = false, float cost_limit = LONG_MAX, bool return_cost = true);\r\n\r\nprivate:\r\n\r\n\tfloat track_thresh;\r\n\tfloat high_thresh;\r\n\tfloat match_thresh;\r\n\tint frame_id;\r\n\tint max_time_lost;\r\n\r\n\tvector<STrack> tracked_stracks;\r\n\tvector<STrack> lost_stracks;\r\n\tvector<STrack> removed_stracks;\r\n\tbyte_kalman::KalmanFilter kalman_filter;\r\n};"
  },
  {
    "path": "onnxruntime/cpp/include/STrack.h",
    "content": "#pragma once\r\n\r\n#include <opencv2/opencv.hpp>\r\n#include \"kalmanFilter.h\"\r\n\r\nusing namespace cv;\r\nusing namespace std;\r\n\r\nenum TrackState { New = 0, Tracked, Lost, Removed };\r\n\r\nclass STrack\r\n{\r\npublic:\r\n\tSTrack(vector<float> tlwh_, float score);\r\n\t~STrack();\r\n\r\n\tvector<float> static tlbr_to_tlwh(vector<float> &tlbr);\r\n\tvoid static multi_predict(vector<STrack*> &stracks, byte_kalman::KalmanFilter &kalman_filter);\r\n\tvoid static_tlwh();\r\n\tvoid static_tlbr();\r\n\tvector<float> tlwh_to_xyah(vector<float> tlwh_tmp);\r\n\tvector<float> to_xyah();\r\n\tvoid mark_lost();\r\n\tvoid mark_removed();\r\n\tint next_id();\r\n\tint end_frame();\r\n\t\r\n\tvoid activate(byte_kalman::KalmanFilter &kalman_filter, int frame_id);\r\n\tvoid re_activate(STrack &new_track, int frame_id, bool new_id = false);\r\n\tvoid update(STrack &new_track, int frame_id);\r\n\r\npublic:\r\n\tbool is_activated;\r\n\tint track_id;\r\n\tint state;\r\n\r\n\tvector<float> _tlwh;\r\n\tvector<float> tlwh;\r\n\tvector<float> tlbr;\r\n\tint frame_id;\r\n\tint tracklet_len;\r\n\tint start_frame;\r\n\r\n\tKAL_MEAN mean;\r\n\tKAL_COVA covariance;\r\n\tfloat score;\r\n\r\nprivate:\r\n\tbyte_kalman::KalmanFilter kalman_filter;\r\n};"
  },
  {
    "path": "onnxruntime/cpp/include/dataType.h",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <vector>\r\n\r\n#include <Eigen/Core>\r\n#include <Eigen/Dense>\r\ntypedef Eigen::Matrix<float, 1, 4, Eigen::RowMajor> DETECTBOX;\r\ntypedef Eigen::Matrix<float, -1, 4, Eigen::RowMajor> DETECTBOXSS;\r\ntypedef Eigen::Matrix<float, 1, 128, Eigen::RowMajor> FEATURE;\r\ntypedef Eigen::Matrix<float, Eigen::Dynamic, 128, Eigen::RowMajor> FEATURESS;\r\n//typedef std::vector<FEATURE> FEATURESS;\r\n\r\n//Kalmanfilter\r\n//typedef Eigen::Matrix<float, 8, 8, Eigen::RowMajor> KAL_FILTER;\r\ntypedef Eigen::Matrix<float, 1, 8, Eigen::RowMajor> KAL_MEAN;\r\ntypedef Eigen::Matrix<float, 8, 8, Eigen::RowMajor> KAL_COVA;\r\ntypedef Eigen::Matrix<float, 1, 4, Eigen::RowMajor> KAL_HMEAN;\r\ntypedef Eigen::Matrix<float, 4, 4, Eigen::RowMajor> KAL_HCOVA;\r\nusing KAL_DATA = std::pair<KAL_MEAN, KAL_COVA>;\r\nusing KAL_HDATA = std::pair<KAL_HMEAN, KAL_HCOVA>;\r\n\r\n//main\r\nusing RESULT_DATA = std::pair<int, DETECTBOX>;\r\n\r\n//tracker:\r\nusing TRACKER_DATA = std::pair<int, FEATURESS>;\r\nusing MATCH_DATA = std::pair<int, int>;\r\ntypedef struct t {\r\n\tstd::vector<MATCH_DATA> matches;\r\n\tstd::vector<int> unmatched_tracks;\r\n\tstd::vector<int> unmatched_detections;\r\n}TRACHER_MATCHD;\r\n\r\n//linear_assignment:\r\ntypedef Eigen::Matrix<float, -1, -1, Eigen::RowMajor> DYNAMICM;"
  },
  {
    "path": "onnxruntime/cpp/include/kalmanFilter.h",
    "content": "#pragma once\r\n\r\n#include \"dataType.h\"\r\n\r\nnamespace byte_kalman\r\n{\r\n\tclass KalmanFilter\r\n\t{\r\n\tpublic:\r\n\t\tstatic const double chi2inv95[10];\r\n\t\tKalmanFilter();\r\n\t\tKAL_DATA initiate(const DETECTBOX& measurement);\r\n\t\tvoid predict(KAL_MEAN& mean, KAL_COVA& covariance);\r\n\t\tKAL_HDATA project(const KAL_MEAN& mean, const KAL_COVA& covariance);\r\n\t\tKAL_DATA update(const KAL_MEAN& mean,\r\n\t\t\tconst KAL_COVA& covariance,\r\n\t\t\tconst DETECTBOX& measurement);\r\n\r\n\t\tEigen::Matrix<float, 1, -1> gating_distance(\r\n\t\t\tconst KAL_MEAN& mean,\r\n\t\t\tconst KAL_COVA& covariance,\r\n\t\t\tconst std::vector<DETECTBOX>& measurements,\r\n\t\t\tbool only_position = false);\r\n\r\n\tprivate:\r\n\t\tEigen::Matrix<float, 8, 8, Eigen::RowMajor> _motion_mat;\r\n\t\tEigen::Matrix<float, 4, 8, Eigen::RowMajor> _update_mat;\r\n\t\tfloat _std_weight_position;\r\n\t\tfloat _std_weight_velocity;\r\n\t};\r\n}"
  },
  {
    "path": "onnxruntime/cpp/include/lapjv.h",
    "content": "#ifndef LAPJV_H\r\n#define LAPJV_H\r\n\r\n#define LARGE 1000000\r\n\r\n#if !defined TRUE\r\n#define TRUE 1\r\n#endif\r\n#if !defined FALSE\r\n#define FALSE 0\r\n#endif\r\n\r\n#define NEW(x, t, n) if ((x = (t *)malloc(sizeof(t) * (n))) == 0) { return -1; }\r\n#define FREE(x) if (x != 0) { free(x); x = 0; }\r\n#define SWAP_INDICES(a, b) { int_t _temp_index = a; a = b; b = _temp_index; }\r\n\r\n#if 0\r\n#include <assert.h>\r\n#define ASSERT(cond) assert(cond)\r\n#define PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)\r\n#define PRINT_COST_ARRAY(a, n) \\\r\n    while (1) { \\\r\n        printf(#a\" = [\"); \\\r\n        if ((n) > 0) { \\\r\n            printf(\"%f\", (a)[0]); \\\r\n            for (uint_t j = 1; j < n; j++) { \\\r\n                printf(\", %f\", (a)[j]); \\\r\n            } \\\r\n        } \\\r\n        printf(\"]\\n\"); \\\r\n        break; \\\r\n    }\r\n#define PRINT_INDEX_ARRAY(a, n) \\\r\n    while (1) { \\\r\n        printf(#a\" = [\"); \\\r\n        if ((n) > 0) { \\\r\n            printf(\"%d\", (a)[0]); \\\r\n            for (uint_t j = 1; j < n; j++) { \\\r\n                printf(\", %d\", (a)[j]); \\\r\n            } \\\r\n        } \\\r\n        printf(\"]\\n\"); \\\r\n        break; \\\r\n    }\r\n#else\r\n#define ASSERT(cond)\r\n#define PRINTF(fmt, ...)\r\n#define PRINT_COST_ARRAY(a, n)\r\n#define PRINT_INDEX_ARRAY(a, n)\r\n#endif\r\n\r\n\r\ntypedef signed int int_t;\r\ntypedef unsigned int uint_t;\r\ntypedef double cost_t;\r\ntypedef char boolean;\r\ntypedef enum fp_t { FP_1 = 1, FP_2 = 2, FP_DYNAMIC = 3 } fp_t;\r\n\r\nextern int_t lapjv_internal(\r\n\tconst uint_t n, cost_t *cost[],\r\n\tint_t *x, int_t *y);\r\n\r\n#endif // LAPJV_H"
  },
  {
    "path": "onnxruntime/cpp/src/BYTETracker.cpp",
    "content": "#include \"BYTETracker.h\"\r\n#include <fstream>\r\n\r\nBYTETracker::BYTETracker(int frame_rate, int track_buffer)\r\n{\r\n\ttrack_thresh = 0.5;\r\n\thigh_thresh = 0.6;\r\n\tmatch_thresh = 0.8;\r\n\r\n\tframe_id = 0;\r\n\tmax_time_lost = int(frame_rate / 30.0 * track_buffer);\r\n\tcout << \"Init ByteTrack!\" << endl;\r\n}\r\n\r\nBYTETracker::~BYTETracker()\r\n{\r\n}\r\n\r\nvector<STrack> BYTETracker::update(const vector<Object>& objects)\r\n{\r\n\r\n\t////////////////// Step 1: Get detections //////////////////\r\n\tthis->frame_id++;\r\n\tvector<STrack> activated_stracks;\r\n\tvector<STrack> refind_stracks;\r\n\tvector<STrack> removed_stracks;\r\n\tvector<STrack> lost_stracks;\r\n\tvector<STrack> detections;\r\n\tvector<STrack> detections_low;\r\n\r\n\tvector<STrack> detections_cp;\r\n\tvector<STrack> tracked_stracks_swap;\r\n\tvector<STrack> resa, resb;\r\n\tvector<STrack> output_stracks;\r\n\r\n\tvector<STrack*> unconfirmed;\r\n\tvector<STrack*> tracked_stracks;\r\n\tvector<STrack*> strack_pool;\r\n\tvector<STrack*> r_tracked_stracks;\r\n\r\n\tif (objects.size() > 0)\r\n\t{\r\n\t\tfor (int i = 0; i < objects.size(); i++)\r\n\t\t{\r\n\t\t\tvector<float> tlbr_;\r\n\t\t\ttlbr_.resize(4);\r\n\t\t\ttlbr_[0] = objects[i].rect.x;\r\n\t\t\ttlbr_[1] = objects[i].rect.y;\r\n\t\t\ttlbr_[2] = objects[i].rect.x + objects[i].rect.width;\r\n\t\t\ttlbr_[3] = objects[i].rect.y + objects[i].rect.height;\r\n\r\n\t\t\tfloat score = objects[i].prob;\r\n\r\n\t\t\tSTrack strack(STrack::tlbr_to_tlwh(tlbr_), score);\r\n\t\t\tif (score >= track_thresh)\r\n\t\t\t{\r\n\t\t\t\tdetections.push_back(strack);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tdetections_low.push_back(strack);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t}\r\n\t}\r\n\r\n\t// Add newly detected tracklets to tracked_stracks\r\n\tfor (int i = 0; i < this->tracked_stracks.size(); i++)\r\n\t{\r\n\t\tif (!this->tracked_stracks[i].is_activated)\r\n\t\t\tunconfirmed.push_back(&this->tracked_stracks[i]);\r\n\t\telse\r\n\t\t\ttracked_stracks.push_back(&this->tracked_stracks[i]);\r\n\t}\r\n\r\n\t////////////////// Step 2: First association, with IoU //////////////////\r\n\tstrack_pool = joint_stracks(tracked_stracks, this->lost_stracks);\r\n\tSTrack::multi_predict(strack_pool, this->kalman_filter);\r\n\r\n\tvector<vector<float> > dists;\r\n\tint dist_size = 0, dist_size_size = 0;\r\n\tdists = iou_distance(strack_pool, detections, dist_size, dist_size_size);\r\n\r\n\tvector<vector<int> > matches;\r\n\tvector<int> u_track, u_detection;\r\n\tlinear_assignment(dists, dist_size, dist_size_size, match_thresh, matches, u_track, u_detection);\r\n\r\n\tfor (int i = 0; i < matches.size(); i++)\r\n\t{\r\n\t\tSTrack *track = strack_pool[matches[i][0]];\r\n\t\tSTrack *det = &detections[matches[i][1]];\r\n\t\tif (track->state == TrackState::Tracked)\r\n\t\t{\r\n\t\t\ttrack->update(*det, this->frame_id);\r\n\t\t\tactivated_stracks.push_back(*track);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ttrack->re_activate(*det, this->frame_id, false);\r\n\t\t\trefind_stracks.push_back(*track);\r\n\t\t}\r\n\t}\r\n\r\n\t////////////////// Step 3: Second association, using low score dets //////////////////\r\n\tfor (int i = 0; i < u_detection.size(); i++)\r\n\t{\r\n\t\tdetections_cp.push_back(detections[u_detection[i]]);\r\n\t}\r\n\tdetections.clear();\r\n\tdetections.assign(detections_low.begin(), detections_low.end());\r\n\t\r\n\tfor (int i = 0; i < u_track.size(); i++)\r\n\t{\r\n\t\tif (strack_pool[u_track[i]]->state == TrackState::Tracked)\r\n\t\t{\r\n\t\t\tr_tracked_stracks.push_back(strack_pool[u_track[i]]);\r\n\t\t}\r\n\t}\r\n\r\n\tdists.clear();\r\n\tdists = iou_distance(r_tracked_stracks, detections, dist_size, dist_size_size);\r\n\r\n\tmatches.clear();\r\n\tu_track.clear();\r\n\tu_detection.clear();\r\n\tlinear_assignment(dists, dist_size, dist_size_size, 0.5, matches, u_track, u_detection);\r\n\r\n\tfor (int i = 0; i < matches.size(); i++)\r\n\t{\r\n\t\tSTrack *track = r_tracked_stracks[matches[i][0]];\r\n\t\tSTrack *det = &detections[matches[i][1]];\r\n\t\tif (track->state == TrackState::Tracked)\r\n\t\t{\r\n\t\t\ttrack->update(*det, this->frame_id);\r\n\t\t\tactivated_stracks.push_back(*track);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ttrack->re_activate(*det, this->frame_id, false);\r\n\t\t\trefind_stracks.push_back(*track);\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int i = 0; i < u_track.size(); i++)\r\n\t{\r\n\t\tSTrack *track = r_tracked_stracks[u_track[i]];\r\n\t\tif (track->state != TrackState::Lost)\r\n\t\t{\r\n\t\t\ttrack->mark_lost();\r\n\t\t\tlost_stracks.push_back(*track);\r\n\t\t}\r\n\t}\r\n\r\n\t// Deal with unconfirmed tracks, usually tracks with only one beginning frame\r\n\tdetections.clear();\r\n\tdetections.assign(detections_cp.begin(), detections_cp.end());\r\n\r\n\tdists.clear();\r\n\tdists = iou_distance(unconfirmed, detections, dist_size, dist_size_size);\r\n\r\n\tmatches.clear();\r\n\tvector<int> u_unconfirmed;\r\n\tu_detection.clear();\r\n\tlinear_assignment(dists, dist_size, dist_size_size, 0.7, matches, u_unconfirmed, u_detection);\r\n\r\n\tfor (int i = 0; i < matches.size(); i++)\r\n\t{\r\n\t\tunconfirmed[matches[i][0]]->update(detections[matches[i][1]], this->frame_id);\r\n\t\tactivated_stracks.push_back(*unconfirmed[matches[i][0]]);\r\n\t}\r\n\r\n\tfor (int i = 0; i < u_unconfirmed.size(); i++)\r\n\t{\r\n\t\tSTrack *track = unconfirmed[u_unconfirmed[i]];\r\n\t\ttrack->mark_removed();\r\n\t\tremoved_stracks.push_back(*track);\r\n\t}\r\n\r\n\t////////////////// Step 4: Init new stracks //////////////////\r\n\tfor (int i = 0; i < u_detection.size(); i++)\r\n\t{\r\n\t\tSTrack *track = &detections[u_detection[i]];\r\n\t\tif (track->score < this->high_thresh)\r\n\t\t\tcontinue;\r\n\t\ttrack->activate(this->kalman_filter, this->frame_id);\r\n\t\tactivated_stracks.push_back(*track);\r\n\t}\r\n\r\n\t////////////////// Step 5: Update state //////////////////\r\n\tfor (int i = 0; i < this->lost_stracks.size(); i++)\r\n\t{\r\n\t\tif (this->frame_id - this->lost_stracks[i].end_frame() > this->max_time_lost)\r\n\t\t{\r\n\t\t\tthis->lost_stracks[i].mark_removed();\r\n\t\t\tremoved_stracks.push_back(this->lost_stracks[i]);\r\n\t\t}\r\n\t}\r\n\t\r\n\tfor (int i = 0; i < this->tracked_stracks.size(); i++)\r\n\t{\r\n\t\tif (this->tracked_stracks[i].state == TrackState::Tracked)\r\n\t\t{\r\n\t\t\ttracked_stracks_swap.push_back(this->tracked_stracks[i]);\r\n\t\t}\r\n\t}\r\n\tthis->tracked_stracks.clear();\r\n\tthis->tracked_stracks.assign(tracked_stracks_swap.begin(), tracked_stracks_swap.end());\r\n\r\n\tthis->tracked_stracks = joint_stracks(this->tracked_stracks, activated_stracks);\r\n\tthis->tracked_stracks = joint_stracks(this->tracked_stracks, refind_stracks);\r\n\r\n\t//std::cout << activated_stracks.size() << std::endl;\r\n\r\n\tthis->lost_stracks = sub_stracks(this->lost_stracks, this->tracked_stracks);\r\n\tfor (int i = 0; i < lost_stracks.size(); i++)\r\n\t{\r\n\t\tthis->lost_stracks.push_back(lost_stracks[i]);\r\n\t}\r\n\r\n\tthis->lost_stracks = sub_stracks(this->lost_stracks, this->removed_stracks);\r\n\tfor (int i = 0; i < removed_stracks.size(); i++)\r\n\t{\r\n\t\tthis->removed_stracks.push_back(removed_stracks[i]);\r\n\t}\r\n\t\r\n\tremove_duplicate_stracks(resa, resb, this->tracked_stracks, this->lost_stracks);\r\n\r\n\tthis->tracked_stracks.clear();\r\n\tthis->tracked_stracks.assign(resa.begin(), resa.end());\r\n\tthis->lost_stracks.clear();\r\n\tthis->lost_stracks.assign(resb.begin(), resb.end());\r\n\t\r\n\tfor (int i = 0; i < this->tracked_stracks.size(); i++)\r\n\t{\r\n\t\tif (this->tracked_stracks[i].is_activated)\r\n\t\t{\r\n\t\t\toutput_stracks.push_back(this->tracked_stracks[i]);\r\n\t\t}\r\n\t}\r\n\treturn output_stracks;\r\n}"
  },
  {
    "path": "onnxruntime/cpp/src/STrack.cpp",
    "content": "#include \"STrack.h\"\r\n\r\nSTrack::STrack(vector<float> tlwh_, float score)\r\n{\r\n\t_tlwh.resize(4);\r\n\t_tlwh.assign(tlwh_.begin(), tlwh_.end());\r\n\r\n\tis_activated = false;\r\n\ttrack_id = 0;\r\n\tstate = TrackState::New;\r\n\t\r\n\ttlwh.resize(4);\r\n\ttlbr.resize(4);\r\n\r\n\tstatic_tlwh();\r\n\tstatic_tlbr();\r\n\tframe_id = 0;\r\n\ttracklet_len = 0;\r\n\tthis->score = score;\r\n\tstart_frame = 0;\r\n}\r\n\r\nSTrack::~STrack()\r\n{\r\n}\r\n\r\nvoid STrack::activate(byte_kalman::KalmanFilter &kalman_filter, int frame_id)\r\n{\r\n\tthis->kalman_filter = kalman_filter;\r\n\tthis->track_id = this->next_id();\r\n\r\n\tvector<float> _tlwh_tmp(4);\r\n\t_tlwh_tmp[0] = this->_tlwh[0];\r\n\t_tlwh_tmp[1] = this->_tlwh[1];\r\n\t_tlwh_tmp[2] = this->_tlwh[2];\r\n\t_tlwh_tmp[3] = this->_tlwh[3];\r\n\tvector<float> xyah = tlwh_to_xyah(_tlwh_tmp);\r\n\tDETECTBOX xyah_box;\r\n\txyah_box[0] = xyah[0];\r\n\txyah_box[1] = xyah[1];\r\n\txyah_box[2] = xyah[2];\r\n\txyah_box[3] = xyah[3];\r\n\tauto mc = this->kalman_filter.initiate(xyah_box);\r\n\tthis->mean = mc.first;\r\n\tthis->covariance = mc.second;\r\n\r\n\tstatic_tlwh();\r\n\tstatic_tlbr();\r\n\r\n\tthis->tracklet_len = 0;\r\n\tthis->state = TrackState::Tracked;\r\n\tif (frame_id == 1)\r\n\t{\r\n\t\tthis->is_activated = true;\r\n\t}\r\n\t//this->is_activated = true;\r\n\tthis->frame_id = frame_id;\r\n\tthis->start_frame = frame_id;\r\n}\r\n\r\nvoid STrack::re_activate(STrack &new_track, int frame_id, bool new_id)\r\n{\r\n\tvector<float> xyah = tlwh_to_xyah(new_track.tlwh);\r\n\tDETECTBOX xyah_box;\r\n\txyah_box[0] = xyah[0];\r\n\txyah_box[1] = xyah[1];\r\n\txyah_box[2] = xyah[2];\r\n\txyah_box[3] = xyah[3];\r\n\tauto mc = this->kalman_filter.update(this->mean, this->covariance, xyah_box);\r\n\tthis->mean = mc.first;\r\n\tthis->covariance = mc.second;\r\n\r\n\tstatic_tlwh();\r\n\tstatic_tlbr();\r\n\r\n\tthis->tracklet_len = 0;\r\n\tthis->state = TrackState::Tracked;\r\n\tthis->is_activated = true;\r\n\tthis->frame_id = frame_id;\r\n\tthis->score = new_track.score;\r\n\tif (new_id)\r\n\t\tthis->track_id = next_id();\r\n}\r\n\r\nvoid STrack::update(STrack &new_track, int frame_id)\r\n{\r\n\tthis->frame_id = frame_id;\r\n\tthis->tracklet_len++;\r\n\r\n\tvector<float> xyah = tlwh_to_xyah(new_track.tlwh);\r\n\tDETECTBOX xyah_box;\r\n\txyah_box[0] = xyah[0];\r\n\txyah_box[1] = xyah[1];\r\n\txyah_box[2] = xyah[2];\r\n\txyah_box[3] = xyah[3];\r\n\r\n\tauto mc = this->kalman_filter.update(this->mean, this->covariance, xyah_box);\r\n\tthis->mean = mc.first;\r\n\tthis->covariance = mc.second;\r\n\r\n\tstatic_tlwh();\r\n\tstatic_tlbr();\r\n\r\n\tthis->state = TrackState::Tracked;\r\n\tthis->is_activated = true;\r\n\r\n\tthis->score = new_track.score;\r\n}\r\n\r\nvoid STrack::static_tlwh()\r\n{\r\n\tif (this->state == TrackState::New)\r\n\t{\r\n\t\ttlwh[0] = _tlwh[0];\r\n\t\ttlwh[1] = _tlwh[1];\r\n\t\ttlwh[2] = _tlwh[2];\r\n\t\ttlwh[3] = _tlwh[3];\r\n\t\treturn;\r\n\t}\r\n\r\n\ttlwh[0] = mean[0];\r\n\ttlwh[1] = mean[1];\r\n\ttlwh[2] = mean[2];\r\n\ttlwh[3] = mean[3];\r\n\r\n\ttlwh[2] *= tlwh[3];\r\n\ttlwh[0] -= tlwh[2] / 2;\r\n\ttlwh[1] -= tlwh[3] / 2;\r\n}\r\n\r\nvoid STrack::static_tlbr()\r\n{\r\n\ttlbr.clear();\r\n\ttlbr.assign(tlwh.begin(), tlwh.end());\r\n\ttlbr[2] += tlbr[0];\r\n\ttlbr[3] += tlbr[1];\r\n}\r\n\r\nvector<float> STrack::tlwh_to_xyah(vector<float> tlwh_tmp)\r\n{\r\n\tvector<float> tlwh_output = tlwh_tmp;\r\n\ttlwh_output[0] += tlwh_output[2] / 2;\r\n\ttlwh_output[1] += tlwh_output[3] / 2;\r\n\ttlwh_output[2] /= tlwh_output[3];\r\n\treturn tlwh_output;\r\n}\r\n\r\nvector<float> STrack::to_xyah()\r\n{\r\n\treturn tlwh_to_xyah(tlwh);\r\n}\r\n\r\nvector<float> STrack::tlbr_to_tlwh(vector<float> &tlbr)\r\n{\r\n\ttlbr[2] -= tlbr[0];\r\n\ttlbr[3] -= tlbr[1];\r\n\treturn tlbr;\r\n}\r\n\r\nvoid STrack::mark_lost()\r\n{\r\n\tstate = TrackState::Lost;\r\n}\r\n\r\nvoid STrack::mark_removed()\r\n{\r\n\tstate = TrackState::Removed;\r\n}\r\n\r\nint STrack::next_id()\r\n{\r\n\tstatic int _count = 0;\r\n\t_count++;\r\n\treturn _count;\r\n}\r\n\r\nint STrack::end_frame()\r\n{\r\n\treturn this->frame_id;\r\n}\r\n\r\nvoid STrack::multi_predict(vector<STrack*> &stracks, byte_kalman::KalmanFilter &kalman_filter)\r\n{\r\n\tfor (int i = 0; i < stracks.size(); i++)\r\n\t{\r\n\t\tif (stracks[i]->state != TrackState::Tracked)\r\n\t\t{\r\n\t\t\tstracks[i]->mean[7] = 0;\r\n\t\t}\r\n\t\tkalman_filter.predict(stracks[i]->mean, stracks[i]->covariance);\r\n\t}\r\n}"
  },
  {
    "path": "onnxruntime/cpp/src/kalmanFilter.cpp",
    "content": "#include \"kalmanFilter.h\"\r\n#include <Eigen/Cholesky>\r\n\r\nnamespace byte_kalman\r\n{\r\n\tconst double KalmanFilter::chi2inv95[10] = {\r\n\t0,\r\n\t3.8415,\r\n\t5.9915,\r\n\t7.8147,\r\n\t9.4877,\r\n\t11.070,\r\n\t12.592,\r\n\t14.067,\r\n\t15.507,\r\n\t16.919\r\n\t};\r\n\tKalmanFilter::KalmanFilter()\r\n\t{\r\n\t\tint ndim = 4;\r\n\t\tdouble dt = 1.;\r\n\r\n\t\t_motion_mat = Eigen::MatrixXf::Identity(8, 8);\r\n\t\tfor (int i = 0; i < ndim; i++) {\r\n\t\t\t_motion_mat(i, ndim + i) = dt;\r\n\t\t}\r\n\t\t_update_mat = Eigen::MatrixXf::Identity(4, 8);\r\n\r\n\t\tthis->_std_weight_position = 1. / 20;\r\n\t\tthis->_std_weight_velocity = 1. / 160;\r\n\t}\r\n\r\n\tKAL_DATA KalmanFilter::initiate(const DETECTBOX &measurement)\r\n\t{\r\n\t\tDETECTBOX mean_pos = measurement;\r\n\t\tDETECTBOX mean_vel;\r\n\t\tfor (int i = 0; i < 4; i++) mean_vel(i) = 0;\r\n\r\n\t\tKAL_MEAN mean;\r\n\t\tfor (int i = 0; i < 8; i++) {\r\n\t\t\tif (i < 4) mean(i) = mean_pos(i);\r\n\t\t\telse mean(i) = mean_vel(i - 4);\r\n\t\t}\r\n\r\n\t\tKAL_MEAN std;\r\n\t\tstd(0) = 2 * _std_weight_position * measurement[3];\r\n\t\tstd(1) = 2 * _std_weight_position * measurement[3];\r\n\t\tstd(2) = 1e-2;\r\n\t\tstd(3) = 2 * _std_weight_position * measurement[3];\r\n\t\tstd(4) = 10 * _std_weight_velocity * measurement[3];\r\n\t\tstd(5) = 10 * _std_weight_velocity * measurement[3];\r\n\t\tstd(6) = 1e-5;\r\n\t\tstd(7) = 10 * _std_weight_velocity * measurement[3];\r\n\r\n\t\tKAL_MEAN tmp = std.array().square();\r\n\t\tKAL_COVA var = tmp.asDiagonal();\r\n\t\treturn std::make_pair(mean, var);\r\n\t}\r\n\r\n\tvoid KalmanFilter::predict(KAL_MEAN &mean, KAL_COVA &covariance)\r\n\t{\r\n\t\t//revise the data;\r\n\t\tDETECTBOX std_pos;\r\n\t\tstd_pos << _std_weight_position * mean(3),\r\n\t\t\t_std_weight_position * mean(3),\r\n\t\t\t1e-2,\r\n\t\t\t_std_weight_position * mean(3);\r\n\t\tDETECTBOX std_vel;\r\n\t\tstd_vel << _std_weight_velocity * mean(3),\r\n\t\t\t_std_weight_velocity * mean(3),\r\n\t\t\t1e-5,\r\n\t\t\t_std_weight_velocity * mean(3);\r\n\t\tKAL_MEAN tmp;\r\n\t\ttmp.block<1, 4>(0, 0) = std_pos;\r\n\t\ttmp.block<1, 4>(0, 4) = std_vel;\r\n\t\ttmp = tmp.array().square();\r\n\t\tKAL_COVA motion_cov = tmp.asDiagonal();\r\n\t\tKAL_MEAN mean1 = this->_motion_mat * mean.transpose();\r\n\t\tKAL_COVA covariance1 = this->_motion_mat * covariance *(_motion_mat.transpose());\r\n\t\tcovariance1 += motion_cov;\r\n\r\n\t\tmean = mean1;\r\n\t\tcovariance = covariance1;\r\n\t}\r\n\r\n\tKAL_HDATA KalmanFilter::project(const KAL_MEAN &mean, const KAL_COVA &covariance)\r\n\t{\r\n\t\tDETECTBOX std;\r\n\t\tstd << _std_weight_position * mean(3), _std_weight_position * mean(3),\r\n\t\t\t1e-1, _std_weight_position * mean(3);\r\n\t\tKAL_HMEAN mean1 = _update_mat * mean.transpose();\r\n\t\tKAL_HCOVA covariance1 = _update_mat * covariance * (_update_mat.transpose());\r\n\t\tEigen::Matrix<float, 4, 4> diag = std.asDiagonal();\r\n\t\tdiag = diag.array().square().matrix();\r\n\t\tcovariance1 += diag;\r\n\t\t//    covariance1.diagonal() << diag;\r\n\t\treturn std::make_pair(mean1, covariance1);\r\n\t}\r\n\r\n\tKAL_DATA\r\n\t\tKalmanFilter::update(\r\n\t\t\tconst KAL_MEAN &mean,\r\n\t\t\tconst KAL_COVA &covariance,\r\n\t\t\tconst DETECTBOX &measurement)\r\n\t{\r\n\t\tKAL_HDATA pa = project(mean, covariance);\r\n\t\tKAL_HMEAN projected_mean = pa.first;\r\n\t\tKAL_HCOVA projected_cov = pa.second;\r\n\r\n\t\t//chol_factor, lower =\r\n\t\t//scipy.linalg.cho_factor(projected_cov, lower=True, check_finite=False)\r\n\t\t//kalmain_gain =\r\n\t\t//scipy.linalg.cho_solve((cho_factor, lower),\r\n\t\t//np.dot(covariance, self._upadte_mat.T).T,\r\n\t\t//check_finite=False).T\r\n\t\tEigen::Matrix<float, 4, 8> B = (covariance * (_update_mat.transpose())).transpose();\r\n\t\tEigen::Matrix<float, 8, 4> kalman_gain = (projected_cov.llt().solve(B)).transpose(); // eg.8x4\r\n\t\tEigen::Matrix<float, 1, 4> innovation = measurement - projected_mean; //eg.1x4\r\n\t\tauto tmp = innovation * (kalman_gain.transpose());\r\n\t\tKAL_MEAN new_mean = (mean.array() + tmp.array()).matrix();\r\n\t\tKAL_COVA new_covariance = covariance - kalman_gain * projected_cov*(kalman_gain.transpose());\r\n\t\treturn std::make_pair(new_mean, new_covariance);\r\n\t}\r\n\r\n\tEigen::Matrix<float, 1, -1>\r\n\t\tKalmanFilter::gating_distance(\r\n\t\t\tconst KAL_MEAN &mean,\r\n\t\t\tconst KAL_COVA &covariance,\r\n\t\t\tconst std::vector<DETECTBOX> &measurements,\r\n\t\t\tbool only_position)\r\n\t{\r\n\t\tKAL_HDATA pa = this->project(mean, covariance);\r\n\t\tif (only_position) {\r\n\t\t\tprintf(\"not implement!\");\r\n\t\t\texit(0);\r\n\t\t}\r\n\t\tKAL_HMEAN mean1 = pa.first;\r\n\t\tKAL_HCOVA covariance1 = pa.second;\r\n\r\n\t\t//    Eigen::Matrix<float, -1, 4, Eigen::RowMajor> d(size, 4);\r\n\t\tDETECTBOXSS d(measurements.size(), 4);\r\n\t\tint pos = 0;\r\n\t\tfor (DETECTBOX box : measurements) {\r\n\t\t\td.row(pos++) = box - mean1;\r\n\t\t}\r\n\t\tEigen::Matrix<float, -1, -1, Eigen::RowMajor> factor = covariance1.llt().matrixL();\r\n\t\tEigen::Matrix<float, -1, -1> z = factor.triangularView<Eigen::Lower>().solve<Eigen::OnTheRight>(d).transpose();\r\n\t\tauto zz = ((z.array())*(z.array())).matrix();\r\n\t\tauto square_maha = zz.colwise().sum();\r\n\t\treturn square_maha;\r\n\t}\r\n}"
  },
  {
    "path": "onnxruntime/cpp/src/lapjv.cpp",
    "content": "#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <string.h>\r\n\r\n#include \"lapjv.h\"\r\n\r\n/** Column-reduction and reduction transfer for a dense cost matrix.\r\n */\r\nint_t _ccrrt_dense(const uint_t n, cost_t *cost[],\r\n\tint_t *free_rows, int_t *x, int_t *y, cost_t *v)\r\n{\r\n\tint_t n_free_rows;\r\n\tboolean *unique;\r\n\r\n\tfor (uint_t i = 0; i < n; i++) {\r\n\t\tx[i] = -1;\r\n\t\tv[i] = LARGE;\r\n\t\ty[i] = 0;\r\n\t}\r\n\tfor (uint_t i = 0; i < n; i++) {\r\n\t\tfor (uint_t j = 0; j < n; j++) {\r\n\t\t\tconst cost_t c = cost[i][j];\r\n\t\t\tif (c < v[j]) {\r\n\t\t\t\tv[j] = c;\r\n\t\t\t\ty[j] = i;\r\n\t\t\t}\r\n\t\t\tPRINTF(\"i=%d, j=%d, c[i,j]=%f, v[j]=%f y[j]=%d\\n\", i, j, c, v[j], y[j]);\r\n\t\t}\r\n\t}\r\n\tPRINT_COST_ARRAY(v, n);\r\n\tPRINT_INDEX_ARRAY(y, n);\r\n\tNEW(unique, boolean, n);\r\n\tmemset(unique, TRUE, n);\r\n\t{\r\n\t\tint_t j = n;\r\n\t\tdo {\r\n\t\t\tj--;\r\n\t\t\tconst int_t i = y[j];\r\n\t\t\tif (x[i] < 0) {\r\n\t\t\t\tx[i] = j;\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tunique[i] = FALSE;\r\n\t\t\t\ty[j] = -1;\r\n\t\t\t}\r\n\t\t} while (j > 0);\r\n\t}\r\n\tn_free_rows = 0;\r\n\tfor (uint_t i = 0; i < n; i++) {\r\n\t\tif (x[i] < 0) {\r\n\t\t\tfree_rows[n_free_rows++] = i;\r\n\t\t}\r\n\t\telse if (unique[i]) {\r\n\t\t\tconst int_t j = x[i];\r\n\t\t\tcost_t min = LARGE;\r\n\t\t\tfor (uint_t j2 = 0; j2 < n; j2++) {\r\n\t\t\t\tif (j2 == (uint_t)j) {\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tconst cost_t c = cost[i][j2] - v[j2];\r\n\t\t\t\tif (c < min) {\r\n\t\t\t\t\tmin = c;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tPRINTF(\"v[%d] = %f - %f\\n\", j, v[j], min);\r\n\t\t\tv[j] -= min;\r\n\t\t}\r\n\t}\r\n\tFREE(unique);\r\n\treturn n_free_rows;\r\n}\r\n\r\n\r\n/** Augmenting row reduction for a dense cost matrix.\r\n */\r\nint_t _carr_dense(\r\n\tconst uint_t n, cost_t *cost[],\r\n\tconst uint_t n_free_rows,\r\n\tint_t *free_rows, int_t *x, int_t *y, cost_t *v)\r\n{\r\n\tuint_t current = 0;\r\n\tint_t new_free_rows = 0;\r\n\tuint_t rr_cnt = 0;\r\n\tPRINT_INDEX_ARRAY(x, n);\r\n\tPRINT_INDEX_ARRAY(y, n);\r\n\tPRINT_COST_ARRAY(v, n);\r\n\tPRINT_INDEX_ARRAY(free_rows, n_free_rows);\r\n\twhile (current < n_free_rows) {\r\n\t\tint_t i0;\r\n\t\tint_t j1, j2;\r\n\t\tcost_t v1, v2, v1_new;\r\n\t\tboolean v1_lowers;\r\n\r\n\t\trr_cnt++;\r\n\t\tPRINTF(\"current = %d rr_cnt = %d\\n\", current, rr_cnt);\r\n\t\tconst int_t free_i = free_rows[current++];\r\n\t\tj1 = 0;\r\n\t\tv1 = cost[free_i][0] - v[0];\r\n\t\tj2 = -1;\r\n\t\tv2 = LARGE;\r\n\t\tfor (uint_t j = 1; j < n; j++) {\r\n\t\t\tPRINTF(\"%d = %f %d = %f\\n\", j1, v1, j2, v2);\r\n\t\t\tconst cost_t c = cost[free_i][j] - v[j];\r\n\t\t\tif (c < v2) {\r\n\t\t\t\tif (c >= v1) {\r\n\t\t\t\t\tv2 = c;\r\n\t\t\t\t\tj2 = j;\r\n\t\t\t\t}\r\n\t\t\t\telse {\r\n\t\t\t\t\tv2 = v1;\r\n\t\t\t\t\tv1 = c;\r\n\t\t\t\t\tj2 = j1;\r\n\t\t\t\t\tj1 = j;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\ti0 = y[j1];\r\n\t\tv1_new = v[j1] - (v2 - v1);\r\n\t\tv1_lowers = v1_new < v[j1];\r\n\t\tPRINTF(\"%d %d 1=%d,%f 2=%d,%f v1'=%f(%d,%g) \\n\", free_i, i0, j1, v1, j2, v2, v1_new, v1_lowers, v[j1] - v1_new);\r\n\t\tif (rr_cnt < current * n) {\r\n\t\t\tif (v1_lowers) {\r\n\t\t\t\tv[j1] = v1_new;\r\n\t\t\t}\r\n\t\t\telse if (i0 >= 0 && j2 >= 0) {\r\n\t\t\t\tj1 = j2;\r\n\t\t\t\ti0 = y[j2];\r\n\t\t\t}\r\n\t\t\tif (i0 >= 0) {\r\n\t\t\t\tif (v1_lowers) {\r\n\t\t\t\t\tfree_rows[--current] = i0;\r\n\t\t\t\t}\r\n\t\t\t\telse {\r\n\t\t\t\t\tfree_rows[new_free_rows++] = i0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse {\r\n\t\t\tPRINTF(\"rr_cnt=%d >= %d (current=%d * n=%d)\\n\", rr_cnt, current * n, current, n);\r\n\t\t\tif (i0 >= 0) {\r\n\t\t\t\tfree_rows[new_free_rows++] = i0;\r\n\t\t\t}\r\n\t\t}\r\n\t\tx[free_i] = j1;\r\n\t\ty[j1] = free_i;\r\n\t}\r\n\treturn new_free_rows;\r\n}\r\n\r\n\r\n/** Find columns with minimum d[j] and put them on the SCAN list.\r\n */\r\nuint_t _find_dense(const uint_t n, uint_t lo, cost_t *d, int_t *cols, int_t *y)\r\n{\r\n\tuint_t hi = lo + 1;\r\n\tcost_t mind = d[cols[lo]];\r\n\tfor (uint_t k = hi; k < n; k++) {\r\n\t\tint_t j = cols[k];\r\n\t\tif (d[j] <= mind) {\r\n\t\t\tif (d[j] < mind) {\r\n\t\t\t\thi = lo;\r\n\t\t\t\tmind = d[j];\r\n\t\t\t}\r\n\t\t\tcols[k] = cols[hi];\r\n\t\t\tcols[hi++] = j;\r\n\t\t}\r\n\t}\r\n\treturn hi;\r\n}\r\n\r\n\r\n// Scan all columns in TODO starting from arbitrary column in SCAN\r\n// and try to decrease d of the TODO columns using the SCAN column.\r\nint_t _scan_dense(const uint_t n, cost_t *cost[],\r\n\tuint_t *plo, uint_t*phi,\r\n\tcost_t *d, int_t *cols, int_t *pred,\r\n\tint_t *y, cost_t *v)\r\n{\r\n\tuint_t lo = *plo;\r\n\tuint_t hi = *phi;\r\n\tcost_t h, cred_ij;\r\n\r\n\twhile (lo != hi) {\r\n\t\tint_t j = cols[lo++];\r\n\t\tconst int_t i = y[j];\r\n\t\tconst cost_t mind = d[j];\r\n\t\th = cost[i][j] - v[j] - mind;\r\n\t\tPRINTF(\"i=%d j=%d h=%f\\n\", i, j, h);\r\n\t\t// For all columns in TODO\r\n\t\tfor (uint_t k = hi; k < n; k++) {\r\n\t\t\tj = cols[k];\r\n\t\t\tcred_ij = cost[i][j] - v[j] - h;\r\n\t\t\tif (cred_ij < d[j]) {\r\n\t\t\t\td[j] = cred_ij;\r\n\t\t\t\tpred[j] = i;\r\n\t\t\t\tif (cred_ij == mind) {\r\n\t\t\t\t\tif (y[j] < 0) {\r\n\t\t\t\t\t\treturn j;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcols[k] = cols[hi];\r\n\t\t\t\t\tcols[hi++] = j;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t*plo = lo;\r\n\t*phi = hi;\r\n\treturn -1;\r\n}\r\n\r\n\r\n/** Single iteration of modified Dijkstra shortest path algorithm as explained in the JV paper.\r\n *\r\n * This is a dense matrix version.\r\n *\r\n * \\return The closest free column index.\r\n */\r\nint_t find_path_dense(\r\n\tconst uint_t n, cost_t *cost[],\r\n\tconst int_t start_i,\r\n\tint_t *y, cost_t *v,\r\n\tint_t *pred)\r\n{\r\n\tuint_t lo = 0, hi = 0;\r\n\tint_t final_j = -1;\r\n\tuint_t n_ready = 0;\r\n\tint_t *cols;\r\n\tcost_t *d;\r\n\r\n\tNEW(cols, int_t, n);\r\n\tNEW(d, cost_t, n);\r\n\r\n\tfor (uint_t i = 0; i < n; i++) {\r\n\t\tcols[i] = i;\r\n\t\tpred[i] = start_i;\r\n\t\td[i] = cost[start_i][i] - v[i];\r\n\t}\r\n\tPRINT_COST_ARRAY(d, n);\r\n\twhile (final_j == -1) {\r\n\t\t// No columns left on the SCAN list.\r\n\t\tif (lo == hi) {\r\n\t\t\tPRINTF(\"%d..%d -> find\\n\", lo, hi);\r\n\t\t\tn_ready = lo;\r\n\t\t\thi = _find_dense(n, lo, d, cols, y);\r\n\t\t\tPRINTF(\"check %d..%d\\n\", lo, hi);\r\n\t\t\tPRINT_INDEX_ARRAY(cols, n);\r\n\t\t\tfor (uint_t k = lo; k < hi; k++) {\r\n\t\t\t\tconst int_t j = cols[k];\r\n\t\t\t\tif (y[j] < 0) {\r\n\t\t\t\t\tfinal_j = j;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (final_j == -1) {\r\n\t\t\tPRINTF(\"%d..%d -> scan\\n\", lo, hi);\r\n\t\t\tfinal_j = _scan_dense(\r\n\t\t\t\tn, cost, &lo, &hi, d, cols, pred, y, v);\r\n\t\t\tPRINT_COST_ARRAY(d, n);\r\n\t\t\tPRINT_INDEX_ARRAY(cols, n);\r\n\t\t\tPRINT_INDEX_ARRAY(pred, n);\r\n\t\t}\r\n\t}\r\n\r\n\tPRINTF(\"found final_j=%d\\n\", final_j);\r\n\tPRINT_INDEX_ARRAY(cols, n);\r\n\t{\r\n\t\tconst cost_t mind = d[cols[lo]];\r\n\t\tfor (uint_t k = 0; k < n_ready; k++) {\r\n\t\t\tconst int_t j = cols[k];\r\n\t\t\tv[j] += d[j] - mind;\r\n\t\t}\r\n\t}\r\n\r\n\tFREE(cols);\r\n\tFREE(d);\r\n\r\n\treturn final_j;\r\n}\r\n\r\n\r\n/** Augment for a dense cost matrix.\r\n */\r\nint_t _ca_dense(\r\n\tconst uint_t n, cost_t *cost[],\r\n\tconst uint_t n_free_rows,\r\n\tint_t *free_rows, int_t *x, int_t *y, cost_t *v)\r\n{\r\n\tint_t *pred;\r\n\r\n\tNEW(pred, int_t, n);\r\n\r\n\tfor (int_t *pfree_i = free_rows; pfree_i < free_rows + n_free_rows; pfree_i++) {\r\n\t\tint_t i = -1, j;\r\n\t\tuint_t k = 0;\r\n\r\n\t\tPRINTF(\"looking at free_i=%d\\n\", *pfree_i);\r\n\t\tj = find_path_dense(n, cost, *pfree_i, y, v, pred);\r\n\t\tASSERT(j >= 0);\r\n\t\tASSERT(j < n);\r\n\t\twhile (i != *pfree_i) {\r\n\t\t\tPRINTF(\"augment %d\\n\", j);\r\n\t\t\tPRINT_INDEX_ARRAY(pred, n);\r\n\t\t\ti = pred[j];\r\n\t\t\tPRINTF(\"y[%d]=%d -> %d\\n\", j, y[j], i);\r\n\t\t\ty[j] = i;\r\n\t\t\tPRINT_INDEX_ARRAY(x, n);\r\n\t\t\tSWAP_INDICES(j, x[i]);\r\n\t\t\tk++;\r\n\t\t\tif (k >= n) {\r\n\t\t\t\tASSERT(FALSE);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tFREE(pred);\r\n\treturn 0;\r\n}\r\n\r\n\r\n/** Solve dense sparse LAP.\r\n */\r\nint lapjv_internal(\r\n\tconst uint_t n, cost_t *cost[],\r\n\tint_t *x, int_t *y)\r\n{\r\n\tint ret;\r\n\tint_t *free_rows;\r\n\tcost_t *v;\r\n\r\n\tNEW(free_rows, int_t, n);\r\n\tNEW(v, cost_t, n);\r\n\tret = _ccrrt_dense(n, cost, free_rows, x, y, v);\r\n\tint i = 0;\r\n\twhile (ret > 0 && i < 2) {\r\n\t\tret = _carr_dense(n, cost, ret, free_rows, x, y, v);\r\n\t\ti++;\r\n\t}\r\n\tif (ret > 0) {\r\n\t\tret = _ca_dense(n, cost, ret, free_rows, x, y, v);\r\n\t}\r\n\tFREE(v);\r\n\tFREE(free_rows);\r\n\treturn ret;\r\n}"
  },
  {
    "path": "onnxruntime/cpp/src/main.cpp",
    "content": "#include <iostream>\n#include <opencv2/core/core.hpp>\n#include <opencv2/imgproc.hpp>\n#include <opencv2/highgui.hpp>\n//#include <cuda_provider_factory.h>\n#include <onnxruntime_cxx_api.h>\n#include <float.h>\n#include <stdio.h>\n#include <vector>\n#include <chrono>\n#include \"BYTETracker.h\"\n\nusing namespace cv;\nusing namespace std;\nusing namespace Ort;\n\nstruct GridAndStride\n{\n    int grid0;\n    int grid1;\n    int stride;\n};\n\nstatic inline float intersection_area(const Object& a, const Object& b)\n{\n    cv::Rect_<float> inter = a.rect & b.rect;\n    return inter.area();\n}\n\nstatic void qsort_descent_inplace(std::vector<Object>& faceobjects, int left, int right)\n{\n    int i = left;\n    int j = right;\n    float p = faceobjects[(left + right) / 2].prob;\n\n    while (i <= j)\n    {\n        while (faceobjects[i].prob > p)\n            i++;\n\n        while (faceobjects[j].prob < p)\n            j--;\n\n        if (i <= j)\n        {\n            // swap\n            std::swap(faceobjects[i], faceobjects[j]);\n\n            i++;\n            j--;\n        }\n    }\n\n    #pragma omp parallel sections\n    {\n        #pragma omp section\n        {\n            if (left < j) qsort_descent_inplace(faceobjects, left, j);\n        }\n        #pragma omp section\n        {\n            if (i < right) qsort_descent_inplace(faceobjects, i, right);\n        }\n    }\n}\n\nstatic void qsort_descent_inplace(std::vector<Object>& objects)\n{\n    if (objects.empty())\n        return;\n\n    qsort_descent_inplace(objects, 0, objects.size() - 1);\n}\n\nclass yolox\n{\npublic:\n    yolox();\n    int detect(cv::Mat &img, std::vector<Object> &detectResults);\nprivate:\n    const float mean_vals[3] = {0.485, 0.456, 0.406};\n    const float norm_vals[3] = {0.229, 0.224, 0.225};\n    vector<float> input_image_;\n    const int stride_arr[3] = {8, 16, 32}; // might have stride=64 in YOLOX\n    std::vector<GridAndStride> grid_strides;\n\n    Mat static_resize(Mat& img);\n    void generate_grids_and_stride(std::vector<int>& strides);\n    void generate_yolox_proposals(const float* feat_ptr, std::vector<Object>& objects);\n    void nms_sorted_bboxes(const std::vector<Object>& faceobjects, std::vector<int>& picked);\n\n    float nms_threshold = 0.7;\n    float prob_threshold = 0.1;\n    int num_grid;\n    int num_class;\n    int INPUT_W;\n    int INPUT_H;\n    Session *session_;\n    Env env = Env(ORT_LOGGING_LEVEL_ERROR, \"yolox\");\n    SessionOptions sessionOptions = SessionOptions();\n    vector<char*> input_names;\n    vector<char*> output_names;\n};\n\nyolox::yolox()\n{\n    string model_path = \"/home/ByteTrack/byte_tracker/model/bytetrack_s.onnx\";\n    //OrtStatus* status = OrtSessionOptionsAppendExecutionProvider_CUDA(sessionOptions, 0);\n    sessionOptions.SetGraphOptimizationLevel(ORT_ENABLE_BASIC);\n    session_ = new Session(env, model_path.c_str(), sessionOptions);\n    size_t numInputNodes = session_->GetInputCount();\n    size_t numOutputNodes = session_->GetOutputCount();\n    AllocatorWithDefaultOptions allocator;\n    vector<vector<int64_t>> input_node_dims; // >=1 outputs\n    for(int i=0;i<numInputNodes;i++)\n    {\n        input_names.push_back(session_->GetInputName(i, allocator));\n        Ort::TypeInfo input_type_info = session_->GetInputTypeInfo(i);\n\t\tauto input_tensor_info = input_type_info.GetTensorTypeAndShapeInfo();\n\t\tauto input_dims = input_tensor_info.GetShape();\n\t\tinput_node_dims.push_back(input_dims);\n    }\n    vector<vector<int64_t>> output_node_dims; // >=1 outputs\n    for(int i=0;i<numOutputNodes;i++)\n    {\n        output_names.push_back(session_->GetOutputName(i, allocator));\n        Ort::TypeInfo output_type_info = session_->GetOutputTypeInfo(i);\n\t\tauto output_tensor_info = output_type_info.GetTensorTypeAndShapeInfo();\n\t\tauto output_dims = output_tensor_info.GetShape();\n\t\toutput_node_dims.push_back(output_dims);\n\t\t/*for (int j = 0; j < output_dims.size(); j++)\n\t\t{\n\t\t\tcout << output_dims[j] << \",\";\n\t\t}\n\t\tcout << endl;*/\n    }\n    this->INPUT_H = input_node_dims[0][2];\n    this->INPUT_W = input_node_dims[0][3];\n    num_grid = output_node_dims[0][1];\n    num_class = output_node_dims[0][2] - 5;\n    std::vector<int> strides(stride_arr, stride_arr + sizeof(stride_arr) / sizeof(stride_arr[0]));\n    generate_grids_and_stride(strides);\n}\n\nMat yolox::static_resize(Mat& img) {\n    float r = min(INPUT_W / (img.cols*1.0), INPUT_H / (img.rows*1.0));\n    // r = std::min(r, 1.0f);\n    int unpad_w = r * img.cols;\n    int unpad_h = r * img.rows;\n    Mat re(unpad_h, unpad_w, CV_8UC3);\n    resize(img, re, re.size());\n    Mat out(INPUT_H, INPUT_W, CV_8UC3, Scalar(114, 114, 114));\n    re.copyTo(out(Rect(0, 0, re.cols, re.rows)));\n    return out;\n}\n\nvoid yolox::generate_grids_and_stride(std::vector<int>& strides)\n{\n    for (int i = 0; i < (int)strides.size(); i++)\n    {\n        int stride = strides[i];\n        int num_grid_w = INPUT_W / stride;\n        int num_grid_h = INPUT_H / stride;\n        for (int g1 = 0; g1 < num_grid_h; g1++)\n        {\n            for (int g0 = 0; g0 < num_grid_w; g0++)\n            {\n                GridAndStride gs;\n                gs.grid0 = g0;\n                gs.grid1 = g1;\n                gs.stride = stride;\n                grid_strides.push_back(gs);\n            }\n        }\n    }\n}\n\nvoid yolox::generate_yolox_proposals(const float* feat_ptr, std::vector<Object>& objects)\n{\n    const int num_anchors = grid_strides.size();\n    for (int anchor_idx = 0; anchor_idx < num_anchors; anchor_idx++)\n    {\n        const int grid0 = grid_strides[anchor_idx].grid0;\n        const int grid1 = grid_strides[anchor_idx].grid1;\n        const int stride = grid_strides[anchor_idx].stride;\n\n        // yolox/models/yolo_head.py decode logic\n        //  outputs[..., :2] = (outputs[..., :2] + grids) * strides\n        //  outputs[..., 2:4] = torch.exp(outputs[..., 2:4]) * strides\n        float x_center = (feat_ptr[0] + grid0) * stride;\n        float y_center = (feat_ptr[1] + grid1) * stride;\n        float w = exp(feat_ptr[2]) * stride;\n        float h = exp(feat_ptr[3]) * stride;\n        float x0 = x_center - w * 0.5f;\n        float y0 = y_center - h * 0.5f;\n\n        float box_objectness = feat_ptr[4];\n        for (int class_idx = 0; class_idx < num_class; class_idx++)\n        {\n            float box_cls_score = feat_ptr[5 + class_idx];\n            float box_prob = box_objectness * box_cls_score;\n            if (box_prob > prob_threshold)\n            {\n                Object obj;\n                obj.rect.x = x0;\n                obj.rect.y = y0;\n                obj.rect.width = w;\n                obj.rect.height = h;\n                obj.label = class_idx;\n                obj.prob = box_prob;\n\n                objects.push_back(obj);\n            }\n\n        } // class loop\n        feat_ptr += (num_class + 5);\n\n    } // point anchor loop\n}\n\nvoid yolox::nms_sorted_bboxes(const std::vector<Object>& faceobjects, std::vector<int>& picked)\n{\n    picked.clear();\n\n    const int n = faceobjects.size();\n\n    std::vector<float> areas(n);\n    for (int i = 0; i < n; i++)\n    {\n        areas[i] = faceobjects[i].rect.area();\n    }\n\n    for (int i = 0; i < n; i++)\n    {\n        const Object& a = faceobjects[i];\n\n        int keep = 1;\n        for (int j = 0; j < (int)picked.size(); j++)\n        {\n            const Object& b = faceobjects[picked[j]];\n\n            // intersection over union\n            float inter_area = intersection_area(a, b);\n            float union_area = areas[i] + areas[picked[j]] - inter_area;\n            // float IoU = inter_area / union_area\n            if (inter_area / union_area > nms_threshold)\n                keep = 0;\n        }\n\n        if (keep)\n            picked.push_back(i);\n    }\n}\n\nint yolox::detect(cv::Mat &srcimg, std::vector<Object>& objects)\n{\n    float scale = min(INPUT_W / (srcimg.cols*1.0), INPUT_H / (srcimg.rows*1.0));\n    Mat img = static_resize(srcimg);\n    int row = img.rows;\n    int col = img.cols;\n    this->input_image_.resize(row * col * img.channels());\n    for (int c = 0; c < 3; c++)\n    {\n        for (int i = 0; i < row; i++)\n        {\n            for (int j = 0; j < col; j++)\n            {\n                float pix = img.ptr<uchar>(i)[j * 3 + 2 - c];\n                this->input_image_[c * row * col + i * col + j] = (pix / 255.0 - mean_vals[c]) / norm_vals[c];\n            }\n        }\n    }\n    array<int64_t, 4> input_shape_{1, 3, row, col};\n    auto allocator_info = MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);\n    Value input_tensor_ = Value::CreateTensor<float>(allocator_info, input_image_.data(), input_image_.size(), input_shape_.data(), input_shape_.size());\n    vector<Value> ort_outputs = session_->Run(RunOptions{nullptr}, &input_names[0], &input_tensor_, 1, output_names.data(), output_names.size());\n\n    const float* out = ort_outputs[0].GetTensorMutableData<float>();\n    std::vector<Object> proposals;\n    generate_yolox_proposals(out, proposals);\n    // sort all proposals by score from highest to lowest\n    qsort_descent_inplace(proposals);\n\n    // apply nms with nms_threshold\n    std::vector<int> picked;\n    nms_sorted_bboxes(proposals, picked);\n\n    int count = picked.size();\n\n    objects.resize(count);\n    for (int i = 0; i < count; i++)\n    {\n        objects[i] = proposals[picked[i]];\n\n        // adjust offset to original unpadded\n        float x0 = (objects[i].rect.x) / scale;\n        float y0 = (objects[i].rect.y) / scale;\n        float x1 = (objects[i].rect.x + objects[i].rect.width) / scale;\n        float y1 = (objects[i].rect.y + objects[i].rect.height) / scale;\n\n        // clip\n        // x0 = std::max(std::min(x0, (float)(img_w - 1)), 0.f);\n        // y0 = std::max(std::min(y0, (float)(img_h - 1)), 0.f);\n        // x1 = std::max(std::min(x1, (float)(img_w - 1)), 0.f);\n        // y1 = std::max(std::min(y1, (float)(img_h - 1)), 0.f);\n\n        objects[i].rect.x = x0;\n        objects[i].rect.y = y0;\n        objects[i].rect.width = x1 - x0;\n        objects[i].rect.height = y1 - y0;\n    }\n\n    return 0;\n}\n\nint main(int argc, char** argv)\n{\n    if (argc != 2)\n    {\n        fprintf(stderr, \"Usage: %s [videopath]\\n\", argv[0]);\n        return -1;\n    }\n\n    const char* videopath = argv[1];\n    VideoCapture cap(videopath);\n\tif (!cap.isOpened())\n\t\treturn 0;\n\n\tint img_w = cap.get(CAP_PROP_FRAME_WIDTH);\n\tint img_h = cap.get(CAP_PROP_FRAME_HEIGHT);\n    int fps = cap.get(CAP_PROP_FPS);\n    long nFrame = static_cast<long>(cap.get(CAP_PROP_FRAME_COUNT));\n    cout << \"Total frames: \" << nFrame << \", fps: \"<<fps<<endl;\n\n    VideoWriter writer(\"demo.avi\", cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), fps, Size(img_w, img_h));\n\n    Mat img;\n    yolox yolox;\n    BYTETracker tracker(fps, 30);\n    int num_frames = 0;\n    int total_ms = 1;\n\tfor (;;)\n    {\n        if(!cap.read(img))\n            break;\n        num_frames++;\n        /*if(num_frames%100 != 0)\n            continue;*/\n\n        if (num_frames % 20 == 0)\n        {\n            cout << \"Processing frame \" << num_frames << \" (\" << num_frames * 1000000 / total_ms << \" fps)\" << endl;\n        }\n\t\tif (img.empty())\n\t\t\tbreak;\n        //cout<<\"Processing frame \"<<num_frames<<endl;\n        std::vector<Object> objects;\n        auto start = chrono::system_clock::now();\n        yolox.detect(img, objects);\n        vector<STrack> output_stracks = tracker.update(objects);\n        auto end = chrono::system_clock::now();\n        total_ms = total_ms + chrono::duration_cast<chrono::microseconds>(end - start).count();\n        for (int i = 0; i < output_stracks.size(); i++)\n\t\t{\n\t\t\tvector<float> tlwh = output_stracks[i].tlwh;\n\t\t\tbool vertical = tlwh[2] / tlwh[3] > 1.6;\n\t\t\tif (tlwh[2] * tlwh[3] > 20 && !vertical)\n\t\t\t{\n\t\t\t\tScalar s = tracker.get_color(output_stracks[i].track_id);\n\t\t\t\tputText(img, format(\"%d\", output_stracks[i].track_id), Point(tlwh[0], tlwh[1] - 5), \n                        0, 0.6, Scalar(0, 0, 255), 2, LINE_AA);\n                rectangle(img, Rect(tlwh[0], tlwh[1], tlwh[2], tlwh[3]), s, 2);\n\t\t\t}\n\t\t}\n        putText(img, format(\"frame: %d fps: %d num: %d\", num_frames, num_frames * 1000000 / total_ms, (int)output_stracks.size()),\n                Point(0, 30), 0, 0.6, Scalar(0, 0, 255), 2, LINE_AA);\n        writer.write(img);\n        /*char c = waitKey(1);\n        if (c > 0)\n        {\n            break;\n        }*/\n    }\n    cap.release();\n    cout << \"FPS: \" << num_frames * 1000000 / total_ms << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "onnxruntime/cpp/src/utils.cpp",
    "content": "#include \"BYTETracker.h\"\r\n#include \"lapjv.h\"\r\n\r\nvector<STrack*> BYTETracker::joint_stracks(vector<STrack*> &tlista, vector<STrack> &tlistb)\r\n{\r\n\tmap<int, int> exists;\r\n\tvector<STrack*> res;\r\n\tfor (int i = 0; i < tlista.size(); i++)\r\n\t{\r\n\t\texists.insert(pair<int, int>(tlista[i]->track_id, 1));\r\n\t\tres.push_back(tlista[i]);\r\n\t}\r\n\tfor (int i = 0; i < tlistb.size(); i++)\r\n\t{\r\n\t\tint tid = tlistb[i].track_id;\r\n\t\tif (!exists[tid] || exists.count(tid) == 0)\r\n\t\t{\r\n\t\t\texists[tid] = 1;\r\n\t\t\tres.push_back(&tlistb[i]);\r\n\t\t}\r\n\t}\r\n\treturn res;\r\n}\r\n\r\nvector<STrack> BYTETracker::joint_stracks(vector<STrack> &tlista, vector<STrack> &tlistb)\r\n{\r\n\tmap<int, int> exists;\r\n\tvector<STrack> res;\r\n\tfor (int i = 0; i < tlista.size(); i++)\r\n\t{\r\n\t\texists.insert(pair<int, int>(tlista[i].track_id, 1));\r\n\t\tres.push_back(tlista[i]);\r\n\t}\r\n\tfor (int i = 0; i < tlistb.size(); i++)\r\n\t{\r\n\t\tint tid = tlistb[i].track_id;\r\n\t\tif (!exists[tid] || exists.count(tid) == 0)\r\n\t\t{\r\n\t\t\texists[tid] = 1;\r\n\t\t\tres.push_back(tlistb[i]);\r\n\t\t}\r\n\t}\r\n\treturn res;\r\n}\r\n\r\nvector<STrack> BYTETracker::sub_stracks(vector<STrack> &tlista, vector<STrack> &tlistb)\r\n{\r\n\tmap<int, STrack> stracks;\r\n\tfor (int i = 0; i < tlista.size(); i++)\r\n\t{\r\n\t\tstracks.insert(pair<int, STrack>(tlista[i].track_id, tlista[i]));\r\n\t}\r\n\tfor (int i = 0; i < tlistb.size(); i++)\r\n\t{\r\n\t\tint tid = tlistb[i].track_id;\r\n\t\tif (stracks.count(tid) != 0)\r\n\t\t{\r\n\t\t\tstracks.erase(tid);\r\n\t\t}\r\n\t}\r\n\r\n\tvector<STrack> res;\r\n\tstd::map<int, STrack>::iterator  it;\r\n\tfor (it = stracks.begin(); it != stracks.end(); ++it)\r\n\t{\r\n\t\tres.push_back(it->second);\r\n\t}\r\n\r\n\treturn res;\r\n}\r\n\r\nvoid BYTETracker::remove_duplicate_stracks(vector<STrack> &resa, vector<STrack> &resb, vector<STrack> &stracksa, vector<STrack> &stracksb)\r\n{\r\n\tvector<vector<float> > pdist = iou_distance(stracksa, stracksb);\r\n\tvector<pair<int, int> > pairs;\r\n\tfor (int i = 0; i < pdist.size(); i++)\r\n\t{\r\n\t\tfor (int j = 0; j < pdist[i].size(); j++)\r\n\t\t{\r\n\t\t\tif (pdist[i][j] < 0.15)\r\n\t\t\t{\r\n\t\t\t\tpairs.push_back(pair<int, int>(i, j));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tvector<int> dupa, dupb;\r\n\tfor (int i = 0; i < pairs.size(); i++)\r\n\t{\r\n\t\tint timep = stracksa[pairs[i].first].frame_id - stracksa[pairs[i].first].start_frame;\r\n\t\tint timeq = stracksb[pairs[i].second].frame_id - stracksb[pairs[i].second].start_frame;\r\n\t\tif (timep > timeq)\r\n\t\t\tdupb.push_back(pairs[i].second);\r\n\t\telse\r\n\t\t\tdupa.push_back(pairs[i].first);\r\n\t}\r\n\r\n\tfor (int i = 0; i < stracksa.size(); i++)\r\n\t{\r\n\t\tvector<int>::iterator iter = find(dupa.begin(), dupa.end(), i);\r\n\t\tif (iter == dupa.end())\r\n\t\t{\r\n\t\t\tresa.push_back(stracksa[i]);\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int i = 0; i < stracksb.size(); i++)\r\n\t{\r\n\t\tvector<int>::iterator iter = find(dupb.begin(), dupb.end(), i);\r\n\t\tif (iter == dupb.end())\r\n\t\t{\r\n\t\t\tresb.push_back(stracksb[i]);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid BYTETracker::linear_assignment(vector<vector<float> > &cost_matrix, int cost_matrix_size, int cost_matrix_size_size, float thresh,\r\n\tvector<vector<int> > &matches, vector<int> &unmatched_a, vector<int> &unmatched_b)\r\n{\r\n\tif (cost_matrix.size() == 0)\r\n\t{\r\n\t\tfor (int i = 0; i < cost_matrix_size; i++)\r\n\t\t{\r\n\t\t\tunmatched_a.push_back(i);\r\n\t\t}\r\n\t\tfor (int i = 0; i < cost_matrix_size_size; i++)\r\n\t\t{\r\n\t\t\tunmatched_b.push_back(i);\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tvector<int> rowsol; vector<int> colsol;\r\n\tfloat c = lapjv(cost_matrix, rowsol, colsol, true, thresh);\r\n\tfor (int i = 0; i < rowsol.size(); i++)\r\n\t{\r\n\t\tif (rowsol[i] >= 0)\r\n\t\t{\r\n\t\t\tvector<int> match;\r\n\t\t\tmatch.push_back(i);\r\n\t\t\tmatch.push_back(rowsol[i]);\r\n\t\t\tmatches.push_back(match);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tunmatched_a.push_back(i);\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int i = 0; i < colsol.size(); i++)\r\n\t{\r\n\t\tif (colsol[i] < 0)\r\n\t\t{\r\n\t\t\tunmatched_b.push_back(i);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvector<vector<float> > BYTETracker::ious(vector<vector<float> > &atlbrs, vector<vector<float> > &btlbrs)\r\n{\r\n\tvector<vector<float> > ious;\r\n\tif (atlbrs.size()*btlbrs.size() == 0)\r\n\t\treturn ious;\r\n\r\n\tious.resize(atlbrs.size());\r\n\tfor (int i = 0; i < ious.size(); i++)\r\n\t{\r\n\t\tious[i].resize(btlbrs.size());\r\n\t}\r\n\r\n\t//bbox_ious\r\n\tfor (int k = 0; k < btlbrs.size(); k++)\r\n\t{\r\n\t\tvector<float> ious_tmp;\r\n\t\tfloat box_area = (btlbrs[k][2] - btlbrs[k][0] + 1)*(btlbrs[k][3] - btlbrs[k][1] + 1);\r\n\t\tfor (int n = 0; n < atlbrs.size(); n++)\r\n\t\t{\r\n\t\t\tfloat iw = min(atlbrs[n][2], btlbrs[k][2]) - max(atlbrs[n][0], btlbrs[k][0]) + 1;\r\n\t\t\tif (iw > 0)\r\n\t\t\t{\r\n\t\t\t\tfloat ih = min(atlbrs[n][3], btlbrs[k][3]) - max(atlbrs[n][1], btlbrs[k][1]) + 1;\r\n\t\t\t\tif(ih > 0)\r\n\t\t\t\t{\r\n\t\t\t\t\tfloat ua = (atlbrs[n][2] - atlbrs[n][0] + 1)*(atlbrs[n][3] - atlbrs[n][1] + 1) + box_area - iw * ih;\r\n\t\t\t\t\tious[n][k] = iw * ih / ua;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tious[n][k] = 0.0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tious[n][k] = 0.0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn ious;\r\n}\r\n\r\nvector<vector<float> > BYTETracker::iou_distance(vector<STrack*> &atracks, vector<STrack> &btracks, int &dist_size, int &dist_size_size)\r\n{\r\n\tvector<vector<float> > cost_matrix;\r\n\tif (atracks.size() * btracks.size() == 0)\r\n\t{\r\n\t\tdist_size = atracks.size();\r\n\t\tdist_size_size = btracks.size();\r\n\t\treturn cost_matrix;\r\n\t}\r\n\tvector<vector<float> > atlbrs, btlbrs;\r\n\tfor (int i = 0; i < atracks.size(); i++)\r\n\t{\r\n\t\tatlbrs.push_back(atracks[i]->tlbr);\r\n\t}\r\n\tfor (int i = 0; i < btracks.size(); i++)\r\n\t{\r\n\t\tbtlbrs.push_back(btracks[i].tlbr);\r\n\t}\r\n\r\n\tdist_size = atracks.size();\r\n\tdist_size_size = btracks.size();\r\n\r\n\tvector<vector<float> > _ious = ious(atlbrs, btlbrs);\r\n\t\r\n\tfor (int i = 0; i < _ious.size();i++)\r\n\t{\r\n\t\tvector<float> _iou;\r\n\t\tfor (int j = 0; j < _ious[i].size(); j++)\r\n\t\t{\r\n\t\t\t_iou.push_back(1 - _ious[i][j]);\r\n\t\t}\r\n\t\tcost_matrix.push_back(_iou);\r\n\t}\r\n\r\n\treturn cost_matrix;\r\n}\r\n\r\nvector<vector<float> > BYTETracker::iou_distance(vector<STrack> &atracks, vector<STrack> &btracks)\r\n{\r\n\tvector<vector<float> > atlbrs, btlbrs;\r\n\tfor (int i = 0; i < atracks.size(); i++)\r\n\t{\r\n\t\tatlbrs.push_back(atracks[i].tlbr);\r\n\t}\r\n\tfor (int i = 0; i < btracks.size(); i++)\r\n\t{\r\n\t\tbtlbrs.push_back(btracks[i].tlbr);\r\n\t}\r\n\r\n\tvector<vector<float> > _ious = ious(atlbrs, btlbrs);\r\n\tvector<vector<float> > cost_matrix;\r\n\tfor (int i = 0; i < _ious.size(); i++)\r\n\t{\r\n\t\tvector<float> _iou;\r\n\t\tfor (int j = 0; j < _ious[i].size(); j++)\r\n\t\t{\r\n\t\t\t_iou.push_back(1 - _ious[i][j]);\r\n\t\t}\r\n\t\tcost_matrix.push_back(_iou);\r\n\t}\r\n\r\n\treturn cost_matrix;\r\n}\r\n\r\ndouble BYTETracker::lapjv(const vector<vector<float> > &cost, vector<int> &rowsol, vector<int> &colsol,\r\n\tbool extend_cost, float cost_limit, bool return_cost)\r\n{\r\n\tvector<vector<float> > cost_c;\r\n\tcost_c.assign(cost.begin(), cost.end());\r\n\r\n\tvector<vector<float> > cost_c_extended;\r\n\r\n\tint n_rows = cost.size();\r\n\tint n_cols = cost[0].size();\r\n\trowsol.resize(n_rows);\r\n\tcolsol.resize(n_cols);\r\n\r\n\tint n = 0;\r\n\tif (n_rows == n_cols)\r\n\t{\r\n\t\tn = n_rows;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (!extend_cost)\r\n\t\t{\r\n\t\t\tcout << \"set extend_cost=True\" << endl;\r\n\t\t\tsystem(\"pause\");\r\n\t\t\texit(0);\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tif (extend_cost || cost_limit < LONG_MAX)\r\n\t{\r\n\t\tn = n_rows + n_cols;\r\n\t\tcost_c_extended.resize(n);\r\n\t\tfor (int i = 0; i < cost_c_extended.size(); i++)\r\n\t\t\tcost_c_extended[i].resize(n);\r\n\r\n\t\tif (cost_limit < LONG_MAX)\r\n\t\t{\r\n\t\t\tfor (int i = 0; i < cost_c_extended.size(); i++)\r\n\t\t\t{\r\n\t\t\t\tfor (int j = 0; j < cost_c_extended[i].size(); j++)\r\n\t\t\t\t{\r\n\t\t\t\t\tcost_c_extended[i][j] = cost_limit / 2.0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfloat cost_max = -1;\r\n\t\t\tfor (int i = 0; i < cost_c.size(); i++)\r\n\t\t\t{\r\n\t\t\t\tfor (int j = 0; j < cost_c[i].size(); j++)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (cost_c[i][j] > cost_max)\r\n\t\t\t\t\t\tcost_max = cost_c[i][j];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tfor (int i = 0; i < cost_c_extended.size(); i++)\r\n\t\t\t{\r\n\t\t\t\tfor (int j = 0; j < cost_c_extended[i].size(); j++)\r\n\t\t\t\t{\r\n\t\t\t\t\tcost_c_extended[i][j] = cost_max + 1;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfor (int i = n_rows; i < cost_c_extended.size(); i++)\r\n\t\t{\r\n\t\t\tfor (int j = n_cols; j < cost_c_extended[i].size(); j++)\r\n\t\t\t{\r\n\t\t\t\tcost_c_extended[i][j] = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor (int i = 0; i < n_rows; i++)\r\n\t\t{\r\n\t\t\tfor (int j = 0; j < n_cols; j++)\r\n\t\t\t{\r\n\t\t\t\tcost_c_extended[i][j] = cost_c[i][j];\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tcost_c.clear();\r\n\t\tcost_c.assign(cost_c_extended.begin(), cost_c_extended.end());\r\n\t}\r\n\r\n\tdouble **cost_ptr;\r\n\tcost_ptr = new double *[sizeof(double *) * n];\r\n\tfor (int i = 0; i < n; i++)\r\n\t\tcost_ptr[i] = new double[sizeof(double) * n];\r\n\r\n\tfor (int i = 0; i < n; i++)\r\n\t{\r\n\t\tfor (int j = 0; j < n; j++)\r\n\t\t{\r\n\t\t\tcost_ptr[i][j] = cost_c[i][j];\r\n\t\t}\r\n\t}\r\n\r\n\tint* x_c = new int[sizeof(int) * n];\r\n\tint *y_c = new int[sizeof(int) * n];\r\n\r\n\tint ret = lapjv_internal(n, cost_ptr, x_c, y_c);\r\n\tif (ret != 0)\r\n\t{\r\n\t\tcout << \"Calculate Wrong!\" << endl;\r\n\t\tsystem(\"pause\");\r\n\t\texit(0);\r\n\t}\r\n\r\n\tdouble opt = 0.0;\r\n\r\n\tif (n != n_rows)\r\n\t{\r\n\t\tfor (int i = 0; i < n; i++)\r\n\t\t{\r\n\t\t\tif (x_c[i] >= n_cols)\r\n\t\t\t\tx_c[i] = -1;\r\n\t\t\tif (y_c[i] >= n_rows)\r\n\t\t\t\ty_c[i] = -1;\r\n\t\t}\r\n\t\tfor (int i = 0; i < n_rows; i++)\r\n\t\t{\r\n\t\t\trowsol[i] = x_c[i];\r\n\t\t}\r\n\t\tfor (int i = 0; i < n_cols; i++)\r\n\t\t{\r\n\t\t\tcolsol[i] = y_c[i];\r\n\t\t}\r\n\r\n\t\tif (return_cost)\r\n\t\t{\r\n\t\t\tfor (int i = 0; i < rowsol.size(); i++)\r\n\t\t\t{\r\n\t\t\t\tif (rowsol[i] != -1)\r\n\t\t\t\t{\r\n\t\t\t\t\t//cout << i << \"\\t\" << rowsol[i] << \"\\t\" << cost_ptr[i][rowsol[i]] << endl;\r\n\t\t\t\t\topt += cost_ptr[i][rowsol[i]];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if (return_cost)\r\n\t{\r\n\t\tfor (int i = 0; i < rowsol.size(); i++)\r\n\t\t{\r\n\t\t\topt += cost_ptr[i][rowsol[i]];\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int i = 0; i < n; i++)\r\n\t{\r\n\t\tdelete[]cost_ptr[i];\r\n\t}\r\n\tdelete[]cost_ptr;\r\n\tdelete[]x_c;\r\n\tdelete[]y_c;\r\n\r\n\treturn opt;\r\n}\r\n\r\nScalar BYTETracker::get_color(int idx)\r\n{\r\n\tidx += 3;\r\n\treturn Scalar(37 * idx % 255, 17 * idx % 255, 29 * idx % 255);\r\n}"
  },
  {
    "path": "onnxruntime/python/byte_tracker/byte_tracker_onnx.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nimport copy\n\nimport numpy as np\nimport onnxruntime\n\nfrom byte_tracker.utils.yolox_utils import (\n    pre_process,\n    post_process,\n    multiclass_nms,\n)\nfrom byte_tracker.tracker.byte_tracker import BYTETracker\n\n\nclass ByteTrackerONNX(object):\n    def __init__(self, args):\n        self.args = args\n\n        self.rgb_means = (0.485, 0.456, 0.406)\n        self.std = (0.229, 0.224, 0.225)\n\n        self.session = onnxruntime.InferenceSession(args.model)\n        self.input_shape = tuple(map(int, args.input_shape.split(',')))\n\n        self.tracker = BYTETracker(args, frame_rate=30)\n\n    def _pre_process(self, image):\n        image_info = {'id': 0}\n\n        image_info['image'] = copy.deepcopy(image)\n        image_info['width'] = image.shape[1]\n        image_info['height'] = image.shape[0]\n\n        preprocessed_image, ratio = pre_process(\n            image,\n            self.input_shape,\n            self.rgb_means,\n            self.std,\n        )\n        image_info['ratio'] = ratio\n\n        return preprocessed_image, image_info\n\n    def inference(self, image):\n        image, image_info = self._pre_process(image)\n\n        input_name = self.session.get_inputs()[0].name\n        result = self.session.run(None, {input_name: image[None, :, :, :]})\n\n        dets = self._post_process(result, image_info)\n\n        bboxes, ids, scores = self._tracker_update(\n            dets,\n            image_info,\n        )\n\n        return image_info, bboxes, ids, scores\n\n    def _post_process(self, result, image_info):\n        predictions = post_process(\n            result[0],\n            self.input_shape,\n            p6=self.args.with_p6,\n        )\n        predictions = predictions[0]\n        boxes = predictions[:, :4]\n        scores = predictions[:, 4:5] * predictions[:, 5:]\n\n        boxes_xyxy = np.ones_like(boxes)\n        boxes_xyxy[:, 0] = boxes[:, 0] - boxes[:, 2] / 2.\n        boxes_xyxy[:, 1] = boxes[:, 1] - boxes[:, 3] / 2.\n        boxes_xyxy[:, 2] = boxes[:, 0] + boxes[:, 2] / 2.\n        boxes_xyxy[:, 3] = boxes[:, 1] + boxes[:, 3] / 2.\n        boxes_xyxy /= image_info['ratio']\n\n        dets = multiclass_nms(\n            boxes_xyxy,\n            scores,\n            nms_thr=self.args.nms_th,\n            score_thr=self.args.score_th,\n        )\n\n        return dets\n\n    def _tracker_update(self, dets, image_info):\n        online_targets = []\n        if dets is not None:\n            online_targets = self.tracker.update(\n                dets[:, :-1],\n                [image_info['height'], image_info['width']],\n                [image_info['height'], image_info['width']],\n            )\n\n        online_tlwhs = []\n        online_ids = []\n        online_scores = []\n        for online_target in online_targets:\n            tlwh = online_target.tlwh\n            track_id = online_target.track_id\n            vertical = tlwh[2] / tlwh[3] > 1.6\n            if tlwh[2] * tlwh[3] > self.args.min_box_area and not vertical:\n                online_tlwhs.append(tlwh)\n                online_ids.append(track_id)\n                online_scores.append(online_target.score)\n\n        return online_tlwhs, online_ids, online_scores\n"
  },
  {
    "path": "onnxruntime/python/byte_tracker/tracker/basetrack.py",
    "content": "import numpy as np\nfrom collections import OrderedDict\n\n\nclass TrackState(object):\n    New = 0\n    Tracked = 1\n    Lost = 2\n    Removed = 3\n\n\nclass BaseTrack(object):\n    _count = 0\n\n    track_id = 0\n    is_activated = False\n    state = TrackState.New\n\n    history = OrderedDict()\n    features = []\n    curr_feature = None\n    score = 0\n    start_frame = 0\n    frame_id = 0\n    time_since_update = 0\n\n    # multi-camera\n    location = (np.inf, np.inf)\n\n    @property\n    def end_frame(self):\n        return self.frame_id\n\n    @staticmethod\n    def next_id():\n        BaseTrack._count += 1\n        return BaseTrack._count\n\n    def activate(self, *args):\n        raise NotImplementedError\n\n    def predict(self):\n        raise NotImplementedError\n\n    def update(self, *args, **kwargs):\n        raise NotImplementedError\n\n    def mark_lost(self):\n        self.state = TrackState.Lost\n\n    def mark_removed(self):\n        self.state = TrackState.Removed"
  },
  {
    "path": "onnxruntime/python/byte_tracker/tracker/byte_tracker.py",
    "content": "import numpy as np\nfrom collections import deque\nimport os\nimport os.path as osp\nimport copy\nimport torch\nimport torch.nn.functional as F\n\nfrom .kalman_filter import KalmanFilter\nfrom byte_tracker.tracker import matching\nfrom .basetrack import BaseTrack, TrackState\n\nclass STrack(BaseTrack):\n    shared_kalman = KalmanFilter()\n    def __init__(self, tlwh, score):\n\n        # wait activate\n        self._tlwh = np.asarray(tlwh, dtype=np.float)\n        self.kalman_filter = None\n        self.mean, self.covariance = None, None\n        self.is_activated = False\n\n        self.score = score\n        self.tracklet_len = 0\n\n    def predict(self):\n        mean_state = self.mean.copy()\n        if self.state != TrackState.Tracked:\n            mean_state[7] = 0\n        self.mean, self.covariance = self.kalman_filter.predict(mean_state, self.covariance)\n\n    @staticmethod\n    def multi_predict(stracks):\n        if len(stracks) > 0:\n            multi_mean = np.asarray([st.mean.copy() for st in stracks])\n            multi_covariance = np.asarray([st.covariance for st in stracks])\n            for i, st in enumerate(stracks):\n                if st.state != TrackState.Tracked:\n                    multi_mean[i][7] = 0\n            multi_mean, multi_covariance = STrack.shared_kalman.multi_predict(multi_mean, multi_covariance)\n            for i, (mean, cov) in enumerate(zip(multi_mean, multi_covariance)):\n                stracks[i].mean = mean\n                stracks[i].covariance = cov\n\n    def activate(self, kalman_filter, frame_id):\n        \"\"\"Start a new tracklet\"\"\"\n        self.kalman_filter = kalman_filter\n        self.track_id = self.next_id()\n        self.mean, self.covariance = self.kalman_filter.initiate(self.tlwh_to_xyah(self._tlwh))\n\n        self.tracklet_len = 0\n        self.state = TrackState.Tracked\n        if frame_id == 1:\n            self.is_activated = True\n        # self.is_activated = True\n        self.frame_id = frame_id\n        self.start_frame = frame_id\n\n    def re_activate(self, new_track, frame_id, new_id=False):\n        self.mean, self.covariance = self.kalman_filter.update(\n            self.mean, self.covariance, self.tlwh_to_xyah(new_track.tlwh)\n        )\n        self.tracklet_len = 0\n        self.state = TrackState.Tracked\n        self.is_activated = True\n        self.frame_id = frame_id\n        if new_id:\n            self.track_id = self.next_id()\n        self.score = new_track.score\n\n    def update(self, new_track, frame_id):\n        \"\"\"\n        Update a matched track\n        :type new_track: STrack\n        :type frame_id: int\n        :type update_feature: bool\n        :return:\n        \"\"\"\n        self.frame_id = frame_id\n        self.tracklet_len += 1\n\n        new_tlwh = new_track.tlwh\n        self.mean, self.covariance = self.kalman_filter.update(\n            self.mean, self.covariance, self.tlwh_to_xyah(new_tlwh))\n        self.state = TrackState.Tracked\n        self.is_activated = True\n\n        self.score = new_track.score\n\n    @property\n    # @jit(nopython=True)\n    def tlwh(self):\n        \"\"\"Get current position in bounding box format `(top left x, top left y,\n                width, height)`.\n        \"\"\"\n        if self.mean is None:\n            return self._tlwh.copy()\n        ret = self.mean[:4].copy()\n        ret[2] *= ret[3]\n        ret[:2] -= ret[2:] / 2\n        return ret\n\n    @property\n    # @jit(nopython=True)\n    def tlbr(self):\n        \"\"\"Convert bounding box to format `(min x, min y, max x, max y)`, i.e.,\n        `(top left, bottom right)`.\n        \"\"\"\n        ret = self.tlwh.copy()\n        ret[2:] += ret[:2]\n        return ret\n\n    @staticmethod\n    # @jit(nopython=True)\n    def tlwh_to_xyah(tlwh):\n        \"\"\"Convert bounding box to format `(center x, center y, aspect ratio,\n        height)`, where the aspect ratio is `width / height`.\n        \"\"\"\n        ret = np.asarray(tlwh).copy()\n        ret[:2] += ret[2:] / 2\n        ret[2] /= ret[3]\n        return ret\n\n    def to_xyah(self):\n        return self.tlwh_to_xyah(self.tlwh)\n\n    @staticmethod\n    # @jit(nopython=True)\n    def tlbr_to_tlwh(tlbr):\n        ret = np.asarray(tlbr).copy()\n        ret[2:] -= ret[:2]\n        return ret\n\n    @staticmethod\n    # @jit(nopython=True)\n    def tlwh_to_tlbr(tlwh):\n        ret = np.asarray(tlwh).copy()\n        ret[2:] += ret[:2]\n        return ret\n\n    def __repr__(self):\n        return 'OT_{}_({}-{})'.format(self.track_id, self.start_frame, self.end_frame)\n\n\nclass BYTETracker(object):\n    def __init__(self, args, frame_rate=30):\n        self.tracked_stracks = []  # type: list[STrack]\n        self.lost_stracks = []  # type: list[STrack]\n        self.removed_stracks = []  # type: list[STrack]\n\n        self.frame_id = 0\n        self.args = args\n        #self.det_thresh = args.track_thresh\n        self.det_thresh = args.track_thresh + 0.1\n        self.buffer_size = int(frame_rate / 30.0 * args.track_buffer)\n        self.max_time_lost = self.buffer_size\n        self.kalman_filter = KalmanFilter()\n\n    def update(self, output_results, img_info, img_size):\n        self.frame_id += 1\n        activated_starcks = []\n        refind_stracks = []\n        lost_stracks = []\n        removed_stracks = []\n\n        if output_results.shape[1] == 5:\n            scores = output_results[:, 4]\n            bboxes = output_results[:, :4]\n        else:\n            output_results = output_results.cpu().numpy()\n            scores = output_results[:, 4] * output_results[:, 5]\n            bboxes = output_results[:, :4]  # x1y1x2y2\n        img_h, img_w = img_info[0], img_info[1]\n        scale = min(img_size[0] / float(img_h), img_size[1] / float(img_w))\n        bboxes /= scale\n\n        remain_inds = scores > self.args.track_thresh\n        inds_low = scores > 0.1\n        inds_high = scores < self.args.track_thresh\n\n        inds_second = np.logical_and(inds_low, inds_high)\n        dets_second = bboxes[inds_second]\n        dets = bboxes[remain_inds]\n        scores_keep = scores[remain_inds]\n        scores_second = scores[inds_second]\n\n        if len(dets) > 0:\n            '''Detections'''\n            detections = [STrack(STrack.tlbr_to_tlwh(tlbr), s) for\n                          (tlbr, s) in zip(dets, scores_keep)]\n        else:\n            detections = []\n\n        ''' Add newly detected tracklets to tracked_stracks'''\n        unconfirmed = []\n        tracked_stracks = []  # type: list[STrack]\n        for track in self.tracked_stracks:\n            if not track.is_activated:\n                unconfirmed.append(track)\n            else:\n                tracked_stracks.append(track)\n\n        ''' Step 2: First association, with high score detection boxes'''\n        strack_pool = joint_stracks(tracked_stracks, self.lost_stracks)\n        # Predict the current location with KF\n        STrack.multi_predict(strack_pool)\n        dists = matching.iou_distance(strack_pool, detections)\n        if not self.args.mot20:\n            dists = matching.fuse_score(dists, detections)\n        matches, u_track, u_detection = matching.linear_assignment(dists, thresh=self.args.match_thresh)\n\n        for itracked, idet in matches:\n            track = strack_pool[itracked]\n            det = detections[idet]\n            if track.state == TrackState.Tracked:\n                track.update(detections[idet], self.frame_id)\n                activated_starcks.append(track)\n            else:\n                track.re_activate(det, self.frame_id, new_id=False)\n                refind_stracks.append(track)\n\n        ''' Step 3: Second association, with low score detection boxes'''\n        # association the untrack to the low score detections\n        if len(dets_second) > 0:\n            '''Detections'''\n            detections_second = [STrack(STrack.tlbr_to_tlwh(tlbr), s) for\n                          (tlbr, s) in zip(dets_second, scores_second)]\n        else:\n            detections_second = []\n        r_tracked_stracks = [strack_pool[i] for i in u_track if strack_pool[i].state == TrackState.Tracked]\n        dists = matching.iou_distance(r_tracked_stracks, detections_second)\n        matches, u_track, u_detection_second = matching.linear_assignment(dists, thresh=0.5)\n        for itracked, idet in matches:\n            track = r_tracked_stracks[itracked]\n            det = detections_second[idet]\n            if track.state == TrackState.Tracked:\n                track.update(det, self.frame_id)\n                activated_starcks.append(track)\n            else:\n                track.re_activate(det, self.frame_id, new_id=False)\n                refind_stracks.append(track)\n\n        for it in u_track:\n            track = r_tracked_stracks[it]\n            if not track.state == TrackState.Lost:\n                track.mark_lost()\n                lost_stracks.append(track)\n\n        '''Deal with unconfirmed tracks, usually tracks with only one beginning frame'''\n        detections = [detections[i] for i in u_detection]\n        dists = matching.iou_distance(unconfirmed, detections)\n        if not self.args.mot20:\n            dists = matching.fuse_score(dists, detections)\n        matches, u_unconfirmed, u_detection = matching.linear_assignment(dists, thresh=0.7)\n        for itracked, idet in matches:\n            unconfirmed[itracked].update(detections[idet], self.frame_id)\n            activated_starcks.append(unconfirmed[itracked])\n        for it in u_unconfirmed:\n            track = unconfirmed[it]\n            track.mark_removed()\n            removed_stracks.append(track)\n\n        \"\"\" Step 4: Init new stracks\"\"\"\n        for inew in u_detection:\n            track = detections[inew]\n            if track.score < self.det_thresh:\n                continue\n            track.activate(self.kalman_filter, self.frame_id)\n            activated_starcks.append(track)\n        \"\"\" Step 5: Update state\"\"\"\n        for track in self.lost_stracks:\n            if self.frame_id - track.end_frame > self.max_time_lost:\n                track.mark_removed()\n                removed_stracks.append(track)\n\n        # print('Ramained match {} s'.format(t4-t3))\n\n        self.tracked_stracks = [t for t in self.tracked_stracks if t.state == TrackState.Tracked]\n        self.tracked_stracks = joint_stracks(self.tracked_stracks, activated_starcks)\n        self.tracked_stracks = joint_stracks(self.tracked_stracks, refind_stracks)\n        self.lost_stracks = sub_stracks(self.lost_stracks, self.tracked_stracks)\n        self.lost_stracks.extend(lost_stracks)\n        self.lost_stracks = sub_stracks(self.lost_stracks, self.removed_stracks)\n        self.removed_stracks.extend(removed_stracks)\n        self.tracked_stracks, self.lost_stracks = remove_duplicate_stracks(self.tracked_stracks, self.lost_stracks)\n        # get scores of lost tracks\n        output_stracks = [track for track in self.tracked_stracks if track.is_activated]\n\n        return output_stracks\n\n\ndef joint_stracks(tlista, tlistb):\n    exists = {}\n    res = []\n    for t in tlista:\n        exists[t.track_id] = 1\n        res.append(t)\n    for t in tlistb:\n        tid = t.track_id\n        if not exists.get(tid, 0):\n            exists[tid] = 1\n            res.append(t)\n    return res\n\n\ndef sub_stracks(tlista, tlistb):\n    stracks = {}\n    for t in tlista:\n        stracks[t.track_id] = t\n    for t in tlistb:\n        tid = t.track_id\n        if stracks.get(tid, 0):\n            del stracks[tid]\n    return list(stracks.values())\n\n\ndef remove_duplicate_stracks(stracksa, stracksb):\n    pdist = matching.iou_distance(stracksa, stracksb)\n    pairs = np.where(pdist < 0.15)\n    dupa, dupb = list(), list()\n    for p, q in zip(*pairs):\n        timep = stracksa[p].frame_id - stracksa[p].start_frame\n        timeq = stracksb[q].frame_id - stracksb[q].start_frame\n        if timep > timeq:\n            dupb.append(q)\n        else:\n            dupa.append(p)\n    resa = [t for i, t in enumerate(stracksa) if not i in dupa]\n    resb = [t for i, t in enumerate(stracksb) if not i in dupb]\n    return resa, resb\n"
  },
  {
    "path": "onnxruntime/python/byte_tracker/tracker/kalman_filter.py",
    "content": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport scipy.linalg\n\n\n\"\"\"\nTable for the 0.95 quantile of the chi-square distribution with N degrees of\nfreedom (contains values for N=1, ..., 9). Taken from MATLAB/Octave's chi2inv\nfunction and used as Mahalanobis gating threshold.\n\"\"\"\nchi2inv95 = {\n    1: 3.8415,\n    2: 5.9915,\n    3: 7.8147,\n    4: 9.4877,\n    5: 11.070,\n    6: 12.592,\n    7: 14.067,\n    8: 15.507,\n    9: 16.919}\n\n\nclass KalmanFilter(object):\n    \"\"\"\n    A simple Kalman filter for tracking bounding boxes in image space.\n\n    The 8-dimensional state space\n\n        x, y, a, h, vx, vy, va, vh\n\n    contains the bounding box center position (x, y), aspect ratio a, height h,\n    and their respective velocities.\n\n    Object motion follows a constant velocity model. The bounding box location\n    (x, y, a, h) is taken as direct observation of the state space (linear\n    observation model).\n\n    \"\"\"\n\n    def __init__(self):\n        ndim, dt = 4, 1.\n\n        # Create Kalman filter model matrices.\n        self._motion_mat = np.eye(2 * ndim, 2 * ndim)\n        for i in range(ndim):\n            self._motion_mat[i, ndim + i] = dt\n        self._update_mat = np.eye(ndim, 2 * ndim)\n\n        # Motion and observation uncertainty are chosen relative to the current\n        # state estimate. These weights control the amount of uncertainty in\n        # the model. This is a bit hacky.\n        self._std_weight_position = 1. / 20\n        self._std_weight_velocity = 1. / 160\n\n    def initiate(self, measurement):\n        \"\"\"Create track from unassociated measurement.\n\n        Parameters\n        ----------\n        measurement : ndarray\n            Bounding box coordinates (x, y, a, h) with center position (x, y),\n            aspect ratio a, and height h.\n\n        Returns\n        -------\n        (ndarray, ndarray)\n            Returns the mean vector (8 dimensional) and covariance matrix (8x8\n            dimensional) of the new track. Unobserved velocities are initialized\n            to 0 mean.\n\n        \"\"\"\n        mean_pos = measurement\n        mean_vel = np.zeros_like(mean_pos)\n        mean = np.r_[mean_pos, mean_vel]\n\n        std = [\n            2 * self._std_weight_position * measurement[3],\n            2 * self._std_weight_position * measurement[3],\n            1e-2,\n            2 * self._std_weight_position * measurement[3],\n            10 * self._std_weight_velocity * measurement[3],\n            10 * self._std_weight_velocity * measurement[3],\n            1e-5,\n            10 * self._std_weight_velocity * measurement[3]]\n        covariance = np.diag(np.square(std))\n        return mean, covariance\n\n    def predict(self, mean, covariance):\n        \"\"\"Run Kalman filter prediction step.\n\n        Parameters\n        ----------\n        mean : ndarray\n            The 8 dimensional mean vector of the object state at the previous\n            time step.\n        covariance : ndarray\n            The 8x8 dimensional covariance matrix of the object state at the\n            previous time step.\n\n        Returns\n        -------\n        (ndarray, ndarray)\n            Returns the mean vector and covariance matrix of the predicted\n            state. Unobserved velocities are initialized to 0 mean.\n\n        \"\"\"\n        std_pos = [\n            self._std_weight_position * mean[3],\n            self._std_weight_position * mean[3],\n            1e-2,\n            self._std_weight_position * mean[3]]\n        std_vel = [\n            self._std_weight_velocity * mean[3],\n            self._std_weight_velocity * mean[3],\n            1e-5,\n            self._std_weight_velocity * mean[3]]\n        motion_cov = np.diag(np.square(np.r_[std_pos, std_vel]))\n\n        #mean = np.dot(self._motion_mat, mean)\n        mean = np.dot(mean, self._motion_mat.T)\n        covariance = np.linalg.multi_dot((\n            self._motion_mat, covariance, self._motion_mat.T)) + motion_cov\n\n        return mean, covariance\n\n    def project(self, mean, covariance):\n        \"\"\"Project state distribution to measurement space.\n\n        Parameters\n        ----------\n        mean : ndarray\n            The state's mean vector (8 dimensional array).\n        covariance : ndarray\n            The state's covariance matrix (8x8 dimensional).\n\n        Returns\n        -------\n        (ndarray, ndarray)\n            Returns the projected mean and covariance matrix of the given state\n            estimate.\n\n        \"\"\"\n        std = [\n            self._std_weight_position * mean[3],\n            self._std_weight_position * mean[3],\n            1e-1,\n            self._std_weight_position * mean[3]]\n        innovation_cov = np.diag(np.square(std))\n\n        mean = np.dot(self._update_mat, mean)\n        covariance = np.linalg.multi_dot((\n            self._update_mat, covariance, self._update_mat.T))\n        return mean, covariance + innovation_cov\n\n    def multi_predict(self, mean, covariance):\n        \"\"\"Run Kalman filter prediction step (Vectorized version).\n        Parameters\n        ----------\n        mean : ndarray\n            The Nx8 dimensional mean matrix of the object states at the previous\n            time step.\n        covariance : ndarray\n            The Nx8x8 dimensional covariance matrics of the object states at the\n            previous time step.\n        Returns\n        -------\n        (ndarray, ndarray)\n            Returns the mean vector and covariance matrix of the predicted\n            state. Unobserved velocities are initialized to 0 mean.\n        \"\"\"\n        std_pos = [\n            self._std_weight_position * mean[:, 3],\n            self._std_weight_position * mean[:, 3],\n            1e-2 * np.ones_like(mean[:, 3]),\n            self._std_weight_position * mean[:, 3]]\n        std_vel = [\n            self._std_weight_velocity * mean[:, 3],\n            self._std_weight_velocity * mean[:, 3],\n            1e-5 * np.ones_like(mean[:, 3]),\n            self._std_weight_velocity * mean[:, 3]]\n        sqr = np.square(np.r_[std_pos, std_vel]).T\n\n        motion_cov = []\n        for i in range(len(mean)):\n            motion_cov.append(np.diag(sqr[i]))\n        motion_cov = np.asarray(motion_cov)\n\n        mean = np.dot(mean, self._motion_mat.T)\n        left = np.dot(self._motion_mat, covariance).transpose((1, 0, 2))\n        covariance = np.dot(left, self._motion_mat.T) + motion_cov\n\n        return mean, covariance\n\n    def update(self, mean, covariance, measurement):\n        \"\"\"Run Kalman filter correction step.\n\n        Parameters\n        ----------\n        mean : ndarray\n            The predicted state's mean vector (8 dimensional).\n        covariance : ndarray\n            The state's covariance matrix (8x8 dimensional).\n        measurement : ndarray\n            The 4 dimensional measurement vector (x, y, a, h), where (x, y)\n            is the center position, a the aspect ratio, and h the height of the\n            bounding box.\n\n        Returns\n        -------\n        (ndarray, ndarray)\n            Returns the measurement-corrected state distribution.\n\n        \"\"\"\n        projected_mean, projected_cov = self.project(mean, covariance)\n\n        chol_factor, lower = scipy.linalg.cho_factor(\n            projected_cov, lower=True, check_finite=False)\n        kalman_gain = scipy.linalg.cho_solve(\n            (chol_factor, lower), np.dot(covariance, self._update_mat.T).T,\n            check_finite=False).T\n        innovation = measurement - projected_mean\n\n        new_mean = mean + np.dot(innovation, kalman_gain.T)\n        new_covariance = covariance - np.linalg.multi_dot((\n            kalman_gain, projected_cov, kalman_gain.T))\n        return new_mean, new_covariance\n\n    def gating_distance(self, mean, covariance, measurements,\n                        only_position=False, metric='maha'):\n        \"\"\"Compute gating distance between state distribution and measurements.\n        A suitable distance threshold can be obtained from `chi2inv95`. If\n        `only_position` is False, the chi-square distribution has 4 degrees of\n        freedom, otherwise 2.\n        Parameters\n        ----------\n        mean : ndarray\n            Mean vector over the state distribution (8 dimensional).\n        covariance : ndarray\n            Covariance of the state distribution (8x8 dimensional).\n        measurements : ndarray\n            An Nx4 dimensional matrix of N measurements, each in\n            format (x, y, a, h) where (x, y) is the bounding box center\n            position, a the aspect ratio, and h the height.\n        only_position : Optional[bool]\n            If True, distance computation is done with respect to the bounding\n            box center position only.\n        Returns\n        -------\n        ndarray\n            Returns an array of length N, where the i-th element contains the\n            squared Mahalanobis distance between (mean, covariance) and\n            `measurements[i]`.\n        \"\"\"\n        mean, covariance = self.project(mean, covariance)\n        if only_position:\n            mean, covariance = mean[:2], covariance[:2, :2]\n            measurements = measurements[:, :2]\n\n        d = measurements - mean\n        if metric == 'gaussian':\n            return np.sum(d * d, axis=1)\n        elif metric == 'maha':\n            cholesky_factor = np.linalg.cholesky(covariance)\n            z = scipy.linalg.solve_triangular(\n                cholesky_factor, d.T, lower=True, check_finite=False,\n                overwrite_b=True)\n            squared_maha = np.sum(z * z, axis=0)\n            return squared_maha\n        else:\n            raise ValueError('invalid distance metric')"
  },
  {
    "path": "onnxruntime/python/byte_tracker/tracker/matching.py",
    "content": "import cv2\nimport numpy as np\nimport scipy\nimport lap\nfrom scipy.spatial.distance import cdist\n\nfrom cython_bbox import bbox_overlaps as bbox_ious\nfrom byte_tracker.tracker import kalman_filter\nimport time\n\ndef merge_matches(m1, m2, shape):\n    O,P,Q = shape\n    m1 = np.asarray(m1)\n    m2 = np.asarray(m2)\n\n    M1 = scipy.sparse.coo_matrix((np.ones(len(m1)), (m1[:, 0], m1[:, 1])), shape=(O, P))\n    M2 = scipy.sparse.coo_matrix((np.ones(len(m2)), (m2[:, 0], m2[:, 1])), shape=(P, Q))\n\n    mask = M1*M2\n    match = mask.nonzero()\n    match = list(zip(match[0], match[1]))\n    unmatched_O = tuple(set(range(O)) - set([i for i, j in match]))\n    unmatched_Q = tuple(set(range(Q)) - set([j for i, j in match]))\n\n    return match, unmatched_O, unmatched_Q\n\n\ndef _indices_to_matches(cost_matrix, indices, thresh):\n    matched_cost = cost_matrix[tuple(zip(*indices))]\n    matched_mask = (matched_cost <= thresh)\n\n    matches = indices[matched_mask]\n    unmatched_a = tuple(set(range(cost_matrix.shape[0])) - set(matches[:, 0]))\n    unmatched_b = tuple(set(range(cost_matrix.shape[1])) - set(matches[:, 1]))\n\n    return matches, unmatched_a, unmatched_b\n\n\ndef linear_assignment(cost_matrix, thresh):\n    if cost_matrix.size == 0:\n        return np.empty((0, 2), dtype=int), tuple(range(cost_matrix.shape[0])), tuple(range(cost_matrix.shape[1]))\n    matches, unmatched_a, unmatched_b = [], [], []\n    cost, x, y = lap.lapjv(cost_matrix, extend_cost=True, cost_limit=thresh)\n    for ix, mx in enumerate(x):\n        if mx >= 0:\n            matches.append([ix, mx])\n    unmatched_a = np.where(x < 0)[0]\n    unmatched_b = np.where(y < 0)[0]\n    matches = np.asarray(matches)\n    return matches, unmatched_a, unmatched_b\n\n\ndef ious(atlbrs, btlbrs):\n    \"\"\"\n    Compute cost based on IoU\n    :type atlbrs: list[tlbr] | np.ndarray\n    :type atlbrs: list[tlbr] | np.ndarray\n\n    :rtype ious np.ndarray\n    \"\"\"\n    ious = np.zeros((len(atlbrs), len(btlbrs)), dtype=np.float)\n    if ious.size == 0:\n        return ious\n\n    ious = bbox_ious(\n        np.ascontiguousarray(atlbrs, dtype=np.float),\n        np.ascontiguousarray(btlbrs, dtype=np.float)\n    )\n\n    return ious\n\n\ndef iou_distance(atracks, btracks):\n    \"\"\"\n    Compute cost based on IoU\n    :type atracks: list[STrack]\n    :type btracks: list[STrack]\n\n    :rtype cost_matrix np.ndarray\n    \"\"\"\n\n    if (len(atracks)>0 and isinstance(atracks[0], np.ndarray)) or (len(btracks) > 0 and isinstance(btracks[0], np.ndarray)):\n        atlbrs = atracks\n        btlbrs = btracks\n    else:\n        atlbrs = [track.tlbr for track in atracks]\n        btlbrs = [track.tlbr for track in btracks]\n    _ious = ious(atlbrs, btlbrs)\n    cost_matrix = 1 - _ious\n\n    return cost_matrix\n\ndef v_iou_distance(atracks, btracks):\n    \"\"\"\n    Compute cost based on IoU\n    :type atracks: list[STrack]\n    :type btracks: list[STrack]\n\n    :rtype cost_matrix np.ndarray\n    \"\"\"\n\n    if (len(atracks)>0 and isinstance(atracks[0], np.ndarray)) or (len(btracks) > 0 and isinstance(btracks[0], np.ndarray)):\n        atlbrs = atracks\n        btlbrs = btracks\n    else:\n        atlbrs = [track.tlwh_to_tlbr(track.pred_bbox) for track in atracks]\n        btlbrs = [track.tlwh_to_tlbr(track.pred_bbox) for track in btracks]\n    _ious = ious(atlbrs, btlbrs)\n    cost_matrix = 1 - _ious\n\n    return cost_matrix\n\ndef embedding_distance(tracks, detections, metric='cosine'):\n    \"\"\"\n    :param tracks: list[STrack]\n    :param detections: list[BaseTrack]\n    :param metric:\n    :return: cost_matrix np.ndarray\n    \"\"\"\n\n    cost_matrix = np.zeros((len(tracks), len(detections)), dtype=np.float)\n    if cost_matrix.size == 0:\n        return cost_matrix\n    det_features = np.asarray([track.curr_feat for track in detections], dtype=np.float)\n    #for i, track in enumerate(tracks):\n        #cost_matrix[i, :] = np.maximum(0.0, cdist(track.smooth_feat.reshape(1,-1), det_features, metric))\n    track_features = np.asarray([track.smooth_feat for track in tracks], dtype=np.float)\n    cost_matrix = np.maximum(0.0, cdist(track_features, det_features, metric))  # Nomalized features\n    return cost_matrix\n\n\ndef gate_cost_matrix(kf, cost_matrix, tracks, detections, only_position=False):\n    if cost_matrix.size == 0:\n        return cost_matrix\n    gating_dim = 2 if only_position else 4\n    gating_threshold = kalman_filter.chi2inv95[gating_dim]\n    measurements = np.asarray([det.to_xyah() for det in detections])\n    for row, track in enumerate(tracks):\n        gating_distance = kf.gating_distance(\n            track.mean, track.covariance, measurements, only_position)\n        cost_matrix[row, gating_distance > gating_threshold] = np.inf\n    return cost_matrix\n\n\ndef fuse_motion(kf, cost_matrix, tracks, detections, only_position=False, lambda_=0.98):\n    if cost_matrix.size == 0:\n        return cost_matrix\n    gating_dim = 2 if only_position else 4\n    gating_threshold = kalman_filter.chi2inv95[gating_dim]\n    measurements = np.asarray([det.to_xyah() for det in detections])\n    for row, track in enumerate(tracks):\n        gating_distance = kf.gating_distance(\n            track.mean, track.covariance, measurements, only_position, metric='maha')\n        cost_matrix[row, gating_distance > gating_threshold] = np.inf\n        cost_matrix[row] = lambda_ * cost_matrix[row] + (1 - lambda_) * gating_distance\n    return cost_matrix\n\n\ndef fuse_iou(cost_matrix, tracks, detections):\n    if cost_matrix.size == 0:\n        return cost_matrix\n    reid_sim = 1 - cost_matrix\n    iou_dist = iou_distance(tracks, detections)\n    iou_sim = 1 - iou_dist\n    fuse_sim = reid_sim * (1 + iou_sim) / 2\n    det_scores = np.array([det.score for det in detections])\n    det_scores = np.expand_dims(det_scores, axis=0).repeat(cost_matrix.shape[0], axis=0)\n    #fuse_sim = fuse_sim * (1 + det_scores) / 2\n    fuse_cost = 1 - fuse_sim\n    return fuse_cost\n\n\ndef fuse_score(cost_matrix, detections):\n    if cost_matrix.size == 0:\n        return cost_matrix\n    iou_sim = 1 - cost_matrix\n    det_scores = np.array([det.score for det in detections])\n    det_scores = np.expand_dims(det_scores, axis=0).repeat(cost_matrix.shape[0], axis=0)\n    fuse_sim = iou_sim * det_scores\n    fuse_cost = 1 - fuse_sim\n    return fuse_cost"
  },
  {
    "path": "onnxruntime/python/byte_tracker/utils/yolox_utils.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nimport cv2\nimport numpy as np\n\n\ndef nms(boxes, scores, nms_thr):\n    \"\"\"Single class NMS implemented in Numpy.\"\"\"\n    x1 = boxes[:, 0]\n    y1 = boxes[:, 1]\n    x2 = boxes[:, 2]\n    y2 = boxes[:, 3]\n\n    areas = (x2 - x1 + 1) * (y2 - y1 + 1)\n    order = scores.argsort()[::-1]\n\n    keep = []\n    while order.size > 0:\n        i = order[0]\n        keep.append(i)\n        xx1 = np.maximum(x1[i], x1[order[1:]])\n        yy1 = np.maximum(y1[i], y1[order[1:]])\n        xx2 = np.minimum(x2[i], x2[order[1:]])\n        yy2 = np.minimum(y2[i], y2[order[1:]])\n\n        w = np.maximum(0.0, xx2 - xx1 + 1)\n        h = np.maximum(0.0, yy2 - yy1 + 1)\n        inter = w * h\n        ovr = inter / (areas[i] + areas[order[1:]] - inter)\n\n        inds = np.where(ovr <= nms_thr)[0]\n        order = order[inds + 1]\n\n    return keep\n\n\ndef multiclass_nms(boxes, scores, nms_thr, score_thr):\n    \"\"\"Multiclass NMS implemented in Numpy\"\"\"\n    final_dets = []\n    num_classes = scores.shape[1]\n    for cls_ind in range(num_classes):\n        cls_scores = scores[:, cls_ind]\n        valid_score_mask = cls_scores > score_thr\n        if valid_score_mask.sum() == 0:\n            continue\n        else:\n            valid_scores = cls_scores[valid_score_mask]\n            valid_boxes = boxes[valid_score_mask]\n            keep = nms(valid_boxes, valid_scores, nms_thr)\n            if len(keep) > 0:\n                cls_inds = np.ones((len(keep), 1)) * cls_ind\n                dets = np.concatenate(\n                    [valid_boxes[keep], valid_scores[keep, None], cls_inds], 1)\n                final_dets.append(dets)\n    if len(final_dets) == 0:\n        return None\n    return np.concatenate(final_dets, 0)\n\n\ndef pre_process(image, input_size, mean, std, swap=(2, 0, 1)):\n    if len(image.shape) == 3:\n        padded_img = np.ones((input_size[0], input_size[1], 3)) * 114.0\n    else:\n        padded_img = np.ones(input_size) * 114.0\n    img = np.array(image)\n    r = min(input_size[0] / img.shape[0], input_size[1] / img.shape[1])\n    resized_img = cv2.resize(\n        img,\n        (int(img.shape[1] * r), int(img.shape[0] * r)),\n        interpolation=cv2.INTER_LINEAR,\n    ).astype(np.float32)\n    padded_img[:int(img.shape[0] * r), :int(img.shape[1] * r)] = resized_img\n\n    padded_img = padded_img[:, :, ::-1]\n    padded_img /= 255.0\n    if mean is not None:\n        padded_img -= mean\n    if std is not None:\n        padded_img /= std\n    padded_img = padded_img.transpose(swap)\n    padded_img = np.ascontiguousarray(padded_img, dtype=np.float32)\n    return padded_img, r\n\n\ndef post_process(outputs, img_size, p6=False):\n    grids = []\n    expanded_strides = []\n\n    if not p6:\n        strides = [8, 16, 32]\n    else:\n        strides = [8, 16, 32, 64]\n\n    hsizes = [img_size[0] // stride for stride in strides]\n    wsizes = [img_size[1] // stride for stride in strides]\n\n    for hsize, wsize, stride in zip(hsizes, wsizes, strides):\n        xv, yv = np.meshgrid(np.arange(wsize), np.arange(hsize))\n        grid = np.stack((xv, yv), 2).reshape(1, -1, 2)\n        grids.append(grid)\n        shape = grid.shape[:2]\n        expanded_strides.append(np.full((*shape, 1), stride))\n\n    grids = np.concatenate(grids, 1)\n    expanded_strides = np.concatenate(expanded_strides, 1)\n    outputs[..., :2] = (outputs[..., :2] + grids) * expanded_strides\n    outputs[..., 2:4] = np.exp(outputs[..., 2:4]) * expanded_strides\n\n    return outputs\n"
  },
  {
    "path": "onnxruntime/python/main.py",
    "content": "import os\nimport copy\nimport time\nimport argparse\nimport cv2\nfrom loguru import logger\nfrom byte_tracker.byte_tracker_onnx import ByteTrackerONNX\n\ndef get_args():\n    parser = argparse.ArgumentParser()\n\n    parser.add_argument(\n        '--use_debug_window',\n        action='store_true',\n    )\n\n    parser.add_argument(\n        '--model',\n        type=str,\n        default='byte_tracker/model/bytetrack_s.onnx',\n    )\n    parser.add_argument(\n        '--video',\n        type=str,\n        default='sample.mp4',\n    )\n    parser.add_argument(\n        '--output_dir',\n        type=str,\n        default='output',\n    )\n    parser.add_argument(\n        '--score_th',\n        type=float,\n        default=0.1,\n    )\n    parser.add_argument(\n        '--nms_th',\n        type=float,\n        default=0.7,\n    )\n    parser.add_argument(\n        '--input_shape',\n        type=str,\n        default='608,1088',\n    )\n    parser.add_argument(\n        '--with_p6',\n        action='store_true',\n        help='Whether your model uses p6 in FPN/PAN.',\n    )\n\n    # tracking args\n    parser.add_argument(\n        '--track_thresh',\n        type=float,\n        default=0.5,\n        help='tracking confidence threshold',\n    )\n    parser.add_argument(\n        '--track_buffer',\n        type=int,\n        default=30,\n        help='the frames for keep lost tracks',\n    )\n    parser.add_argument(\n        '--match_thresh',\n        type=float,\n        default=0.8,\n        help='matching threshold for tracking',\n    )\n    parser.add_argument(\n        '--min-box-area',\n        type=float,\n        default=10,\n        help='filter out tiny boxes',\n    )\n    parser.add_argument(\n        '--mot20',\n        dest='mot20',\n        default=False,\n        action='store_true',\n        help='test mot20.',\n    )\n\n    args = parser.parse_args()\n\n    return args\n\n\ndef main():\n    args = get_args()\n\n    use_debug_window = args.use_debug_window\n\n    video_path = args.video\n    output_dir = args.output_dir\n\n    byte_tracker = ByteTrackerONNX(args)\n\n    cap = cv2.VideoCapture(video_path)\n    width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)\n    height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)\n    fps = cap.get(cv2.CAP_PROP_FPS)\n    frame_count = cap.get(cv2.CAP_PROP_FRAME_COUNT)\n\n    if not use_debug_window:\n        os.makedirs(output_dir, exist_ok=True)\n        save_path = os.path.join(output_dir, video_path.split(\"/\")[-1])\n        logger.info(f\"video save path is {save_path}\")\n\n        video_writer = cv2.VideoWriter(\n            save_path,\n            cv2.VideoWriter_fourcc(*\"mp4v\"),\n            fps,\n            (int(width), int(height)),\n        )\n\n    frame_id = 1\n\n    while True:\n        start_time = time.time()\n        ret, frame = cap.read()\n        if not ret:\n            break\n        debug_image = copy.deepcopy(frame)\n        _, bboxes, ids, scores = byte_tracker.inference(frame)\n        elapsed_time = time.time() - start_time\n        debug_image = draw_tracking_info(\n            debug_image,\n            bboxes,\n            ids,\n            scores,\n            frame_id,\n            elapsed_time,\n        )\n\n        if use_debug_window:\n            key = cv2.waitKey(1)\n            if key == 27:  # ESC\n                break\n            cv2.namedWindow('ByteTrack ONNX Sample', 0)\n            cv2.imshow('ByteTrack ONNX Sample', debug_image)\n        else:\n            video_writer.write(debug_image)\n\n        logger.info(\n            'frame {}/{} ({:.2f} ms)'.format(frame_id, int(frame_count),\n                                             elapsed_time * 1000), )\n        frame_id += 1\n\n    if use_debug_window:\n        cap.release()\n        cv2.destroyAllWindows()\n\n\ndef get_id_color(index):\n    temp_index = abs(int(index)) * 3\n    color = ((37 * temp_index) % 255, (17 * temp_index) % 255,\n             (29 * temp_index) % 255)\n    return color\n\n\ndef draw_tracking_info(\n    image,\n    tlwhs,\n    ids,\n    scores,\n    frame_id=0,\n    elapsed_time=0.,\n):\n    text_scale = 1.5\n    text_thickness = 2\n    line_thickness = 2\n\n    text = 'frame: %d ' % (frame_id)\n    text += 'elapsed time: %.0fms ' % (elapsed_time * 1000)\n    text += 'num: %d' % (len(tlwhs))\n    cv2.putText(\n        image,\n        text,\n        (0, int(15 * text_scale)),\n        cv2.FONT_HERSHEY_PLAIN,\n        2,\n        (0, 255, 0),\n        thickness=text_thickness,\n    )\n\n    for index, tlwh in enumerate(tlwhs):\n        x1, y1 = int(tlwh[0]), int(tlwh[1])\n        x2, y2 = x1 + int(tlwh[2]), y1 + int(tlwh[3])\n\n        color = get_id_color(ids[index])\n        cv2.rectangle(image, (x1, y1), (x2, y2), color, line_thickness)\n\n        # text = str(ids[index]) + ':%.2f' % (scores[index])\n        text = str(ids[index])\n        cv2.putText(image, text, (x1, y1 - 5), cv2.FONT_HERSHEY_PLAIN,\n                    text_scale, (0, 0, 0), text_thickness + 3)\n        cv2.putText(image, text, (x1, y1 - 5), cv2.FONT_HERSHEY_PLAIN,\n                    text_scale, (255, 255, 255), text_thickness)\n    return image\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "opencv/README.md",
    "content": "# ByteTrack-opencv\n\n#### 安装\n\n首先确保你的机器安装了opencv4.5以上版本的，接下来安装 `eigen`\n\n```shell\nunzip eigen-3.3.9.zip\ncd eigen-3.3.9\nmkdir build\ncd build\ncmake ..\nsudo make install\n```\n\n#### 编译C++程序\n\n```\nmkdir build\ncd build && rm -rf *\ncmake .. && make\n```\n\n#### 运行\n\npython版本：\n\n```\npython main.py\n```\n\nC++版本：\n\n```\n./bytetrack-opencv-cpp /home/ByteTrack/sample.mp4\n```\n\n"
  },
  {
    "path": "opencv/cpp/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.5)\nproject(bytetrack-opencv-cpp)\nset(CMAKE_CXX_STANDARD 11)\n\nfind_package(OpenCV REQUIRED)\ninclude_directories(include)\ninclude_directories(/usr/local/include/eigen3)\ninclude_directories(${OpenCV_INCLUDE_DIRS})\nfile(GLOB My_Source_Files src/*.cpp)\nadd_executable(bytetrack-opencv-cpp ${My_Source_Files})\ntarget_link_libraries(bytetrack-opencv-cpp ${OpenCV_LIBS})"
  },
  {
    "path": "opencv/cpp/include/BYTETracker.h",
    "content": "#pragma once\r\n\r\n#include \"STrack.h\"\r\n\r\nstruct Object\r\n{\r\n    cv::Rect_<float> rect;\r\n    int label;\r\n    float prob;\r\n};\r\n\r\nclass BYTETracker\r\n{\r\npublic:\r\n\tBYTETracker(int frame_rate = 30, int track_buffer = 30);\r\n\t~BYTETracker();\r\n\r\n\tvector<STrack> update(const vector<Object>& objects);\r\n\tScalar get_color(int idx);\r\n\r\nprivate:\r\n\tvector<STrack*> joint_stracks(vector<STrack*> &tlista, vector<STrack> &tlistb);\r\n\tvector<STrack> joint_stracks(vector<STrack> &tlista, vector<STrack> &tlistb);\r\n\r\n\tvector<STrack> sub_stracks(vector<STrack> &tlista, vector<STrack> &tlistb);\r\n\tvoid remove_duplicate_stracks(vector<STrack> &resa, vector<STrack> &resb, vector<STrack> &stracksa, vector<STrack> &stracksb);\r\n\r\n\tvoid linear_assignment(vector<vector<float> > &cost_matrix, int cost_matrix_size, int cost_matrix_size_size, float thresh,\r\n\t\tvector<vector<int> > &matches, vector<int> &unmatched_a, vector<int> &unmatched_b);\r\n\tvector<vector<float> > iou_distance(vector<STrack*> &atracks, vector<STrack> &btracks, int &dist_size, int &dist_size_size);\r\n\tvector<vector<float> > iou_distance(vector<STrack> &atracks, vector<STrack> &btracks);\r\n\tvector<vector<float> > ious(vector<vector<float> > &atlbrs, vector<vector<float> > &btlbrs);\r\n\r\n\tdouble lapjv(const vector<vector<float> > &cost, vector<int> &rowsol, vector<int> &colsol, \r\n\t\tbool extend_cost = false, float cost_limit = LONG_MAX, bool return_cost = true);\r\n\r\nprivate:\r\n\r\n\tfloat track_thresh;\r\n\tfloat high_thresh;\r\n\tfloat match_thresh;\r\n\tint frame_id;\r\n\tint max_time_lost;\r\n\r\n\tvector<STrack> tracked_stracks;\r\n\tvector<STrack> lost_stracks;\r\n\tvector<STrack> removed_stracks;\r\n\tbyte_kalman::KalmanFilter kalman_filter;\r\n};"
  },
  {
    "path": "opencv/cpp/include/STrack.h",
    "content": "#pragma once\r\n\r\n#include <opencv2/opencv.hpp>\r\n#include \"kalmanFilter.h\"\r\n\r\nusing namespace cv;\r\nusing namespace std;\r\n\r\nenum TrackState { New = 0, Tracked, Lost, Removed };\r\n\r\nclass STrack\r\n{\r\npublic:\r\n\tSTrack(vector<float> tlwh_, float score);\r\n\t~STrack();\r\n\r\n\tvector<float> static tlbr_to_tlwh(vector<float> &tlbr);\r\n\tvoid static multi_predict(vector<STrack*> &stracks, byte_kalman::KalmanFilter &kalman_filter);\r\n\tvoid static_tlwh();\r\n\tvoid static_tlbr();\r\n\tvector<float> tlwh_to_xyah(vector<float> tlwh_tmp);\r\n\tvector<float> to_xyah();\r\n\tvoid mark_lost();\r\n\tvoid mark_removed();\r\n\tint next_id();\r\n\tint end_frame();\r\n\t\r\n\tvoid activate(byte_kalman::KalmanFilter &kalman_filter, int frame_id);\r\n\tvoid re_activate(STrack &new_track, int frame_id, bool new_id = false);\r\n\tvoid update(STrack &new_track, int frame_id);\r\n\r\npublic:\r\n\tbool is_activated;\r\n\tint track_id;\r\n\tint state;\r\n\r\n\tvector<float> _tlwh;\r\n\tvector<float> tlwh;\r\n\tvector<float> tlbr;\r\n\tint frame_id;\r\n\tint tracklet_len;\r\n\tint start_frame;\r\n\r\n\tKAL_MEAN mean;\r\n\tKAL_COVA covariance;\r\n\tfloat score;\r\n\r\nprivate:\r\n\tbyte_kalman::KalmanFilter kalman_filter;\r\n};"
  },
  {
    "path": "opencv/cpp/include/dataType.h",
    "content": "#pragma once\r\n\r\n#include <cstddef>\r\n#include <vector>\r\n\r\n#include <Eigen/Core>\r\n#include <Eigen/Dense>\r\ntypedef Eigen::Matrix<float, 1, 4, Eigen::RowMajor> DETECTBOX;\r\ntypedef Eigen::Matrix<float, -1, 4, Eigen::RowMajor> DETECTBOXSS;\r\ntypedef Eigen::Matrix<float, 1, 128, Eigen::RowMajor> FEATURE;\r\ntypedef Eigen::Matrix<float, Eigen::Dynamic, 128, Eigen::RowMajor> FEATURESS;\r\n//typedef std::vector<FEATURE> FEATURESS;\r\n\r\n//Kalmanfilter\r\n//typedef Eigen::Matrix<float, 8, 8, Eigen::RowMajor> KAL_FILTER;\r\ntypedef Eigen::Matrix<float, 1, 8, Eigen::RowMajor> KAL_MEAN;\r\ntypedef Eigen::Matrix<float, 8, 8, Eigen::RowMajor> KAL_COVA;\r\ntypedef Eigen::Matrix<float, 1, 4, Eigen::RowMajor> KAL_HMEAN;\r\ntypedef Eigen::Matrix<float, 4, 4, Eigen::RowMajor> KAL_HCOVA;\r\nusing KAL_DATA = std::pair<KAL_MEAN, KAL_COVA>;\r\nusing KAL_HDATA = std::pair<KAL_HMEAN, KAL_HCOVA>;\r\n\r\n//main\r\nusing RESULT_DATA = std::pair<int, DETECTBOX>;\r\n\r\n//tracker:\r\nusing TRACKER_DATA = std::pair<int, FEATURESS>;\r\nusing MATCH_DATA = std::pair<int, int>;\r\ntypedef struct t {\r\n\tstd::vector<MATCH_DATA> matches;\r\n\tstd::vector<int> unmatched_tracks;\r\n\tstd::vector<int> unmatched_detections;\r\n}TRACHER_MATCHD;\r\n\r\n//linear_assignment:\r\ntypedef Eigen::Matrix<float, -1, -1, Eigen::RowMajor> DYNAMICM;"
  },
  {
    "path": "opencv/cpp/include/kalmanFilter.h",
    "content": "#pragma once\r\n\r\n#include \"dataType.h\"\r\n\r\nnamespace byte_kalman\r\n{\r\n\tclass KalmanFilter\r\n\t{\r\n\tpublic:\r\n\t\tstatic const double chi2inv95[10];\r\n\t\tKalmanFilter();\r\n\t\tKAL_DATA initiate(const DETECTBOX& measurement);\r\n\t\tvoid predict(KAL_MEAN& mean, KAL_COVA& covariance);\r\n\t\tKAL_HDATA project(const KAL_MEAN& mean, const KAL_COVA& covariance);\r\n\t\tKAL_DATA update(const KAL_MEAN& mean,\r\n\t\t\tconst KAL_COVA& covariance,\r\n\t\t\tconst DETECTBOX& measurement);\r\n\r\n\t\tEigen::Matrix<float, 1, -1> gating_distance(\r\n\t\t\tconst KAL_MEAN& mean,\r\n\t\t\tconst KAL_COVA& covariance,\r\n\t\t\tconst std::vector<DETECTBOX>& measurements,\r\n\t\t\tbool only_position = false);\r\n\r\n\tprivate:\r\n\t\tEigen::Matrix<float, 8, 8, Eigen::RowMajor> _motion_mat;\r\n\t\tEigen::Matrix<float, 4, 8, Eigen::RowMajor> _update_mat;\r\n\t\tfloat _std_weight_position;\r\n\t\tfloat _std_weight_velocity;\r\n\t};\r\n}"
  },
  {
    "path": "opencv/cpp/include/lapjv.h",
    "content": "#ifndef LAPJV_H\r\n#define LAPJV_H\r\n\r\n#define LARGE 1000000\r\n\r\n#if !defined TRUE\r\n#define TRUE 1\r\n#endif\r\n#if !defined FALSE\r\n#define FALSE 0\r\n#endif\r\n\r\n#define NEW(x, t, n) if ((x = (t *)malloc(sizeof(t) * (n))) == 0) { return -1; }\r\n#define FREE(x) if (x != 0) { free(x); x = 0; }\r\n#define SWAP_INDICES(a, b) { int_t _temp_index = a; a = b; b = _temp_index; }\r\n\r\n#if 0\r\n#include <assert.h>\r\n#define ASSERT(cond) assert(cond)\r\n#define PRINTF(fmt, ...) printf(fmt, ##__VA_ARGS__)\r\n#define PRINT_COST_ARRAY(a, n) \\\r\n    while (1) { \\\r\n        printf(#a\" = [\"); \\\r\n        if ((n) > 0) { \\\r\n            printf(\"%f\", (a)[0]); \\\r\n            for (uint_t j = 1; j < n; j++) { \\\r\n                printf(\", %f\", (a)[j]); \\\r\n            } \\\r\n        } \\\r\n        printf(\"]\\n\"); \\\r\n        break; \\\r\n    }\r\n#define PRINT_INDEX_ARRAY(a, n) \\\r\n    while (1) { \\\r\n        printf(#a\" = [\"); \\\r\n        if ((n) > 0) { \\\r\n            printf(\"%d\", (a)[0]); \\\r\n            for (uint_t j = 1; j < n; j++) { \\\r\n                printf(\", %d\", (a)[j]); \\\r\n            } \\\r\n        } \\\r\n        printf(\"]\\n\"); \\\r\n        break; \\\r\n    }\r\n#else\r\n#define ASSERT(cond)\r\n#define PRINTF(fmt, ...)\r\n#define PRINT_COST_ARRAY(a, n)\r\n#define PRINT_INDEX_ARRAY(a, n)\r\n#endif\r\n\r\n\r\ntypedef signed int int_t;\r\ntypedef unsigned int uint_t;\r\ntypedef double cost_t;\r\ntypedef char boolean;\r\ntypedef enum fp_t { FP_1 = 1, FP_2 = 2, FP_DYNAMIC = 3 } fp_t;\r\n\r\nextern int_t lapjv_internal(\r\n\tconst uint_t n, cost_t *cost[],\r\n\tint_t *x, int_t *y);\r\n\r\n#endif // LAPJV_H"
  },
  {
    "path": "opencv/cpp/src/BYTETracker.cpp",
    "content": "#include \"BYTETracker.h\"\r\n#include <fstream>\r\n\r\nBYTETracker::BYTETracker(int frame_rate, int track_buffer)\r\n{\r\n\ttrack_thresh = 0.5;\r\n\thigh_thresh = 0.6;\r\n\tmatch_thresh = 0.8;\r\n\r\n\tframe_id = 0;\r\n\tmax_time_lost = int(frame_rate / 30.0 * track_buffer);\r\n\tcout << \"Init ByteTrack!\" << endl;\r\n}\r\n\r\nBYTETracker::~BYTETracker()\r\n{\r\n}\r\n\r\nvector<STrack> BYTETracker::update(const vector<Object>& objects)\r\n{\r\n\r\n\t////////////////// Step 1: Get detections //////////////////\r\n\tthis->frame_id++;\r\n\tvector<STrack> activated_stracks;\r\n\tvector<STrack> refind_stracks;\r\n\tvector<STrack> removed_stracks;\r\n\tvector<STrack> lost_stracks;\r\n\tvector<STrack> detections;\r\n\tvector<STrack> detections_low;\r\n\r\n\tvector<STrack> detections_cp;\r\n\tvector<STrack> tracked_stracks_swap;\r\n\tvector<STrack> resa, resb;\r\n\tvector<STrack> output_stracks;\r\n\r\n\tvector<STrack*> unconfirmed;\r\n\tvector<STrack*> tracked_stracks;\r\n\tvector<STrack*> strack_pool;\r\n\tvector<STrack*> r_tracked_stracks;\r\n\r\n\tif (objects.size() > 0)\r\n\t{\r\n\t\tfor (int i = 0; i < objects.size(); i++)\r\n\t\t{\r\n\t\t\tvector<float> tlbr_;\r\n\t\t\ttlbr_.resize(4);\r\n\t\t\ttlbr_[0] = objects[i].rect.x;\r\n\t\t\ttlbr_[1] = objects[i].rect.y;\r\n\t\t\ttlbr_[2] = objects[i].rect.x + objects[i].rect.width;\r\n\t\t\ttlbr_[3] = objects[i].rect.y + objects[i].rect.height;\r\n\r\n\t\t\tfloat score = objects[i].prob;\r\n\r\n\t\t\tSTrack strack(STrack::tlbr_to_tlwh(tlbr_), score);\r\n\t\t\tif (score >= track_thresh)\r\n\t\t\t{\r\n\t\t\t\tdetections.push_back(strack);\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tdetections_low.push_back(strack);\r\n\t\t\t}\r\n\t\t\t\r\n\t\t}\r\n\t}\r\n\r\n\t// Add newly detected tracklets to tracked_stracks\r\n\tfor (int i = 0; i < this->tracked_stracks.size(); i++)\r\n\t{\r\n\t\tif (!this->tracked_stracks[i].is_activated)\r\n\t\t\tunconfirmed.push_back(&this->tracked_stracks[i]);\r\n\t\telse\r\n\t\t\ttracked_stracks.push_back(&this->tracked_stracks[i]);\r\n\t}\r\n\r\n\t////////////////// Step 2: First association, with IoU //////////////////\r\n\tstrack_pool = joint_stracks(tracked_stracks, this->lost_stracks);\r\n\tSTrack::multi_predict(strack_pool, this->kalman_filter);\r\n\r\n\tvector<vector<float> > dists;\r\n\tint dist_size = 0, dist_size_size = 0;\r\n\tdists = iou_distance(strack_pool, detections, dist_size, dist_size_size);\r\n\r\n\tvector<vector<int> > matches;\r\n\tvector<int> u_track, u_detection;\r\n\tlinear_assignment(dists, dist_size, dist_size_size, match_thresh, matches, u_track, u_detection);\r\n\r\n\tfor (int i = 0; i < matches.size(); i++)\r\n\t{\r\n\t\tSTrack *track = strack_pool[matches[i][0]];\r\n\t\tSTrack *det = &detections[matches[i][1]];\r\n\t\tif (track->state == TrackState::Tracked)\r\n\t\t{\r\n\t\t\ttrack->update(*det, this->frame_id);\r\n\t\t\tactivated_stracks.push_back(*track);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ttrack->re_activate(*det, this->frame_id, false);\r\n\t\t\trefind_stracks.push_back(*track);\r\n\t\t}\r\n\t}\r\n\r\n\t////////////////// Step 3: Second association, using low score dets //////////////////\r\n\tfor (int i = 0; i < u_detection.size(); i++)\r\n\t{\r\n\t\tdetections_cp.push_back(detections[u_detection[i]]);\r\n\t}\r\n\tdetections.clear();\r\n\tdetections.assign(detections_low.begin(), detections_low.end());\r\n\t\r\n\tfor (int i = 0; i < u_track.size(); i++)\r\n\t{\r\n\t\tif (strack_pool[u_track[i]]->state == TrackState::Tracked)\r\n\t\t{\r\n\t\t\tr_tracked_stracks.push_back(strack_pool[u_track[i]]);\r\n\t\t}\r\n\t}\r\n\r\n\tdists.clear();\r\n\tdists = iou_distance(r_tracked_stracks, detections, dist_size, dist_size_size);\r\n\r\n\tmatches.clear();\r\n\tu_track.clear();\r\n\tu_detection.clear();\r\n\tlinear_assignment(dists, dist_size, dist_size_size, 0.5, matches, u_track, u_detection);\r\n\r\n\tfor (int i = 0; i < matches.size(); i++)\r\n\t{\r\n\t\tSTrack *track = r_tracked_stracks[matches[i][0]];\r\n\t\tSTrack *det = &detections[matches[i][1]];\r\n\t\tif (track->state == TrackState::Tracked)\r\n\t\t{\r\n\t\t\ttrack->update(*det, this->frame_id);\r\n\t\t\tactivated_stracks.push_back(*track);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\ttrack->re_activate(*det, this->frame_id, false);\r\n\t\t\trefind_stracks.push_back(*track);\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int i = 0; i < u_track.size(); i++)\r\n\t{\r\n\t\tSTrack *track = r_tracked_stracks[u_track[i]];\r\n\t\tif (track->state != TrackState::Lost)\r\n\t\t{\r\n\t\t\ttrack->mark_lost();\r\n\t\t\tlost_stracks.push_back(*track);\r\n\t\t}\r\n\t}\r\n\r\n\t// Deal with unconfirmed tracks, usually tracks with only one beginning frame\r\n\tdetections.clear();\r\n\tdetections.assign(detections_cp.begin(), detections_cp.end());\r\n\r\n\tdists.clear();\r\n\tdists = iou_distance(unconfirmed, detections, dist_size, dist_size_size);\r\n\r\n\tmatches.clear();\r\n\tvector<int> u_unconfirmed;\r\n\tu_detection.clear();\r\n\tlinear_assignment(dists, dist_size, dist_size_size, 0.7, matches, u_unconfirmed, u_detection);\r\n\r\n\tfor (int i = 0; i < matches.size(); i++)\r\n\t{\r\n\t\tunconfirmed[matches[i][0]]->update(detections[matches[i][1]], this->frame_id);\r\n\t\tactivated_stracks.push_back(*unconfirmed[matches[i][0]]);\r\n\t}\r\n\r\n\tfor (int i = 0; i < u_unconfirmed.size(); i++)\r\n\t{\r\n\t\tSTrack *track = unconfirmed[u_unconfirmed[i]];\r\n\t\ttrack->mark_removed();\r\n\t\tremoved_stracks.push_back(*track);\r\n\t}\r\n\r\n\t////////////////// Step 4: Init new stracks //////////////////\r\n\tfor (int i = 0; i < u_detection.size(); i++)\r\n\t{\r\n\t\tSTrack *track = &detections[u_detection[i]];\r\n\t\tif (track->score < this->high_thresh)\r\n\t\t\tcontinue;\r\n\t\ttrack->activate(this->kalman_filter, this->frame_id);\r\n\t\tactivated_stracks.push_back(*track);\r\n\t}\r\n\r\n\t////////////////// Step 5: Update state //////////////////\r\n\tfor (int i = 0; i < this->lost_stracks.size(); i++)\r\n\t{\r\n\t\tif (this->frame_id - this->lost_stracks[i].end_frame() > this->max_time_lost)\r\n\t\t{\r\n\t\t\tthis->lost_stracks[i].mark_removed();\r\n\t\t\tremoved_stracks.push_back(this->lost_stracks[i]);\r\n\t\t}\r\n\t}\r\n\t\r\n\tfor (int i = 0; i < this->tracked_stracks.size(); i++)\r\n\t{\r\n\t\tif (this->tracked_stracks[i].state == TrackState::Tracked)\r\n\t\t{\r\n\t\t\ttracked_stracks_swap.push_back(this->tracked_stracks[i]);\r\n\t\t}\r\n\t}\r\n\tthis->tracked_stracks.clear();\r\n\tthis->tracked_stracks.assign(tracked_stracks_swap.begin(), tracked_stracks_swap.end());\r\n\r\n\tthis->tracked_stracks = joint_stracks(this->tracked_stracks, activated_stracks);\r\n\tthis->tracked_stracks = joint_stracks(this->tracked_stracks, refind_stracks);\r\n\r\n\t//std::cout << activated_stracks.size() << std::endl;\r\n\r\n\tthis->lost_stracks = sub_stracks(this->lost_stracks, this->tracked_stracks);\r\n\tfor (int i = 0; i < lost_stracks.size(); i++)\r\n\t{\r\n\t\tthis->lost_stracks.push_back(lost_stracks[i]);\r\n\t}\r\n\r\n\tthis->lost_stracks = sub_stracks(this->lost_stracks, this->removed_stracks);\r\n\tfor (int i = 0; i < removed_stracks.size(); i++)\r\n\t{\r\n\t\tthis->removed_stracks.push_back(removed_stracks[i]);\r\n\t}\r\n\t\r\n\tremove_duplicate_stracks(resa, resb, this->tracked_stracks, this->lost_stracks);\r\n\r\n\tthis->tracked_stracks.clear();\r\n\tthis->tracked_stracks.assign(resa.begin(), resa.end());\r\n\tthis->lost_stracks.clear();\r\n\tthis->lost_stracks.assign(resb.begin(), resb.end());\r\n\t\r\n\tfor (int i = 0; i < this->tracked_stracks.size(); i++)\r\n\t{\r\n\t\tif (this->tracked_stracks[i].is_activated)\r\n\t\t{\r\n\t\t\toutput_stracks.push_back(this->tracked_stracks[i]);\r\n\t\t}\r\n\t}\r\n\treturn output_stracks;\r\n}"
  },
  {
    "path": "opencv/cpp/src/STrack.cpp",
    "content": "#include \"STrack.h\"\r\n\r\nSTrack::STrack(vector<float> tlwh_, float score)\r\n{\r\n\t_tlwh.resize(4);\r\n\t_tlwh.assign(tlwh_.begin(), tlwh_.end());\r\n\r\n\tis_activated = false;\r\n\ttrack_id = 0;\r\n\tstate = TrackState::New;\r\n\t\r\n\ttlwh.resize(4);\r\n\ttlbr.resize(4);\r\n\r\n\tstatic_tlwh();\r\n\tstatic_tlbr();\r\n\tframe_id = 0;\r\n\ttracklet_len = 0;\r\n\tthis->score = score;\r\n\tstart_frame = 0;\r\n}\r\n\r\nSTrack::~STrack()\r\n{\r\n}\r\n\r\nvoid STrack::activate(byte_kalman::KalmanFilter &kalman_filter, int frame_id)\r\n{\r\n\tthis->kalman_filter = kalman_filter;\r\n\tthis->track_id = this->next_id();\r\n\r\n\tvector<float> _tlwh_tmp(4);\r\n\t_tlwh_tmp[0] = this->_tlwh[0];\r\n\t_tlwh_tmp[1] = this->_tlwh[1];\r\n\t_tlwh_tmp[2] = this->_tlwh[2];\r\n\t_tlwh_tmp[3] = this->_tlwh[3];\r\n\tvector<float> xyah = tlwh_to_xyah(_tlwh_tmp);\r\n\tDETECTBOX xyah_box;\r\n\txyah_box[0] = xyah[0];\r\n\txyah_box[1] = xyah[1];\r\n\txyah_box[2] = xyah[2];\r\n\txyah_box[3] = xyah[3];\r\n\tauto mc = this->kalman_filter.initiate(xyah_box);\r\n\tthis->mean = mc.first;\r\n\tthis->covariance = mc.second;\r\n\r\n\tstatic_tlwh();\r\n\tstatic_tlbr();\r\n\r\n\tthis->tracklet_len = 0;\r\n\tthis->state = TrackState::Tracked;\r\n\tif (frame_id == 1)\r\n\t{\r\n\t\tthis->is_activated = true;\r\n\t}\r\n\t//this->is_activated = true;\r\n\tthis->frame_id = frame_id;\r\n\tthis->start_frame = frame_id;\r\n}\r\n\r\nvoid STrack::re_activate(STrack &new_track, int frame_id, bool new_id)\r\n{\r\n\tvector<float> xyah = tlwh_to_xyah(new_track.tlwh);\r\n\tDETECTBOX xyah_box;\r\n\txyah_box[0] = xyah[0];\r\n\txyah_box[1] = xyah[1];\r\n\txyah_box[2] = xyah[2];\r\n\txyah_box[3] = xyah[3];\r\n\tauto mc = this->kalman_filter.update(this->mean, this->covariance, xyah_box);\r\n\tthis->mean = mc.first;\r\n\tthis->covariance = mc.second;\r\n\r\n\tstatic_tlwh();\r\n\tstatic_tlbr();\r\n\r\n\tthis->tracklet_len = 0;\r\n\tthis->state = TrackState::Tracked;\r\n\tthis->is_activated = true;\r\n\tthis->frame_id = frame_id;\r\n\tthis->score = new_track.score;\r\n\tif (new_id)\r\n\t\tthis->track_id = next_id();\r\n}\r\n\r\nvoid STrack::update(STrack &new_track, int frame_id)\r\n{\r\n\tthis->frame_id = frame_id;\r\n\tthis->tracklet_len++;\r\n\r\n\tvector<float> xyah = tlwh_to_xyah(new_track.tlwh);\r\n\tDETECTBOX xyah_box;\r\n\txyah_box[0] = xyah[0];\r\n\txyah_box[1] = xyah[1];\r\n\txyah_box[2] = xyah[2];\r\n\txyah_box[3] = xyah[3];\r\n\r\n\tauto mc = this->kalman_filter.update(this->mean, this->covariance, xyah_box);\r\n\tthis->mean = mc.first;\r\n\tthis->covariance = mc.second;\r\n\r\n\tstatic_tlwh();\r\n\tstatic_tlbr();\r\n\r\n\tthis->state = TrackState::Tracked;\r\n\tthis->is_activated = true;\r\n\r\n\tthis->score = new_track.score;\r\n}\r\n\r\nvoid STrack::static_tlwh()\r\n{\r\n\tif (this->state == TrackState::New)\r\n\t{\r\n\t\ttlwh[0] = _tlwh[0];\r\n\t\ttlwh[1] = _tlwh[1];\r\n\t\ttlwh[2] = _tlwh[2];\r\n\t\ttlwh[3] = _tlwh[3];\r\n\t\treturn;\r\n\t}\r\n\r\n\ttlwh[0] = mean[0];\r\n\ttlwh[1] = mean[1];\r\n\ttlwh[2] = mean[2];\r\n\ttlwh[3] = mean[3];\r\n\r\n\ttlwh[2] *= tlwh[3];\r\n\ttlwh[0] -= tlwh[2] / 2;\r\n\ttlwh[1] -= tlwh[3] / 2;\r\n}\r\n\r\nvoid STrack::static_tlbr()\r\n{\r\n\ttlbr.clear();\r\n\ttlbr.assign(tlwh.begin(), tlwh.end());\r\n\ttlbr[2] += tlbr[0];\r\n\ttlbr[3] += tlbr[1];\r\n}\r\n\r\nvector<float> STrack::tlwh_to_xyah(vector<float> tlwh_tmp)\r\n{\r\n\tvector<float> tlwh_output = tlwh_tmp;\r\n\ttlwh_output[0] += tlwh_output[2] / 2;\r\n\ttlwh_output[1] += tlwh_output[3] / 2;\r\n\ttlwh_output[2] /= tlwh_output[3];\r\n\treturn tlwh_output;\r\n}\r\n\r\nvector<float> STrack::to_xyah()\r\n{\r\n\treturn tlwh_to_xyah(tlwh);\r\n}\r\n\r\nvector<float> STrack::tlbr_to_tlwh(vector<float> &tlbr)\r\n{\r\n\ttlbr[2] -= tlbr[0];\r\n\ttlbr[3] -= tlbr[1];\r\n\treturn tlbr;\r\n}\r\n\r\nvoid STrack::mark_lost()\r\n{\r\n\tstate = TrackState::Lost;\r\n}\r\n\r\nvoid STrack::mark_removed()\r\n{\r\n\tstate = TrackState::Removed;\r\n}\r\n\r\nint STrack::next_id()\r\n{\r\n\tstatic int _count = 0;\r\n\t_count++;\r\n\treturn _count;\r\n}\r\n\r\nint STrack::end_frame()\r\n{\r\n\treturn this->frame_id;\r\n}\r\n\r\nvoid STrack::multi_predict(vector<STrack*> &stracks, byte_kalman::KalmanFilter &kalman_filter)\r\n{\r\n\tfor (int i = 0; i < stracks.size(); i++)\r\n\t{\r\n\t\tif (stracks[i]->state != TrackState::Tracked)\r\n\t\t{\r\n\t\t\tstracks[i]->mean[7] = 0;\r\n\t\t}\r\n\t\tkalman_filter.predict(stracks[i]->mean, stracks[i]->covariance);\r\n\t}\r\n}"
  },
  {
    "path": "opencv/cpp/src/kalmanFilter.cpp",
    "content": "#include \"kalmanFilter.h\"\r\n#include <Eigen/Cholesky>\r\n\r\nnamespace byte_kalman\r\n{\r\n\tconst double KalmanFilter::chi2inv95[10] = {\r\n\t0,\r\n\t3.8415,\r\n\t5.9915,\r\n\t7.8147,\r\n\t9.4877,\r\n\t11.070,\r\n\t12.592,\r\n\t14.067,\r\n\t15.507,\r\n\t16.919\r\n\t};\r\n\tKalmanFilter::KalmanFilter()\r\n\t{\r\n\t\tint ndim = 4;\r\n\t\tdouble dt = 1.;\r\n\r\n\t\t_motion_mat = Eigen::MatrixXf::Identity(8, 8);\r\n\t\tfor (int i = 0; i < ndim; i++) {\r\n\t\t\t_motion_mat(i, ndim + i) = dt;\r\n\t\t}\r\n\t\t_update_mat = Eigen::MatrixXf::Identity(4, 8);\r\n\r\n\t\tthis->_std_weight_position = 1. / 20;\r\n\t\tthis->_std_weight_velocity = 1. / 160;\r\n\t}\r\n\r\n\tKAL_DATA KalmanFilter::initiate(const DETECTBOX &measurement)\r\n\t{\r\n\t\tDETECTBOX mean_pos = measurement;\r\n\t\tDETECTBOX mean_vel;\r\n\t\tfor (int i = 0; i < 4; i++) mean_vel(i) = 0;\r\n\r\n\t\tKAL_MEAN mean;\r\n\t\tfor (int i = 0; i < 8; i++) {\r\n\t\t\tif (i < 4) mean(i) = mean_pos(i);\r\n\t\t\telse mean(i) = mean_vel(i - 4);\r\n\t\t}\r\n\r\n\t\tKAL_MEAN std;\r\n\t\tstd(0) = 2 * _std_weight_position * measurement[3];\r\n\t\tstd(1) = 2 * _std_weight_position * measurement[3];\r\n\t\tstd(2) = 1e-2;\r\n\t\tstd(3) = 2 * _std_weight_position * measurement[3];\r\n\t\tstd(4) = 10 * _std_weight_velocity * measurement[3];\r\n\t\tstd(5) = 10 * _std_weight_velocity * measurement[3];\r\n\t\tstd(6) = 1e-5;\r\n\t\tstd(7) = 10 * _std_weight_velocity * measurement[3];\r\n\r\n\t\tKAL_MEAN tmp = std.array().square();\r\n\t\tKAL_COVA var = tmp.asDiagonal();\r\n\t\treturn std::make_pair(mean, var);\r\n\t}\r\n\r\n\tvoid KalmanFilter::predict(KAL_MEAN &mean, KAL_COVA &covariance)\r\n\t{\r\n\t\t//revise the data;\r\n\t\tDETECTBOX std_pos;\r\n\t\tstd_pos << _std_weight_position * mean(3),\r\n\t\t\t_std_weight_position * mean(3),\r\n\t\t\t1e-2,\r\n\t\t\t_std_weight_position * mean(3);\r\n\t\tDETECTBOX std_vel;\r\n\t\tstd_vel << _std_weight_velocity * mean(3),\r\n\t\t\t_std_weight_velocity * mean(3),\r\n\t\t\t1e-5,\r\n\t\t\t_std_weight_velocity * mean(3);\r\n\t\tKAL_MEAN tmp;\r\n\t\ttmp.block<1, 4>(0, 0) = std_pos;\r\n\t\ttmp.block<1, 4>(0, 4) = std_vel;\r\n\t\ttmp = tmp.array().square();\r\n\t\tKAL_COVA motion_cov = tmp.asDiagonal();\r\n\t\tKAL_MEAN mean1 = this->_motion_mat * mean.transpose();\r\n\t\tKAL_COVA covariance1 = this->_motion_mat * covariance *(_motion_mat.transpose());\r\n\t\tcovariance1 += motion_cov;\r\n\r\n\t\tmean = mean1;\r\n\t\tcovariance = covariance1;\r\n\t}\r\n\r\n\tKAL_HDATA KalmanFilter::project(const KAL_MEAN &mean, const KAL_COVA &covariance)\r\n\t{\r\n\t\tDETECTBOX std;\r\n\t\tstd << _std_weight_position * mean(3), _std_weight_position * mean(3),\r\n\t\t\t1e-1, _std_weight_position * mean(3);\r\n\t\tKAL_HMEAN mean1 = _update_mat * mean.transpose();\r\n\t\tKAL_HCOVA covariance1 = _update_mat * covariance * (_update_mat.transpose());\r\n\t\tEigen::Matrix<float, 4, 4> diag = std.asDiagonal();\r\n\t\tdiag = diag.array().square().matrix();\r\n\t\tcovariance1 += diag;\r\n\t\t//    covariance1.diagonal() << diag;\r\n\t\treturn std::make_pair(mean1, covariance1);\r\n\t}\r\n\r\n\tKAL_DATA\r\n\t\tKalmanFilter::update(\r\n\t\t\tconst KAL_MEAN &mean,\r\n\t\t\tconst KAL_COVA &covariance,\r\n\t\t\tconst DETECTBOX &measurement)\r\n\t{\r\n\t\tKAL_HDATA pa = project(mean, covariance);\r\n\t\tKAL_HMEAN projected_mean = pa.first;\r\n\t\tKAL_HCOVA projected_cov = pa.second;\r\n\r\n\t\t//chol_factor, lower =\r\n\t\t//scipy.linalg.cho_factor(projected_cov, lower=True, check_finite=False)\r\n\t\t//kalmain_gain =\r\n\t\t//scipy.linalg.cho_solve((cho_factor, lower),\r\n\t\t//np.dot(covariance, self._upadte_mat.T).T,\r\n\t\t//check_finite=False).T\r\n\t\tEigen::Matrix<float, 4, 8> B = (covariance * (_update_mat.transpose())).transpose();\r\n\t\tEigen::Matrix<float, 8, 4> kalman_gain = (projected_cov.llt().solve(B)).transpose(); // eg.8x4\r\n\t\tEigen::Matrix<float, 1, 4> innovation = measurement - projected_mean; //eg.1x4\r\n\t\tauto tmp = innovation * (kalman_gain.transpose());\r\n\t\tKAL_MEAN new_mean = (mean.array() + tmp.array()).matrix();\r\n\t\tKAL_COVA new_covariance = covariance - kalman_gain * projected_cov*(kalman_gain.transpose());\r\n\t\treturn std::make_pair(new_mean, new_covariance);\r\n\t}\r\n\r\n\tEigen::Matrix<float, 1, -1>\r\n\t\tKalmanFilter::gating_distance(\r\n\t\t\tconst KAL_MEAN &mean,\r\n\t\t\tconst KAL_COVA &covariance,\r\n\t\t\tconst std::vector<DETECTBOX> &measurements,\r\n\t\t\tbool only_position)\r\n\t{\r\n\t\tKAL_HDATA pa = this->project(mean, covariance);\r\n\t\tif (only_position) {\r\n\t\t\tprintf(\"not implement!\");\r\n\t\t\texit(0);\r\n\t\t}\r\n\t\tKAL_HMEAN mean1 = pa.first;\r\n\t\tKAL_HCOVA covariance1 = pa.second;\r\n\r\n\t\t//    Eigen::Matrix<float, -1, 4, Eigen::RowMajor> d(size, 4);\r\n\t\tDETECTBOXSS d(measurements.size(), 4);\r\n\t\tint pos = 0;\r\n\t\tfor (DETECTBOX box : measurements) {\r\n\t\t\td.row(pos++) = box - mean1;\r\n\t\t}\r\n\t\tEigen::Matrix<float, -1, -1, Eigen::RowMajor> factor = covariance1.llt().matrixL();\r\n\t\tEigen::Matrix<float, -1, -1> z = factor.triangularView<Eigen::Lower>().solve<Eigen::OnTheRight>(d).transpose();\r\n\t\tauto zz = ((z.array())*(z.array())).matrix();\r\n\t\tauto square_maha = zz.colwise().sum();\r\n\t\treturn square_maha;\r\n\t}\r\n}"
  },
  {
    "path": "opencv/cpp/src/lapjv.cpp",
    "content": "#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <string.h>\r\n\r\n#include \"lapjv.h\"\r\n\r\n/** Column-reduction and reduction transfer for a dense cost matrix.\r\n */\r\nint_t _ccrrt_dense(const uint_t n, cost_t *cost[],\r\n\tint_t *free_rows, int_t *x, int_t *y, cost_t *v)\r\n{\r\n\tint_t n_free_rows;\r\n\tboolean *unique;\r\n\r\n\tfor (uint_t i = 0; i < n; i++) {\r\n\t\tx[i] = -1;\r\n\t\tv[i] = LARGE;\r\n\t\ty[i] = 0;\r\n\t}\r\n\tfor (uint_t i = 0; i < n; i++) {\r\n\t\tfor (uint_t j = 0; j < n; j++) {\r\n\t\t\tconst cost_t c = cost[i][j];\r\n\t\t\tif (c < v[j]) {\r\n\t\t\t\tv[j] = c;\r\n\t\t\t\ty[j] = i;\r\n\t\t\t}\r\n\t\t\tPRINTF(\"i=%d, j=%d, c[i,j]=%f, v[j]=%f y[j]=%d\\n\", i, j, c, v[j], y[j]);\r\n\t\t}\r\n\t}\r\n\tPRINT_COST_ARRAY(v, n);\r\n\tPRINT_INDEX_ARRAY(y, n);\r\n\tNEW(unique, boolean, n);\r\n\tmemset(unique, TRUE, n);\r\n\t{\r\n\t\tint_t j = n;\r\n\t\tdo {\r\n\t\t\tj--;\r\n\t\t\tconst int_t i = y[j];\r\n\t\t\tif (x[i] < 0) {\r\n\t\t\t\tx[i] = j;\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\tunique[i] = FALSE;\r\n\t\t\t\ty[j] = -1;\r\n\t\t\t}\r\n\t\t} while (j > 0);\r\n\t}\r\n\tn_free_rows = 0;\r\n\tfor (uint_t i = 0; i < n; i++) {\r\n\t\tif (x[i] < 0) {\r\n\t\t\tfree_rows[n_free_rows++] = i;\r\n\t\t}\r\n\t\telse if (unique[i]) {\r\n\t\t\tconst int_t j = x[i];\r\n\t\t\tcost_t min = LARGE;\r\n\t\t\tfor (uint_t j2 = 0; j2 < n; j2++) {\r\n\t\t\t\tif (j2 == (uint_t)j) {\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tconst cost_t c = cost[i][j2] - v[j2];\r\n\t\t\t\tif (c < min) {\r\n\t\t\t\t\tmin = c;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tPRINTF(\"v[%d] = %f - %f\\n\", j, v[j], min);\r\n\t\t\tv[j] -= min;\r\n\t\t}\r\n\t}\r\n\tFREE(unique);\r\n\treturn n_free_rows;\r\n}\r\n\r\n\r\n/** Augmenting row reduction for a dense cost matrix.\r\n */\r\nint_t _carr_dense(\r\n\tconst uint_t n, cost_t *cost[],\r\n\tconst uint_t n_free_rows,\r\n\tint_t *free_rows, int_t *x, int_t *y, cost_t *v)\r\n{\r\n\tuint_t current = 0;\r\n\tint_t new_free_rows = 0;\r\n\tuint_t rr_cnt = 0;\r\n\tPRINT_INDEX_ARRAY(x, n);\r\n\tPRINT_INDEX_ARRAY(y, n);\r\n\tPRINT_COST_ARRAY(v, n);\r\n\tPRINT_INDEX_ARRAY(free_rows, n_free_rows);\r\n\twhile (current < n_free_rows) {\r\n\t\tint_t i0;\r\n\t\tint_t j1, j2;\r\n\t\tcost_t v1, v2, v1_new;\r\n\t\tboolean v1_lowers;\r\n\r\n\t\trr_cnt++;\r\n\t\tPRINTF(\"current = %d rr_cnt = %d\\n\", current, rr_cnt);\r\n\t\tconst int_t free_i = free_rows[current++];\r\n\t\tj1 = 0;\r\n\t\tv1 = cost[free_i][0] - v[0];\r\n\t\tj2 = -1;\r\n\t\tv2 = LARGE;\r\n\t\tfor (uint_t j = 1; j < n; j++) {\r\n\t\t\tPRINTF(\"%d = %f %d = %f\\n\", j1, v1, j2, v2);\r\n\t\t\tconst cost_t c = cost[free_i][j] - v[j];\r\n\t\t\tif (c < v2) {\r\n\t\t\t\tif (c >= v1) {\r\n\t\t\t\t\tv2 = c;\r\n\t\t\t\t\tj2 = j;\r\n\t\t\t\t}\r\n\t\t\t\telse {\r\n\t\t\t\t\tv2 = v1;\r\n\t\t\t\t\tv1 = c;\r\n\t\t\t\t\tj2 = j1;\r\n\t\t\t\t\tj1 = j;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\ti0 = y[j1];\r\n\t\tv1_new = v[j1] - (v2 - v1);\r\n\t\tv1_lowers = v1_new < v[j1];\r\n\t\tPRINTF(\"%d %d 1=%d,%f 2=%d,%f v1'=%f(%d,%g) \\n\", free_i, i0, j1, v1, j2, v2, v1_new, v1_lowers, v[j1] - v1_new);\r\n\t\tif (rr_cnt < current * n) {\r\n\t\t\tif (v1_lowers) {\r\n\t\t\t\tv[j1] = v1_new;\r\n\t\t\t}\r\n\t\t\telse if (i0 >= 0 && j2 >= 0) {\r\n\t\t\t\tj1 = j2;\r\n\t\t\t\ti0 = y[j2];\r\n\t\t\t}\r\n\t\t\tif (i0 >= 0) {\r\n\t\t\t\tif (v1_lowers) {\r\n\t\t\t\t\tfree_rows[--current] = i0;\r\n\t\t\t\t}\r\n\t\t\t\telse {\r\n\t\t\t\t\tfree_rows[new_free_rows++] = i0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse {\r\n\t\t\tPRINTF(\"rr_cnt=%d >= %d (current=%d * n=%d)\\n\", rr_cnt, current * n, current, n);\r\n\t\t\tif (i0 >= 0) {\r\n\t\t\t\tfree_rows[new_free_rows++] = i0;\r\n\t\t\t}\r\n\t\t}\r\n\t\tx[free_i] = j1;\r\n\t\ty[j1] = free_i;\r\n\t}\r\n\treturn new_free_rows;\r\n}\r\n\r\n\r\n/** Find columns with minimum d[j] and put them on the SCAN list.\r\n */\r\nuint_t _find_dense(const uint_t n, uint_t lo, cost_t *d, int_t *cols, int_t *y)\r\n{\r\n\tuint_t hi = lo + 1;\r\n\tcost_t mind = d[cols[lo]];\r\n\tfor (uint_t k = hi; k < n; k++) {\r\n\t\tint_t j = cols[k];\r\n\t\tif (d[j] <= mind) {\r\n\t\t\tif (d[j] < mind) {\r\n\t\t\t\thi = lo;\r\n\t\t\t\tmind = d[j];\r\n\t\t\t}\r\n\t\t\tcols[k] = cols[hi];\r\n\t\t\tcols[hi++] = j;\r\n\t\t}\r\n\t}\r\n\treturn hi;\r\n}\r\n\r\n\r\n// Scan all columns in TODO starting from arbitrary column in SCAN\r\n// and try to decrease d of the TODO columns using the SCAN column.\r\nint_t _scan_dense(const uint_t n, cost_t *cost[],\r\n\tuint_t *plo, uint_t*phi,\r\n\tcost_t *d, int_t *cols, int_t *pred,\r\n\tint_t *y, cost_t *v)\r\n{\r\n\tuint_t lo = *plo;\r\n\tuint_t hi = *phi;\r\n\tcost_t h, cred_ij;\r\n\r\n\twhile (lo != hi) {\r\n\t\tint_t j = cols[lo++];\r\n\t\tconst int_t i = y[j];\r\n\t\tconst cost_t mind = d[j];\r\n\t\th = cost[i][j] - v[j] - mind;\r\n\t\tPRINTF(\"i=%d j=%d h=%f\\n\", i, j, h);\r\n\t\t// For all columns in TODO\r\n\t\tfor (uint_t k = hi; k < n; k++) {\r\n\t\t\tj = cols[k];\r\n\t\t\tcred_ij = cost[i][j] - v[j] - h;\r\n\t\t\tif (cred_ij < d[j]) {\r\n\t\t\t\td[j] = cred_ij;\r\n\t\t\t\tpred[j] = i;\r\n\t\t\t\tif (cred_ij == mind) {\r\n\t\t\t\t\tif (y[j] < 0) {\r\n\t\t\t\t\t\treturn j;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcols[k] = cols[hi];\r\n\t\t\t\t\tcols[hi++] = j;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t*plo = lo;\r\n\t*phi = hi;\r\n\treturn -1;\r\n}\r\n\r\n\r\n/** Single iteration of modified Dijkstra shortest path algorithm as explained in the JV paper.\r\n *\r\n * This is a dense matrix version.\r\n *\r\n * \\return The closest free column index.\r\n */\r\nint_t find_path_dense(\r\n\tconst uint_t n, cost_t *cost[],\r\n\tconst int_t start_i,\r\n\tint_t *y, cost_t *v,\r\n\tint_t *pred)\r\n{\r\n\tuint_t lo = 0, hi = 0;\r\n\tint_t final_j = -1;\r\n\tuint_t n_ready = 0;\r\n\tint_t *cols;\r\n\tcost_t *d;\r\n\r\n\tNEW(cols, int_t, n);\r\n\tNEW(d, cost_t, n);\r\n\r\n\tfor (uint_t i = 0; i < n; i++) {\r\n\t\tcols[i] = i;\r\n\t\tpred[i] = start_i;\r\n\t\td[i] = cost[start_i][i] - v[i];\r\n\t}\r\n\tPRINT_COST_ARRAY(d, n);\r\n\twhile (final_j == -1) {\r\n\t\t// No columns left on the SCAN list.\r\n\t\tif (lo == hi) {\r\n\t\t\tPRINTF(\"%d..%d -> find\\n\", lo, hi);\r\n\t\t\tn_ready = lo;\r\n\t\t\thi = _find_dense(n, lo, d, cols, y);\r\n\t\t\tPRINTF(\"check %d..%d\\n\", lo, hi);\r\n\t\t\tPRINT_INDEX_ARRAY(cols, n);\r\n\t\t\tfor (uint_t k = lo; k < hi; k++) {\r\n\t\t\t\tconst int_t j = cols[k];\r\n\t\t\t\tif (y[j] < 0) {\r\n\t\t\t\t\tfinal_j = j;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (final_j == -1) {\r\n\t\t\tPRINTF(\"%d..%d -> scan\\n\", lo, hi);\r\n\t\t\tfinal_j = _scan_dense(\r\n\t\t\t\tn, cost, &lo, &hi, d, cols, pred, y, v);\r\n\t\t\tPRINT_COST_ARRAY(d, n);\r\n\t\t\tPRINT_INDEX_ARRAY(cols, n);\r\n\t\t\tPRINT_INDEX_ARRAY(pred, n);\r\n\t\t}\r\n\t}\r\n\r\n\tPRINTF(\"found final_j=%d\\n\", final_j);\r\n\tPRINT_INDEX_ARRAY(cols, n);\r\n\t{\r\n\t\tconst cost_t mind = d[cols[lo]];\r\n\t\tfor (uint_t k = 0; k < n_ready; k++) {\r\n\t\t\tconst int_t j = cols[k];\r\n\t\t\tv[j] += d[j] - mind;\r\n\t\t}\r\n\t}\r\n\r\n\tFREE(cols);\r\n\tFREE(d);\r\n\r\n\treturn final_j;\r\n}\r\n\r\n\r\n/** Augment for a dense cost matrix.\r\n */\r\nint_t _ca_dense(\r\n\tconst uint_t n, cost_t *cost[],\r\n\tconst uint_t n_free_rows,\r\n\tint_t *free_rows, int_t *x, int_t *y, cost_t *v)\r\n{\r\n\tint_t *pred;\r\n\r\n\tNEW(pred, int_t, n);\r\n\r\n\tfor (int_t *pfree_i = free_rows; pfree_i < free_rows + n_free_rows; pfree_i++) {\r\n\t\tint_t i = -1, j;\r\n\t\tuint_t k = 0;\r\n\r\n\t\tPRINTF(\"looking at free_i=%d\\n\", *pfree_i);\r\n\t\tj = find_path_dense(n, cost, *pfree_i, y, v, pred);\r\n\t\tASSERT(j >= 0);\r\n\t\tASSERT(j < n);\r\n\t\twhile (i != *pfree_i) {\r\n\t\t\tPRINTF(\"augment %d\\n\", j);\r\n\t\t\tPRINT_INDEX_ARRAY(pred, n);\r\n\t\t\ti = pred[j];\r\n\t\t\tPRINTF(\"y[%d]=%d -> %d\\n\", j, y[j], i);\r\n\t\t\ty[j] = i;\r\n\t\t\tPRINT_INDEX_ARRAY(x, n);\r\n\t\t\tSWAP_INDICES(j, x[i]);\r\n\t\t\tk++;\r\n\t\t\tif (k >= n) {\r\n\t\t\t\tASSERT(FALSE);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\tFREE(pred);\r\n\treturn 0;\r\n}\r\n\r\n\r\n/** Solve dense sparse LAP.\r\n */\r\nint lapjv_internal(\r\n\tconst uint_t n, cost_t *cost[],\r\n\tint_t *x, int_t *y)\r\n{\r\n\tint ret;\r\n\tint_t *free_rows;\r\n\tcost_t *v;\r\n\r\n\tNEW(free_rows, int_t, n);\r\n\tNEW(v, cost_t, n);\r\n\tret = _ccrrt_dense(n, cost, free_rows, x, y, v);\r\n\tint i = 0;\r\n\twhile (ret > 0 && i < 2) {\r\n\t\tret = _carr_dense(n, cost, ret, free_rows, x, y, v);\r\n\t\ti++;\r\n\t}\r\n\tif (ret > 0) {\r\n\t\tret = _ca_dense(n, cost, ret, free_rows, x, y, v);\r\n\t}\r\n\tFREE(v);\r\n\tFREE(free_rows);\r\n\treturn ret;\r\n}"
  },
  {
    "path": "opencv/cpp/src/main.cpp",
    "content": "#include <iostream>\n#include <opencv2/core/core.hpp>\n#include <opencv2/imgproc.hpp>\n#include <opencv2/highgui.hpp>\n#include <opencv2/dnn.hpp>\n#include <float.h>\n#include <stdio.h>\n#include <vector>\n#include <chrono>\n#include \"BYTETracker.h\"\n\nusing namespace cv;\nusing namespace std;\nusing namespace dnn;\n\nstruct GridAndStride\n{\n    int grid0;\n    int grid1;\n    int stride;\n};\n\nstatic inline float intersection_area(const Object& a, const Object& b)\n{\n    cv::Rect_<float> inter = a.rect & b.rect;\n    return inter.area();\n}\n\nstatic void qsort_descent_inplace(std::vector<Object>& faceobjects, int left, int right)\n{\n    int i = left;\n    int j = right;\n    float p = faceobjects[(left + right) / 2].prob;\n\n    while (i <= j)\n    {\n        while (faceobjects[i].prob > p)\n            i++;\n\n        while (faceobjects[j].prob < p)\n            j--;\n\n        if (i <= j)\n        {\n            // swap\n            std::swap(faceobjects[i], faceobjects[j]);\n\n            i++;\n            j--;\n        }\n    }\n\n    #pragma omp parallel sections\n    {\n        #pragma omp section\n        {\n            if (left < j) qsort_descent_inplace(faceobjects, left, j);\n        }\n        #pragma omp section\n        {\n            if (i < right) qsort_descent_inplace(faceobjects, i, right);\n        }\n    }\n}\n\nstatic void qsort_descent_inplace(std::vector<Object>& objects)\n{\n    if (objects.empty())\n        return;\n\n    qsort_descent_inplace(objects, 0, objects.size() - 1);\n}\n\nclass yolox\n{\npublic:\n    yolox();\n    int detect(cv::Mat &img, std::vector<Object> &detectResults);\nprivate:\n    const int INPUT_W = 1088;\n    const int INPUT_H = 608;\n    const float mean_vals[3] = {0.485, 0.456, 0.406};\n    const float norm_vals[3] = {0.229, 0.224, 0.225};\n    const int stride_arr[3] = {8, 16, 32}; // might have stride=64 in YOLOX\n    std::vector<GridAndStride> grid_strides;\n\n    Mat static_resize(Mat& img);\n    void generate_grids_and_stride(std::vector<int>& strides);\n    void generate_yolox_proposals(const float* feat_ptr, std::vector<Object>& objects);\n    void nms_sorted_bboxes(const std::vector<Object>& faceobjects, std::vector<int>& picked);\n    float nms_threshold = 0.7;\n    float prob_threshold = 0.1;\n    int num_grid;\n    int num_class;\n    Net net;\n};\n\nyolox::yolox()\n{\n    string model_path = \"/home/ByteTrack/byte_tracker/model/bytetrack_s.onnx\";\n    this->net = readNet(model_path);\n    std::vector<int> strides(stride_arr, stride_arr + sizeof(stride_arr) / sizeof(stride_arr[0]));\n    generate_grids_and_stride(strides);\n}\n\nMat yolox::static_resize(Mat& img) {\n    float r = min(INPUT_W / (img.cols*1.0), INPUT_H / (img.rows*1.0));\n    // r = std::min(r, 1.0f);\n    int unpad_w = r * img.cols;\n    int unpad_h = r * img.rows;\n    Mat re(unpad_h, unpad_w, CV_8UC3);\n    resize(img, re, re.size());\n    Mat out(INPUT_H, INPUT_W, CV_8UC3, Scalar(114, 114, 114));\n    re.copyTo(out(Rect(0, 0, re.cols, re.rows)));\n    return out;\n}\n\nvoid yolox::generate_grids_and_stride(std::vector<int>& strides)\n{\n    for (int i = 0; i < (int)strides.size(); i++)\n    {\n        int stride = strides[i];\n        int num_grid_w = INPUT_W / stride;\n        int num_grid_h = INPUT_H / stride;\n        for (int g1 = 0; g1 < num_grid_h; g1++)\n        {\n            for (int g0 = 0; g0 < num_grid_w; g0++)\n            {\n                GridAndStride gs;\n                gs.grid0 = g0;\n                gs.grid1 = g1;\n                gs.stride = stride;\n                grid_strides.push_back(gs);\n            }\n        }\n    }\n}\n\nvoid yolox::generate_yolox_proposals(const float* feat_ptr, std::vector<Object>& objects)\n{\n    const int num_anchors = grid_strides.size();\n    for (int anchor_idx = 0; anchor_idx < num_anchors; anchor_idx++)\n    {\n        const int grid0 = grid_strides[anchor_idx].grid0;\n        const int grid1 = grid_strides[anchor_idx].grid1;\n        const int stride = grid_strides[anchor_idx].stride;\n\n        // yolox/models/yolo_head.py decode logic\n        //  outputs[..., :2] = (outputs[..., :2] + grids) * strides\n        //  outputs[..., 2:4] = torch.exp(outputs[..., 2:4]) * strides\n        float x_center = (feat_ptr[0] + grid0) * stride;\n        float y_center = (feat_ptr[1] + grid1) * stride;\n        float w = exp(feat_ptr[2]) * stride;\n        float h = exp(feat_ptr[3]) * stride;\n        float x0 = x_center - w * 0.5f;\n        float y0 = y_center - h * 0.5f;\n\n        float box_objectness = feat_ptr[4];\n        for (int class_idx = 0; class_idx < num_class; class_idx++)\n        {\n            float box_cls_score = feat_ptr[5 + class_idx];\n            float box_prob = box_objectness * box_cls_score;\n            if (box_prob > prob_threshold)\n            {\n                Object obj;\n                obj.rect.x = x0;\n                obj.rect.y = y0;\n                obj.rect.width = w;\n                obj.rect.height = h;\n                obj.label = class_idx;\n                obj.prob = box_prob;\n\n                objects.push_back(obj);\n            }\n\n        } // class loop\n        feat_ptr += (num_class + 5);\n\n    } // point anchor loop\n}\n\nvoid yolox::nms_sorted_bboxes(const std::vector<Object>& faceobjects, std::vector<int>& picked)\n{\n    picked.clear();\n\n    const int n = faceobjects.size();\n\n    std::vector<float> areas(n);\n    for (int i = 0; i < n; i++)\n    {\n        areas[i] = faceobjects[i].rect.area();\n    }\n\n    for (int i = 0; i < n; i++)\n    {\n        const Object& a = faceobjects[i];\n\n        int keep = 1;\n        for (int j = 0; j < (int)picked.size(); j++)\n        {\n            const Object& b = faceobjects[picked[j]];\n\n            // intersection over union\n            float inter_area = intersection_area(a, b);\n            float union_area = areas[i] + areas[picked[j]] - inter_area;\n            // float IoU = inter_area / union_area\n            if (inter_area / union_area > nms_threshold)\n                keep = 0;\n        }\n\n        if (keep)\n            picked.push_back(i);\n    }\n}\n\nint yolox::detect(cv::Mat &srcimg, std::vector<Object>& objects)\n{\n    float scale = min(INPUT_W / (srcimg.cols*1.0), INPUT_H / (srcimg.rows*1.0));\n    Mat img = static_resize(srcimg);\n    img.convertTo(img, CV_32F);\n\tint i = 0, j = 0;\n    for (i = 0; i < img.rows; i++)\n\t{\n\t\tfloat* pdata = (float*)(img.data + i * img.step);\n\t\tfor (j = 0; j < img.cols; j++)\n\t\t{\n\t\t    pdata[0] = (pdata[2] / 255.0 - this->mean_vals[0]) / this->norm_vals[0];\n\t\t\tpdata[1] = (pdata[1] / 255.0 - this->mean_vals[1]) / this->norm_vals[1];\n\t\t\tpdata[2] = (pdata[0] / 255.0 - this->mean_vals[2]) / this->norm_vals[2];\n\t\t\tpdata += 3;\n        }\n    }\n    Mat blob = blobFromImage(img);\n\tthis->net.setInput(blob);\n\tvector<Mat> outs;\n\tthis->net.forward(outs, this->net.getUnconnectedOutLayersNames());\n    this->num_grid = outs[0].size[1];\n    this->num_class = outs[0].size[2] - 5;\n    const float* out = (float*)outs[0].data;\n    std::vector<Object> proposals;\n    generate_yolox_proposals(out, proposals);\n    // sort all proposals by score from highest to lowest\n    qsort_descent_inplace(proposals);\n\n    // apply nms with nms_threshold\n    std::vector<int> picked;\n    nms_sorted_bboxes(proposals, picked);\n\n    int count = picked.size();\n\n    objects.resize(count);\n    for (int i = 0; i < count; i++)\n    {\n        objects[i] = proposals[picked[i]];\n\n        // adjust offset to original unpadded\n        float x0 = (objects[i].rect.x) / scale;\n        float y0 = (objects[i].rect.y) / scale;\n        float x1 = (objects[i].rect.x + objects[i].rect.width) / scale;\n        float y1 = (objects[i].rect.y + objects[i].rect.height) / scale;\n\n        // clip\n        // x0 = std::max(std::min(x0, (float)(img_w - 1)), 0.f);\n        // y0 = std::max(std::min(y0, (float)(img_h - 1)), 0.f);\n        // x1 = std::max(std::min(x1, (float)(img_w - 1)), 0.f);\n        // y1 = std::max(std::min(y1, (float)(img_h - 1)), 0.f);\n\n        objects[i].rect.x = x0;\n        objects[i].rect.y = y0;\n        objects[i].rect.width = x1 - x0;\n        objects[i].rect.height = y1 - y0;\n    }\n\n    return 0;\n}\n\nint main(int argc, char** argv)\n{\n    if (argc != 2)\n    {\n        fprintf(stderr, \"Usage: %s [videopath]\\n\", argv[0]);\n        return -1;\n    }\n\n    const char* videopath = argv[1];\n    VideoCapture cap(videopath);\n\tif (!cap.isOpened())\n\t\treturn 0;\n\n\tint img_w = cap.get(CAP_PROP_FRAME_WIDTH);\n\tint img_h = cap.get(CAP_PROP_FRAME_HEIGHT);\n    int fps = cap.get(CAP_PROP_FPS);\n    long nFrame = static_cast<long>(cap.get(CAP_PROP_FRAME_COUNT));\n    cout << \"Total frames: \" << nFrame << \", fps: \"<<fps<<endl;\n\n    VideoWriter writer(\"demo.avi\", cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), fps, Size(img_w, img_h));\n\n    Mat img;\n    yolox yolox;\n    BYTETracker tracker(fps, 30);\n    int num_frames = 0;\n    int total_ms = 1;\n\tfor (;;)\n    {\n        if(!cap.read(img))\n            break;\n        num_frames++;\n        /*if(num_frames%100 != 0)\n            continue;*/\n\n        if (num_frames % 20 == 0)\n        {\n            cout << \"Processing frame \" << num_frames << \" (\" << num_frames * 1000000 / total_ms << \" fps)\" << endl;\n        }\n\t\tif (img.empty())\n\t\t\tbreak;\n        //cout<<\"Processing frame \"<<num_frames<<endl;\n        std::vector<Object> objects;\n        auto start = chrono::system_clock::now();\n        yolox.detect(img, objects);\n        vector<STrack> output_stracks = tracker.update(objects);\n        auto end = chrono::system_clock::now();\n        total_ms = total_ms + chrono::duration_cast<chrono::microseconds>(end - start).count();\n        for (int i = 0; i < output_stracks.size(); i++)\n\t\t{\n\t\t\tvector<float> tlwh = output_stracks[i].tlwh;\n\t\t\tbool vertical = tlwh[2] / tlwh[3] > 1.6;\n\t\t\tif (tlwh[2] * tlwh[3] > 20 && !vertical)\n\t\t\t{\n\t\t\t\tScalar s = tracker.get_color(output_stracks[i].track_id);\n\t\t\t\tputText(img, format(\"%d\", output_stracks[i].track_id), Point(tlwh[0], tlwh[1] - 5), \n                        0, 0.6, Scalar(0, 0, 255), 2, LINE_AA);\n                rectangle(img, Rect(tlwh[0], tlwh[1], tlwh[2], tlwh[3]), s, 2);\n\t\t\t}\n\t\t}\n        putText(img, format(\"frame: %d fps: %d num: %d\", num_frames, num_frames * 1000000 / total_ms, (int)output_stracks.size()),\n                Point(0, 30), 0, 0.6, Scalar(0, 0, 255), 2, LINE_AA);\n        writer.write(img);\n        /*char c = waitKey(1);\n        if (c > 0)\n        {\n            break;\n        }*/\n    }\n    cap.release();\n    cout << \"FPS: \" << num_frames * 1000000 / total_ms << endl;\n\n    return 0;\n}\n"
  },
  {
    "path": "opencv/cpp/src/utils.cpp",
    "content": "#include \"BYTETracker.h\"\r\n#include \"lapjv.h\"\r\n\r\nvector<STrack*> BYTETracker::joint_stracks(vector<STrack*> &tlista, vector<STrack> &tlistb)\r\n{\r\n\tmap<int, int> exists;\r\n\tvector<STrack*> res;\r\n\tfor (int i = 0; i < tlista.size(); i++)\r\n\t{\r\n\t\texists.insert(pair<int, int>(tlista[i]->track_id, 1));\r\n\t\tres.push_back(tlista[i]);\r\n\t}\r\n\tfor (int i = 0; i < tlistb.size(); i++)\r\n\t{\r\n\t\tint tid = tlistb[i].track_id;\r\n\t\tif (!exists[tid] || exists.count(tid) == 0)\r\n\t\t{\r\n\t\t\texists[tid] = 1;\r\n\t\t\tres.push_back(&tlistb[i]);\r\n\t\t}\r\n\t}\r\n\treturn res;\r\n}\r\n\r\nvector<STrack> BYTETracker::joint_stracks(vector<STrack> &tlista, vector<STrack> &tlistb)\r\n{\r\n\tmap<int, int> exists;\r\n\tvector<STrack> res;\r\n\tfor (int i = 0; i < tlista.size(); i++)\r\n\t{\r\n\t\texists.insert(pair<int, int>(tlista[i].track_id, 1));\r\n\t\tres.push_back(tlista[i]);\r\n\t}\r\n\tfor (int i = 0; i < tlistb.size(); i++)\r\n\t{\r\n\t\tint tid = tlistb[i].track_id;\r\n\t\tif (!exists[tid] || exists.count(tid) == 0)\r\n\t\t{\r\n\t\t\texists[tid] = 1;\r\n\t\t\tres.push_back(tlistb[i]);\r\n\t\t}\r\n\t}\r\n\treturn res;\r\n}\r\n\r\nvector<STrack> BYTETracker::sub_stracks(vector<STrack> &tlista, vector<STrack> &tlistb)\r\n{\r\n\tmap<int, STrack> stracks;\r\n\tfor (int i = 0; i < tlista.size(); i++)\r\n\t{\r\n\t\tstracks.insert(pair<int, STrack>(tlista[i].track_id, tlista[i]));\r\n\t}\r\n\tfor (int i = 0; i < tlistb.size(); i++)\r\n\t{\r\n\t\tint tid = tlistb[i].track_id;\r\n\t\tif (stracks.count(tid) != 0)\r\n\t\t{\r\n\t\t\tstracks.erase(tid);\r\n\t\t}\r\n\t}\r\n\r\n\tvector<STrack> res;\r\n\tstd::map<int, STrack>::iterator  it;\r\n\tfor (it = stracks.begin(); it != stracks.end(); ++it)\r\n\t{\r\n\t\tres.push_back(it->second);\r\n\t}\r\n\r\n\treturn res;\r\n}\r\n\r\nvoid BYTETracker::remove_duplicate_stracks(vector<STrack> &resa, vector<STrack> &resb, vector<STrack> &stracksa, vector<STrack> &stracksb)\r\n{\r\n\tvector<vector<float> > pdist = iou_distance(stracksa, stracksb);\r\n\tvector<pair<int, int> > pairs;\r\n\tfor (int i = 0; i < pdist.size(); i++)\r\n\t{\r\n\t\tfor (int j = 0; j < pdist[i].size(); j++)\r\n\t\t{\r\n\t\t\tif (pdist[i][j] < 0.15)\r\n\t\t\t{\r\n\t\t\t\tpairs.push_back(pair<int, int>(i, j));\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tvector<int> dupa, dupb;\r\n\tfor (int i = 0; i < pairs.size(); i++)\r\n\t{\r\n\t\tint timep = stracksa[pairs[i].first].frame_id - stracksa[pairs[i].first].start_frame;\r\n\t\tint timeq = stracksb[pairs[i].second].frame_id - stracksb[pairs[i].second].start_frame;\r\n\t\tif (timep > timeq)\r\n\t\t\tdupb.push_back(pairs[i].second);\r\n\t\telse\r\n\t\t\tdupa.push_back(pairs[i].first);\r\n\t}\r\n\r\n\tfor (int i = 0; i < stracksa.size(); i++)\r\n\t{\r\n\t\tvector<int>::iterator iter = find(dupa.begin(), dupa.end(), i);\r\n\t\tif (iter == dupa.end())\r\n\t\t{\r\n\t\t\tresa.push_back(stracksa[i]);\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int i = 0; i < stracksb.size(); i++)\r\n\t{\r\n\t\tvector<int>::iterator iter = find(dupb.begin(), dupb.end(), i);\r\n\t\tif (iter == dupb.end())\r\n\t\t{\r\n\t\t\tresb.push_back(stracksb[i]);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvoid BYTETracker::linear_assignment(vector<vector<float> > &cost_matrix, int cost_matrix_size, int cost_matrix_size_size, float thresh,\r\n\tvector<vector<int> > &matches, vector<int> &unmatched_a, vector<int> &unmatched_b)\r\n{\r\n\tif (cost_matrix.size() == 0)\r\n\t{\r\n\t\tfor (int i = 0; i < cost_matrix_size; i++)\r\n\t\t{\r\n\t\t\tunmatched_a.push_back(i);\r\n\t\t}\r\n\t\tfor (int i = 0; i < cost_matrix_size_size; i++)\r\n\t\t{\r\n\t\t\tunmatched_b.push_back(i);\r\n\t\t}\r\n\t\treturn;\r\n\t}\r\n\r\n\tvector<int> rowsol; vector<int> colsol;\r\n\tfloat c = lapjv(cost_matrix, rowsol, colsol, true, thresh);\r\n\tfor (int i = 0; i < rowsol.size(); i++)\r\n\t{\r\n\t\tif (rowsol[i] >= 0)\r\n\t\t{\r\n\t\t\tvector<int> match;\r\n\t\t\tmatch.push_back(i);\r\n\t\t\tmatch.push_back(rowsol[i]);\r\n\t\t\tmatches.push_back(match);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tunmatched_a.push_back(i);\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int i = 0; i < colsol.size(); i++)\r\n\t{\r\n\t\tif (colsol[i] < 0)\r\n\t\t{\r\n\t\t\tunmatched_b.push_back(i);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nvector<vector<float> > BYTETracker::ious(vector<vector<float> > &atlbrs, vector<vector<float> > &btlbrs)\r\n{\r\n\tvector<vector<float> > ious;\r\n\tif (atlbrs.size()*btlbrs.size() == 0)\r\n\t\treturn ious;\r\n\r\n\tious.resize(atlbrs.size());\r\n\tfor (int i = 0; i < ious.size(); i++)\r\n\t{\r\n\t\tious[i].resize(btlbrs.size());\r\n\t}\r\n\r\n\t//bbox_ious\r\n\tfor (int k = 0; k < btlbrs.size(); k++)\r\n\t{\r\n\t\tvector<float> ious_tmp;\r\n\t\tfloat box_area = (btlbrs[k][2] - btlbrs[k][0] + 1)*(btlbrs[k][3] - btlbrs[k][1] + 1);\r\n\t\tfor (int n = 0; n < atlbrs.size(); n++)\r\n\t\t{\r\n\t\t\tfloat iw = min(atlbrs[n][2], btlbrs[k][2]) - max(atlbrs[n][0], btlbrs[k][0]) + 1;\r\n\t\t\tif (iw > 0)\r\n\t\t\t{\r\n\t\t\t\tfloat ih = min(atlbrs[n][3], btlbrs[k][3]) - max(atlbrs[n][1], btlbrs[k][1]) + 1;\r\n\t\t\t\tif(ih > 0)\r\n\t\t\t\t{\r\n\t\t\t\t\tfloat ua = (atlbrs[n][2] - atlbrs[n][0] + 1)*(atlbrs[n][3] - atlbrs[n][1] + 1) + box_area - iw * ih;\r\n\t\t\t\t\tious[n][k] = iw * ih / ua;\r\n\t\t\t\t}\r\n\t\t\t\telse\r\n\t\t\t\t{\r\n\t\t\t\t\tious[n][k] = 0.0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\telse\r\n\t\t\t{\r\n\t\t\t\tious[n][k] = 0.0;\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\treturn ious;\r\n}\r\n\r\nvector<vector<float> > BYTETracker::iou_distance(vector<STrack*> &atracks, vector<STrack> &btracks, int &dist_size, int &dist_size_size)\r\n{\r\n\tvector<vector<float> > cost_matrix;\r\n\tif (atracks.size() * btracks.size() == 0)\r\n\t{\r\n\t\tdist_size = atracks.size();\r\n\t\tdist_size_size = btracks.size();\r\n\t\treturn cost_matrix;\r\n\t}\r\n\tvector<vector<float> > atlbrs, btlbrs;\r\n\tfor (int i = 0; i < atracks.size(); i++)\r\n\t{\r\n\t\tatlbrs.push_back(atracks[i]->tlbr);\r\n\t}\r\n\tfor (int i = 0; i < btracks.size(); i++)\r\n\t{\r\n\t\tbtlbrs.push_back(btracks[i].tlbr);\r\n\t}\r\n\r\n\tdist_size = atracks.size();\r\n\tdist_size_size = btracks.size();\r\n\r\n\tvector<vector<float> > _ious = ious(atlbrs, btlbrs);\r\n\t\r\n\tfor (int i = 0; i < _ious.size();i++)\r\n\t{\r\n\t\tvector<float> _iou;\r\n\t\tfor (int j = 0; j < _ious[i].size(); j++)\r\n\t\t{\r\n\t\t\t_iou.push_back(1 - _ious[i][j]);\r\n\t\t}\r\n\t\tcost_matrix.push_back(_iou);\r\n\t}\r\n\r\n\treturn cost_matrix;\r\n}\r\n\r\nvector<vector<float> > BYTETracker::iou_distance(vector<STrack> &atracks, vector<STrack> &btracks)\r\n{\r\n\tvector<vector<float> > atlbrs, btlbrs;\r\n\tfor (int i = 0; i < atracks.size(); i++)\r\n\t{\r\n\t\tatlbrs.push_back(atracks[i].tlbr);\r\n\t}\r\n\tfor (int i = 0; i < btracks.size(); i++)\r\n\t{\r\n\t\tbtlbrs.push_back(btracks[i].tlbr);\r\n\t}\r\n\r\n\tvector<vector<float> > _ious = ious(atlbrs, btlbrs);\r\n\tvector<vector<float> > cost_matrix;\r\n\tfor (int i = 0; i < _ious.size(); i++)\r\n\t{\r\n\t\tvector<float> _iou;\r\n\t\tfor (int j = 0; j < _ious[i].size(); j++)\r\n\t\t{\r\n\t\t\t_iou.push_back(1 - _ious[i][j]);\r\n\t\t}\r\n\t\tcost_matrix.push_back(_iou);\r\n\t}\r\n\r\n\treturn cost_matrix;\r\n}\r\n\r\ndouble BYTETracker::lapjv(const vector<vector<float> > &cost, vector<int> &rowsol, vector<int> &colsol,\r\n\tbool extend_cost, float cost_limit, bool return_cost)\r\n{\r\n\tvector<vector<float> > cost_c;\r\n\tcost_c.assign(cost.begin(), cost.end());\r\n\r\n\tvector<vector<float> > cost_c_extended;\r\n\r\n\tint n_rows = cost.size();\r\n\tint n_cols = cost[0].size();\r\n\trowsol.resize(n_rows);\r\n\tcolsol.resize(n_cols);\r\n\r\n\tint n = 0;\r\n\tif (n_rows == n_cols)\r\n\t{\r\n\t\tn = n_rows;\r\n\t}\r\n\telse\r\n\t{\r\n\t\tif (!extend_cost)\r\n\t\t{\r\n\t\t\tcout << \"set extend_cost=True\" << endl;\r\n\t\t\tsystem(\"pause\");\r\n\t\t\texit(0);\r\n\t\t}\r\n\t}\r\n\t\t\r\n\tif (extend_cost || cost_limit < LONG_MAX)\r\n\t{\r\n\t\tn = n_rows + n_cols;\r\n\t\tcost_c_extended.resize(n);\r\n\t\tfor (int i = 0; i < cost_c_extended.size(); i++)\r\n\t\t\tcost_c_extended[i].resize(n);\r\n\r\n\t\tif (cost_limit < LONG_MAX)\r\n\t\t{\r\n\t\t\tfor (int i = 0; i < cost_c_extended.size(); i++)\r\n\t\t\t{\r\n\t\t\t\tfor (int j = 0; j < cost_c_extended[i].size(); j++)\r\n\t\t\t\t{\r\n\t\t\t\t\tcost_c_extended[i][j] = cost_limit / 2.0;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tfloat cost_max = -1;\r\n\t\t\tfor (int i = 0; i < cost_c.size(); i++)\r\n\t\t\t{\r\n\t\t\t\tfor (int j = 0; j < cost_c[i].size(); j++)\r\n\t\t\t\t{\r\n\t\t\t\t\tif (cost_c[i][j] > cost_max)\r\n\t\t\t\t\t\tcost_max = cost_c[i][j];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tfor (int i = 0; i < cost_c_extended.size(); i++)\r\n\t\t\t{\r\n\t\t\t\tfor (int j = 0; j < cost_c_extended[i].size(); j++)\r\n\t\t\t\t{\r\n\t\t\t\t\tcost_c_extended[i][j] = cost_max + 1;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tfor (int i = n_rows; i < cost_c_extended.size(); i++)\r\n\t\t{\r\n\t\t\tfor (int j = n_cols; j < cost_c_extended[i].size(); j++)\r\n\t\t\t{\r\n\t\t\t\tcost_c_extended[i][j] = 0;\r\n\t\t\t}\r\n\t\t}\r\n\t\tfor (int i = 0; i < n_rows; i++)\r\n\t\t{\r\n\t\t\tfor (int j = 0; j < n_cols; j++)\r\n\t\t\t{\r\n\t\t\t\tcost_c_extended[i][j] = cost_c[i][j];\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tcost_c.clear();\r\n\t\tcost_c.assign(cost_c_extended.begin(), cost_c_extended.end());\r\n\t}\r\n\r\n\tdouble **cost_ptr;\r\n\tcost_ptr = new double *[sizeof(double *) * n];\r\n\tfor (int i = 0; i < n; i++)\r\n\t\tcost_ptr[i] = new double[sizeof(double) * n];\r\n\r\n\tfor (int i = 0; i < n; i++)\r\n\t{\r\n\t\tfor (int j = 0; j < n; j++)\r\n\t\t{\r\n\t\t\tcost_ptr[i][j] = cost_c[i][j];\r\n\t\t}\r\n\t}\r\n\r\n\tint* x_c = new int[sizeof(int) * n];\r\n\tint *y_c = new int[sizeof(int) * n];\r\n\r\n\tint ret = lapjv_internal(n, cost_ptr, x_c, y_c);\r\n\tif (ret != 0)\r\n\t{\r\n\t\tcout << \"Calculate Wrong!\" << endl;\r\n\t\tsystem(\"pause\");\r\n\t\texit(0);\r\n\t}\r\n\r\n\tdouble opt = 0.0;\r\n\r\n\tif (n != n_rows)\r\n\t{\r\n\t\tfor (int i = 0; i < n; i++)\r\n\t\t{\r\n\t\t\tif (x_c[i] >= n_cols)\r\n\t\t\t\tx_c[i] = -1;\r\n\t\t\tif (y_c[i] >= n_rows)\r\n\t\t\t\ty_c[i] = -1;\r\n\t\t}\r\n\t\tfor (int i = 0; i < n_rows; i++)\r\n\t\t{\r\n\t\t\trowsol[i] = x_c[i];\r\n\t\t}\r\n\t\tfor (int i = 0; i < n_cols; i++)\r\n\t\t{\r\n\t\t\tcolsol[i] = y_c[i];\r\n\t\t}\r\n\r\n\t\tif (return_cost)\r\n\t\t{\r\n\t\t\tfor (int i = 0; i < rowsol.size(); i++)\r\n\t\t\t{\r\n\t\t\t\tif (rowsol[i] != -1)\r\n\t\t\t\t{\r\n\t\t\t\t\t//cout << i << \"\\t\" << rowsol[i] << \"\\t\" << cost_ptr[i][rowsol[i]] << endl;\r\n\t\t\t\t\topt += cost_ptr[i][rowsol[i]];\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\telse if (return_cost)\r\n\t{\r\n\t\tfor (int i = 0; i < rowsol.size(); i++)\r\n\t\t{\r\n\t\t\topt += cost_ptr[i][rowsol[i]];\r\n\t\t}\r\n\t}\r\n\r\n\tfor (int i = 0; i < n; i++)\r\n\t{\r\n\t\tdelete[]cost_ptr[i];\r\n\t}\r\n\tdelete[]cost_ptr;\r\n\tdelete[]x_c;\r\n\tdelete[]y_c;\r\n\r\n\treturn opt;\r\n}\r\n\r\nScalar BYTETracker::get_color(int idx)\r\n{\r\n\tidx += 3;\r\n\treturn Scalar(37 * idx % 255, 17 * idx % 255, 29 * idx % 255);\r\n}"
  },
  {
    "path": "opencv/python/byte_tracker/byte_tracker_onnx.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nimport copy\n\nimport numpy as np\nimport onnxruntime\n\nfrom byte_tracker.utils.yolox_utils import (\n    pre_process,\n    post_process,\n    multiclass_nms,\n)\nfrom byte_tracker.tracker.byte_tracker import BYTETracker\n\n\nclass ByteTrackerONNX(object):\n    def __init__(self, args):\n        self.args = args\n\n        self.rgb_means = (0.485, 0.456, 0.406)\n        self.std = (0.229, 0.224, 0.225)\n\n        self.session = onnxruntime.InferenceSession(args.model)\n        self.input_shape = tuple(map(int, args.input_shape.split(',')))\n\n        self.tracker = BYTETracker(args, frame_rate=30)\n\n    def _pre_process(self, image):\n        image_info = {'id': 0}\n\n        image_info['image'] = copy.deepcopy(image)\n        image_info['width'] = image.shape[1]\n        image_info['height'] = image.shape[0]\n\n        preprocessed_image, ratio = pre_process(\n            image,\n            self.input_shape,\n            self.rgb_means,\n            self.std,\n        )\n        image_info['ratio'] = ratio\n\n        return preprocessed_image, image_info\n\n    def inference(self, image):\n        image, image_info = self._pre_process(image)\n\n        input_name = self.session.get_inputs()[0].name\n        result = self.session.run(None, {input_name: image[None, :, :, :]})\n\n        dets = self._post_process(result, image_info)\n\n        bboxes, ids, scores = self._tracker_update(\n            dets,\n            image_info,\n        )\n\n        return image_info, bboxes, ids, scores\n\n    def _post_process(self, result, image_info):\n        predictions = post_process(\n            result[0],\n            self.input_shape,\n            p6=self.args.with_p6,\n        )\n        predictions = predictions[0]\n        boxes = predictions[:, :4]\n        scores = predictions[:, 4:5] * predictions[:, 5:]\n\n        boxes_xyxy = np.ones_like(boxes)\n        boxes_xyxy[:, 0] = boxes[:, 0] - boxes[:, 2] / 2.\n        boxes_xyxy[:, 1] = boxes[:, 1] - boxes[:, 3] / 2.\n        boxes_xyxy[:, 2] = boxes[:, 0] + boxes[:, 2] / 2.\n        boxes_xyxy[:, 3] = boxes[:, 1] + boxes[:, 3] / 2.\n        boxes_xyxy /= image_info['ratio']\n\n        dets = multiclass_nms(\n            boxes_xyxy,\n            scores,\n            nms_thr=self.args.nms_th,\n            score_thr=self.args.score_th,\n        )\n\n        return dets\n\n    def _tracker_update(self, dets, image_info):\n        online_targets = []\n        if dets is not None:\n            online_targets = self.tracker.update(\n                dets[:, :-1],\n                [image_info['height'], image_info['width']],\n                [image_info['height'], image_info['width']],\n            )\n\n        online_tlwhs = []\n        online_ids = []\n        online_scores = []\n        for online_target in online_targets:\n            tlwh = online_target.tlwh\n            track_id = online_target.track_id\n            vertical = tlwh[2] / tlwh[3] > 1.6\n            if tlwh[2] * tlwh[3] > self.args.min_box_area and not vertical:\n                online_tlwhs.append(tlwh)\n                online_ids.append(track_id)\n                online_scores.append(online_target.score)\n\n        return online_tlwhs, online_ids, online_scores\n"
  },
  {
    "path": "opencv/python/byte_tracker/tracker/basetrack.py",
    "content": "import numpy as np\nfrom collections import OrderedDict\n\n\nclass TrackState(object):\n    New = 0\n    Tracked = 1\n    Lost = 2\n    Removed = 3\n\n\nclass BaseTrack(object):\n    _count = 0\n\n    track_id = 0\n    is_activated = False\n    state = TrackState.New\n\n    history = OrderedDict()\n    features = []\n    curr_feature = None\n    score = 0\n    start_frame = 0\n    frame_id = 0\n    time_since_update = 0\n\n    # multi-camera\n    location = (np.inf, np.inf)\n\n    @property\n    def end_frame(self):\n        return self.frame_id\n\n    @staticmethod\n    def next_id():\n        BaseTrack._count += 1\n        return BaseTrack._count\n\n    def activate(self, *args):\n        raise NotImplementedError\n\n    def predict(self):\n        raise NotImplementedError\n\n    def update(self, *args, **kwargs):\n        raise NotImplementedError\n\n    def mark_lost(self):\n        self.state = TrackState.Lost\n\n    def mark_removed(self):\n        self.state = TrackState.Removed"
  },
  {
    "path": "opencv/python/byte_tracker/tracker/byte_tracker.py",
    "content": "import numpy as np\nfrom collections import deque\nimport os\nimport os.path as osp\nimport copy\nimport torch\nimport torch.nn.functional as F\n\nfrom .kalman_filter import KalmanFilter\nfrom byte_tracker.tracker import matching\nfrom .basetrack import BaseTrack, TrackState\n\nclass STrack(BaseTrack):\n    shared_kalman = KalmanFilter()\n    def __init__(self, tlwh, score):\n\n        # wait activate\n        self._tlwh = np.asarray(tlwh, dtype=np.float)\n        self.kalman_filter = None\n        self.mean, self.covariance = None, None\n        self.is_activated = False\n\n        self.score = score\n        self.tracklet_len = 0\n\n    def predict(self):\n        mean_state = self.mean.copy()\n        if self.state != TrackState.Tracked:\n            mean_state[7] = 0\n        self.mean, self.covariance = self.kalman_filter.predict(mean_state, self.covariance)\n\n    @staticmethod\n    def multi_predict(stracks):\n        if len(stracks) > 0:\n            multi_mean = np.asarray([st.mean.copy() for st in stracks])\n            multi_covariance = np.asarray([st.covariance for st in stracks])\n            for i, st in enumerate(stracks):\n                if st.state != TrackState.Tracked:\n                    multi_mean[i][7] = 0\n            multi_mean, multi_covariance = STrack.shared_kalman.multi_predict(multi_mean, multi_covariance)\n            for i, (mean, cov) in enumerate(zip(multi_mean, multi_covariance)):\n                stracks[i].mean = mean\n                stracks[i].covariance = cov\n\n    def activate(self, kalman_filter, frame_id):\n        \"\"\"Start a new tracklet\"\"\"\n        self.kalman_filter = kalman_filter\n        self.track_id = self.next_id()\n        self.mean, self.covariance = self.kalman_filter.initiate(self.tlwh_to_xyah(self._tlwh))\n\n        self.tracklet_len = 0\n        self.state = TrackState.Tracked\n        if frame_id == 1:\n            self.is_activated = True\n        # self.is_activated = True\n        self.frame_id = frame_id\n        self.start_frame = frame_id\n\n    def re_activate(self, new_track, frame_id, new_id=False):\n        self.mean, self.covariance = self.kalman_filter.update(\n            self.mean, self.covariance, self.tlwh_to_xyah(new_track.tlwh)\n        )\n        self.tracklet_len = 0\n        self.state = TrackState.Tracked\n        self.is_activated = True\n        self.frame_id = frame_id\n        if new_id:\n            self.track_id = self.next_id()\n        self.score = new_track.score\n\n    def update(self, new_track, frame_id):\n        \"\"\"\n        Update a matched track\n        :type new_track: STrack\n        :type frame_id: int\n        :type update_feature: bool\n        :return:\n        \"\"\"\n        self.frame_id = frame_id\n        self.tracklet_len += 1\n\n        new_tlwh = new_track.tlwh\n        self.mean, self.covariance = self.kalman_filter.update(\n            self.mean, self.covariance, self.tlwh_to_xyah(new_tlwh))\n        self.state = TrackState.Tracked\n        self.is_activated = True\n\n        self.score = new_track.score\n\n    @property\n    # @jit(nopython=True)\n    def tlwh(self):\n        \"\"\"Get current position in bounding box format `(top left x, top left y,\n                width, height)`.\n        \"\"\"\n        if self.mean is None:\n            return self._tlwh.copy()\n        ret = self.mean[:4].copy()\n        ret[2] *= ret[3]\n        ret[:2] -= ret[2:] / 2\n        return ret\n\n    @property\n    # @jit(nopython=True)\n    def tlbr(self):\n        \"\"\"Convert bounding box to format `(min x, min y, max x, max y)`, i.e.,\n        `(top left, bottom right)`.\n        \"\"\"\n        ret = self.tlwh.copy()\n        ret[2:] += ret[:2]\n        return ret\n\n    @staticmethod\n    # @jit(nopython=True)\n    def tlwh_to_xyah(tlwh):\n        \"\"\"Convert bounding box to format `(center x, center y, aspect ratio,\n        height)`, where the aspect ratio is `width / height`.\n        \"\"\"\n        ret = np.asarray(tlwh).copy()\n        ret[:2] += ret[2:] / 2\n        ret[2] /= ret[3]\n        return ret\n\n    def to_xyah(self):\n        return self.tlwh_to_xyah(self.tlwh)\n\n    @staticmethod\n    # @jit(nopython=True)\n    def tlbr_to_tlwh(tlbr):\n        ret = np.asarray(tlbr).copy()\n        ret[2:] -= ret[:2]\n        return ret\n\n    @staticmethod\n    # @jit(nopython=True)\n    def tlwh_to_tlbr(tlwh):\n        ret = np.asarray(tlwh).copy()\n        ret[2:] += ret[:2]\n        return ret\n\n    def __repr__(self):\n        return 'OT_{}_({}-{})'.format(self.track_id, self.start_frame, self.end_frame)\n\n\nclass BYTETracker(object):\n    def __init__(self, args, frame_rate=30):\n        self.tracked_stracks = []  # type: list[STrack]\n        self.lost_stracks = []  # type: list[STrack]\n        self.removed_stracks = []  # type: list[STrack]\n\n        self.frame_id = 0\n        self.args = args\n        #self.det_thresh = args.track_thresh\n        self.det_thresh = args.track_thresh + 0.1\n        self.buffer_size = int(frame_rate / 30.0 * args.track_buffer)\n        self.max_time_lost = self.buffer_size\n        self.kalman_filter = KalmanFilter()\n\n    def update(self, output_results, img_info, img_size):\n        self.frame_id += 1\n        activated_starcks = []\n        refind_stracks = []\n        lost_stracks = []\n        removed_stracks = []\n\n        if output_results.shape[1] == 5:\n            scores = output_results[:, 4]\n            bboxes = output_results[:, :4]\n        else:\n            output_results = output_results.cpu().numpy()\n            scores = output_results[:, 4] * output_results[:, 5]\n            bboxes = output_results[:, :4]  # x1y1x2y2\n        img_h, img_w = img_info[0], img_info[1]\n        scale = min(img_size[0] / float(img_h), img_size[1] / float(img_w))\n        bboxes /= scale\n\n        remain_inds = scores > self.args.track_thresh\n        inds_low = scores > 0.1\n        inds_high = scores < self.args.track_thresh\n\n        inds_second = np.logical_and(inds_low, inds_high)\n        dets_second = bboxes[inds_second]\n        dets = bboxes[remain_inds]\n        scores_keep = scores[remain_inds]\n        scores_second = scores[inds_second]\n\n        if len(dets) > 0:\n            '''Detections'''\n            detections = [STrack(STrack.tlbr_to_tlwh(tlbr), s) for\n                          (tlbr, s) in zip(dets, scores_keep)]\n        else:\n            detections = []\n\n        ''' Add newly detected tracklets to tracked_stracks'''\n        unconfirmed = []\n        tracked_stracks = []  # type: list[STrack]\n        for track in self.tracked_stracks:\n            if not track.is_activated:\n                unconfirmed.append(track)\n            else:\n                tracked_stracks.append(track)\n\n        ''' Step 2: First association, with high score detection boxes'''\n        strack_pool = joint_stracks(tracked_stracks, self.lost_stracks)\n        # Predict the current location with KF\n        STrack.multi_predict(strack_pool)\n        dists = matching.iou_distance(strack_pool, detections)\n        if not self.args.mot20:\n            dists = matching.fuse_score(dists, detections)\n        matches, u_track, u_detection = matching.linear_assignment(dists, thresh=self.args.match_thresh)\n\n        for itracked, idet in matches:\n            track = strack_pool[itracked]\n            det = detections[idet]\n            if track.state == TrackState.Tracked:\n                track.update(detections[idet], self.frame_id)\n                activated_starcks.append(track)\n            else:\n                track.re_activate(det, self.frame_id, new_id=False)\n                refind_stracks.append(track)\n\n        ''' Step 3: Second association, with low score detection boxes'''\n        # association the untrack to the low score detections\n        if len(dets_second) > 0:\n            '''Detections'''\n            detections_second = [STrack(STrack.tlbr_to_tlwh(tlbr), s) for\n                          (tlbr, s) in zip(dets_second, scores_second)]\n        else:\n            detections_second = []\n        r_tracked_stracks = [strack_pool[i] for i in u_track if strack_pool[i].state == TrackState.Tracked]\n        dists = matching.iou_distance(r_tracked_stracks, detections_second)\n        matches, u_track, u_detection_second = matching.linear_assignment(dists, thresh=0.5)\n        for itracked, idet in matches:\n            track = r_tracked_stracks[itracked]\n            det = detections_second[idet]\n            if track.state == TrackState.Tracked:\n                track.update(det, self.frame_id)\n                activated_starcks.append(track)\n            else:\n                track.re_activate(det, self.frame_id, new_id=False)\n                refind_stracks.append(track)\n\n        for it in u_track:\n            track = r_tracked_stracks[it]\n            if not track.state == TrackState.Lost:\n                track.mark_lost()\n                lost_stracks.append(track)\n\n        '''Deal with unconfirmed tracks, usually tracks with only one beginning frame'''\n        detections = [detections[i] for i in u_detection]\n        dists = matching.iou_distance(unconfirmed, detections)\n        if not self.args.mot20:\n            dists = matching.fuse_score(dists, detections)\n        matches, u_unconfirmed, u_detection = matching.linear_assignment(dists, thresh=0.7)\n        for itracked, idet in matches:\n            unconfirmed[itracked].update(detections[idet], self.frame_id)\n            activated_starcks.append(unconfirmed[itracked])\n        for it in u_unconfirmed:\n            track = unconfirmed[it]\n            track.mark_removed()\n            removed_stracks.append(track)\n\n        \"\"\" Step 4: Init new stracks\"\"\"\n        for inew in u_detection:\n            track = detections[inew]\n            if track.score < self.det_thresh:\n                continue\n            track.activate(self.kalman_filter, self.frame_id)\n            activated_starcks.append(track)\n        \"\"\" Step 5: Update state\"\"\"\n        for track in self.lost_stracks:\n            if self.frame_id - track.end_frame > self.max_time_lost:\n                track.mark_removed()\n                removed_stracks.append(track)\n\n        # print('Ramained match {} s'.format(t4-t3))\n\n        self.tracked_stracks = [t for t in self.tracked_stracks if t.state == TrackState.Tracked]\n        self.tracked_stracks = joint_stracks(self.tracked_stracks, activated_starcks)\n        self.tracked_stracks = joint_stracks(self.tracked_stracks, refind_stracks)\n        self.lost_stracks = sub_stracks(self.lost_stracks, self.tracked_stracks)\n        self.lost_stracks.extend(lost_stracks)\n        self.lost_stracks = sub_stracks(self.lost_stracks, self.removed_stracks)\n        self.removed_stracks.extend(removed_stracks)\n        self.tracked_stracks, self.lost_stracks = remove_duplicate_stracks(self.tracked_stracks, self.lost_stracks)\n        # get scores of lost tracks\n        output_stracks = [track for track in self.tracked_stracks if track.is_activated]\n\n        return output_stracks\n\n\ndef joint_stracks(tlista, tlistb):\n    exists = {}\n    res = []\n    for t in tlista:\n        exists[t.track_id] = 1\n        res.append(t)\n    for t in tlistb:\n        tid = t.track_id\n        if not exists.get(tid, 0):\n            exists[tid] = 1\n            res.append(t)\n    return res\n\n\ndef sub_stracks(tlista, tlistb):\n    stracks = {}\n    for t in tlista:\n        stracks[t.track_id] = t\n    for t in tlistb:\n        tid = t.track_id\n        if stracks.get(tid, 0):\n            del stracks[tid]\n    return list(stracks.values())\n\n\ndef remove_duplicate_stracks(stracksa, stracksb):\n    pdist = matching.iou_distance(stracksa, stracksb)\n    pairs = np.where(pdist < 0.15)\n    dupa, dupb = list(), list()\n    for p, q in zip(*pairs):\n        timep = stracksa[p].frame_id - stracksa[p].start_frame\n        timeq = stracksb[q].frame_id - stracksb[q].start_frame\n        if timep > timeq:\n            dupb.append(q)\n        else:\n            dupa.append(p)\n    resa = [t for i, t in enumerate(stracksa) if not i in dupa]\n    resb = [t for i, t in enumerate(stracksb) if not i in dupb]\n    return resa, resb\n"
  },
  {
    "path": "opencv/python/byte_tracker/tracker/kalman_filter.py",
    "content": "# vim: expandtab:ts=4:sw=4\nimport numpy as np\nimport scipy.linalg\n\n\n\"\"\"\nTable for the 0.95 quantile of the chi-square distribution with N degrees of\nfreedom (contains values for N=1, ..., 9). Taken from MATLAB/Octave's chi2inv\nfunction and used as Mahalanobis gating threshold.\n\"\"\"\nchi2inv95 = {\n    1: 3.8415,\n    2: 5.9915,\n    3: 7.8147,\n    4: 9.4877,\n    5: 11.070,\n    6: 12.592,\n    7: 14.067,\n    8: 15.507,\n    9: 16.919}\n\n\nclass KalmanFilter(object):\n    \"\"\"\n    A simple Kalman filter for tracking bounding boxes in image space.\n\n    The 8-dimensional state space\n\n        x, y, a, h, vx, vy, va, vh\n\n    contains the bounding box center position (x, y), aspect ratio a, height h,\n    and their respective velocities.\n\n    Object motion follows a constant velocity model. The bounding box location\n    (x, y, a, h) is taken as direct observation of the state space (linear\n    observation model).\n\n    \"\"\"\n\n    def __init__(self):\n        ndim, dt = 4, 1.\n\n        # Create Kalman filter model matrices.\n        self._motion_mat = np.eye(2 * ndim, 2 * ndim)\n        for i in range(ndim):\n            self._motion_mat[i, ndim + i] = dt\n        self._update_mat = np.eye(ndim, 2 * ndim)\n\n        # Motion and observation uncertainty are chosen relative to the current\n        # state estimate. These weights control the amount of uncertainty in\n        # the model. This is a bit hacky.\n        self._std_weight_position = 1. / 20\n        self._std_weight_velocity = 1. / 160\n\n    def initiate(self, measurement):\n        \"\"\"Create track from unassociated measurement.\n\n        Parameters\n        ----------\n        measurement : ndarray\n            Bounding box coordinates (x, y, a, h) with center position (x, y),\n            aspect ratio a, and height h.\n\n        Returns\n        -------\n        (ndarray, ndarray)\n            Returns the mean vector (8 dimensional) and covariance matrix (8x8\n            dimensional) of the new track. Unobserved velocities are initialized\n            to 0 mean.\n\n        \"\"\"\n        mean_pos = measurement\n        mean_vel = np.zeros_like(mean_pos)\n        mean = np.r_[mean_pos, mean_vel]\n\n        std = [\n            2 * self._std_weight_position * measurement[3],\n            2 * self._std_weight_position * measurement[3],\n            1e-2,\n            2 * self._std_weight_position * measurement[3],\n            10 * self._std_weight_velocity * measurement[3],\n            10 * self._std_weight_velocity * measurement[3],\n            1e-5,\n            10 * self._std_weight_velocity * measurement[3]]\n        covariance = np.diag(np.square(std))\n        return mean, covariance\n\n    def predict(self, mean, covariance):\n        \"\"\"Run Kalman filter prediction step.\n\n        Parameters\n        ----------\n        mean : ndarray\n            The 8 dimensional mean vector of the object state at the previous\n            time step.\n        covariance : ndarray\n            The 8x8 dimensional covariance matrix of the object state at the\n            previous time step.\n\n        Returns\n        -------\n        (ndarray, ndarray)\n            Returns the mean vector and covariance matrix of the predicted\n            state. Unobserved velocities are initialized to 0 mean.\n\n        \"\"\"\n        std_pos = [\n            self._std_weight_position * mean[3],\n            self._std_weight_position * mean[3],\n            1e-2,\n            self._std_weight_position * mean[3]]\n        std_vel = [\n            self._std_weight_velocity * mean[3],\n            self._std_weight_velocity * mean[3],\n            1e-5,\n            self._std_weight_velocity * mean[3]]\n        motion_cov = np.diag(np.square(np.r_[std_pos, std_vel]))\n\n        #mean = np.dot(self._motion_mat, mean)\n        mean = np.dot(mean, self._motion_mat.T)\n        covariance = np.linalg.multi_dot((\n            self._motion_mat, covariance, self._motion_mat.T)) + motion_cov\n\n        return mean, covariance\n\n    def project(self, mean, covariance):\n        \"\"\"Project state distribution to measurement space.\n\n        Parameters\n        ----------\n        mean : ndarray\n            The state's mean vector (8 dimensional array).\n        covariance : ndarray\n            The state's covariance matrix (8x8 dimensional).\n\n        Returns\n        -------\n        (ndarray, ndarray)\n            Returns the projected mean and covariance matrix of the given state\n            estimate.\n\n        \"\"\"\n        std = [\n            self._std_weight_position * mean[3],\n            self._std_weight_position * mean[3],\n            1e-1,\n            self._std_weight_position * mean[3]]\n        innovation_cov = np.diag(np.square(std))\n\n        mean = np.dot(self._update_mat, mean)\n        covariance = np.linalg.multi_dot((\n            self._update_mat, covariance, self._update_mat.T))\n        return mean, covariance + innovation_cov\n\n    def multi_predict(self, mean, covariance):\n        \"\"\"Run Kalman filter prediction step (Vectorized version).\n        Parameters\n        ----------\n        mean : ndarray\n            The Nx8 dimensional mean matrix of the object states at the previous\n            time step.\n        covariance : ndarray\n            The Nx8x8 dimensional covariance matrics of the object states at the\n            previous time step.\n        Returns\n        -------\n        (ndarray, ndarray)\n            Returns the mean vector and covariance matrix of the predicted\n            state. Unobserved velocities are initialized to 0 mean.\n        \"\"\"\n        std_pos = [\n            self._std_weight_position * mean[:, 3],\n            self._std_weight_position * mean[:, 3],\n            1e-2 * np.ones_like(mean[:, 3]),\n            self._std_weight_position * mean[:, 3]]\n        std_vel = [\n            self._std_weight_velocity * mean[:, 3],\n            self._std_weight_velocity * mean[:, 3],\n            1e-5 * np.ones_like(mean[:, 3]),\n            self._std_weight_velocity * mean[:, 3]]\n        sqr = np.square(np.r_[std_pos, std_vel]).T\n\n        motion_cov = []\n        for i in range(len(mean)):\n            motion_cov.append(np.diag(sqr[i]))\n        motion_cov = np.asarray(motion_cov)\n\n        mean = np.dot(mean, self._motion_mat.T)\n        left = np.dot(self._motion_mat, covariance).transpose((1, 0, 2))\n        covariance = np.dot(left, self._motion_mat.T) + motion_cov\n\n        return mean, covariance\n\n    def update(self, mean, covariance, measurement):\n        \"\"\"Run Kalman filter correction step.\n\n        Parameters\n        ----------\n        mean : ndarray\n            The predicted state's mean vector (8 dimensional).\n        covariance : ndarray\n            The state's covariance matrix (8x8 dimensional).\n        measurement : ndarray\n            The 4 dimensional measurement vector (x, y, a, h), where (x, y)\n            is the center position, a the aspect ratio, and h the height of the\n            bounding box.\n\n        Returns\n        -------\n        (ndarray, ndarray)\n            Returns the measurement-corrected state distribution.\n\n        \"\"\"\n        projected_mean, projected_cov = self.project(mean, covariance)\n\n        chol_factor, lower = scipy.linalg.cho_factor(\n            projected_cov, lower=True, check_finite=False)\n        kalman_gain = scipy.linalg.cho_solve(\n            (chol_factor, lower), np.dot(covariance, self._update_mat.T).T,\n            check_finite=False).T\n        innovation = measurement - projected_mean\n\n        new_mean = mean + np.dot(innovation, kalman_gain.T)\n        new_covariance = covariance - np.linalg.multi_dot((\n            kalman_gain, projected_cov, kalman_gain.T))\n        return new_mean, new_covariance\n\n    def gating_distance(self, mean, covariance, measurements,\n                        only_position=False, metric='maha'):\n        \"\"\"Compute gating distance between state distribution and measurements.\n        A suitable distance threshold can be obtained from `chi2inv95`. If\n        `only_position` is False, the chi-square distribution has 4 degrees of\n        freedom, otherwise 2.\n        Parameters\n        ----------\n        mean : ndarray\n            Mean vector over the state distribution (8 dimensional).\n        covariance : ndarray\n            Covariance of the state distribution (8x8 dimensional).\n        measurements : ndarray\n            An Nx4 dimensional matrix of N measurements, each in\n            format (x, y, a, h) where (x, y) is the bounding box center\n            position, a the aspect ratio, and h the height.\n        only_position : Optional[bool]\n            If True, distance computation is done with respect to the bounding\n            box center position only.\n        Returns\n        -------\n        ndarray\n            Returns an array of length N, where the i-th element contains the\n            squared Mahalanobis distance between (mean, covariance) and\n            `measurements[i]`.\n        \"\"\"\n        mean, covariance = self.project(mean, covariance)\n        if only_position:\n            mean, covariance = mean[:2], covariance[:2, :2]\n            measurements = measurements[:, :2]\n\n        d = measurements - mean\n        if metric == 'gaussian':\n            return np.sum(d * d, axis=1)\n        elif metric == 'maha':\n            cholesky_factor = np.linalg.cholesky(covariance)\n            z = scipy.linalg.solve_triangular(\n                cholesky_factor, d.T, lower=True, check_finite=False,\n                overwrite_b=True)\n            squared_maha = np.sum(z * z, axis=0)\n            return squared_maha\n        else:\n            raise ValueError('invalid distance metric')"
  },
  {
    "path": "opencv/python/byte_tracker/tracker/matching.py",
    "content": "import cv2\nimport numpy as np\nimport scipy\nimport lap\nfrom scipy.spatial.distance import cdist\n\nfrom cython_bbox import bbox_overlaps as bbox_ious\nfrom byte_tracker.tracker import kalman_filter\nimport time\n\ndef merge_matches(m1, m2, shape):\n    O,P,Q = shape\n    m1 = np.asarray(m1)\n    m2 = np.asarray(m2)\n\n    M1 = scipy.sparse.coo_matrix((np.ones(len(m1)), (m1[:, 0], m1[:, 1])), shape=(O, P))\n    M2 = scipy.sparse.coo_matrix((np.ones(len(m2)), (m2[:, 0], m2[:, 1])), shape=(P, Q))\n\n    mask = M1*M2\n    match = mask.nonzero()\n    match = list(zip(match[0], match[1]))\n    unmatched_O = tuple(set(range(O)) - set([i for i, j in match]))\n    unmatched_Q = tuple(set(range(Q)) - set([j for i, j in match]))\n\n    return match, unmatched_O, unmatched_Q\n\n\ndef _indices_to_matches(cost_matrix, indices, thresh):\n    matched_cost = cost_matrix[tuple(zip(*indices))]\n    matched_mask = (matched_cost <= thresh)\n\n    matches = indices[matched_mask]\n    unmatched_a = tuple(set(range(cost_matrix.shape[0])) - set(matches[:, 0]))\n    unmatched_b = tuple(set(range(cost_matrix.shape[1])) - set(matches[:, 1]))\n\n    return matches, unmatched_a, unmatched_b\n\n\ndef linear_assignment(cost_matrix, thresh):\n    if cost_matrix.size == 0:\n        return np.empty((0, 2), dtype=int), tuple(range(cost_matrix.shape[0])), tuple(range(cost_matrix.shape[1]))\n    matches, unmatched_a, unmatched_b = [], [], []\n    cost, x, y = lap.lapjv(cost_matrix, extend_cost=True, cost_limit=thresh)\n    for ix, mx in enumerate(x):\n        if mx >= 0:\n            matches.append([ix, mx])\n    unmatched_a = np.where(x < 0)[0]\n    unmatched_b = np.where(y < 0)[0]\n    matches = np.asarray(matches)\n    return matches, unmatched_a, unmatched_b\n\n\ndef ious(atlbrs, btlbrs):\n    \"\"\"\n    Compute cost based on IoU\n    :type atlbrs: list[tlbr] | np.ndarray\n    :type atlbrs: list[tlbr] | np.ndarray\n\n    :rtype ious np.ndarray\n    \"\"\"\n    ious = np.zeros((len(atlbrs), len(btlbrs)), dtype=np.float)\n    if ious.size == 0:\n        return ious\n\n    ious = bbox_ious(\n        np.ascontiguousarray(atlbrs, dtype=np.float),\n        np.ascontiguousarray(btlbrs, dtype=np.float)\n    )\n\n    return ious\n\n\ndef iou_distance(atracks, btracks):\n    \"\"\"\n    Compute cost based on IoU\n    :type atracks: list[STrack]\n    :type btracks: list[STrack]\n\n    :rtype cost_matrix np.ndarray\n    \"\"\"\n\n    if (len(atracks)>0 and isinstance(atracks[0], np.ndarray)) or (len(btracks) > 0 and isinstance(btracks[0], np.ndarray)):\n        atlbrs = atracks\n        btlbrs = btracks\n    else:\n        atlbrs = [track.tlbr for track in atracks]\n        btlbrs = [track.tlbr for track in btracks]\n    _ious = ious(atlbrs, btlbrs)\n    cost_matrix = 1 - _ious\n\n    return cost_matrix\n\ndef v_iou_distance(atracks, btracks):\n    \"\"\"\n    Compute cost based on IoU\n    :type atracks: list[STrack]\n    :type btracks: list[STrack]\n\n    :rtype cost_matrix np.ndarray\n    \"\"\"\n\n    if (len(atracks)>0 and isinstance(atracks[0], np.ndarray)) or (len(btracks) > 0 and isinstance(btracks[0], np.ndarray)):\n        atlbrs = atracks\n        btlbrs = btracks\n    else:\n        atlbrs = [track.tlwh_to_tlbr(track.pred_bbox) for track in atracks]\n        btlbrs = [track.tlwh_to_tlbr(track.pred_bbox) for track in btracks]\n    _ious = ious(atlbrs, btlbrs)\n    cost_matrix = 1 - _ious\n\n    return cost_matrix\n\ndef embedding_distance(tracks, detections, metric='cosine'):\n    \"\"\"\n    :param tracks: list[STrack]\n    :param detections: list[BaseTrack]\n    :param metric:\n    :return: cost_matrix np.ndarray\n    \"\"\"\n\n    cost_matrix = np.zeros((len(tracks), len(detections)), dtype=np.float)\n    if cost_matrix.size == 0:\n        return cost_matrix\n    det_features = np.asarray([track.curr_feat for track in detections], dtype=np.float)\n    #for i, track in enumerate(tracks):\n        #cost_matrix[i, :] = np.maximum(0.0, cdist(track.smooth_feat.reshape(1,-1), det_features, metric))\n    track_features = np.asarray([track.smooth_feat for track in tracks], dtype=np.float)\n    cost_matrix = np.maximum(0.0, cdist(track_features, det_features, metric))  # Nomalized features\n    return cost_matrix\n\n\ndef gate_cost_matrix(kf, cost_matrix, tracks, detections, only_position=False):\n    if cost_matrix.size == 0:\n        return cost_matrix\n    gating_dim = 2 if only_position else 4\n    gating_threshold = kalman_filter.chi2inv95[gating_dim]\n    measurements = np.asarray([det.to_xyah() for det in detections])\n    for row, track in enumerate(tracks):\n        gating_distance = kf.gating_distance(\n            track.mean, track.covariance, measurements, only_position)\n        cost_matrix[row, gating_distance > gating_threshold] = np.inf\n    return cost_matrix\n\n\ndef fuse_motion(kf, cost_matrix, tracks, detections, only_position=False, lambda_=0.98):\n    if cost_matrix.size == 0:\n        return cost_matrix\n    gating_dim = 2 if only_position else 4\n    gating_threshold = kalman_filter.chi2inv95[gating_dim]\n    measurements = np.asarray([det.to_xyah() for det in detections])\n    for row, track in enumerate(tracks):\n        gating_distance = kf.gating_distance(\n            track.mean, track.covariance, measurements, only_position, metric='maha')\n        cost_matrix[row, gating_distance > gating_threshold] = np.inf\n        cost_matrix[row] = lambda_ * cost_matrix[row] + (1 - lambda_) * gating_distance\n    return cost_matrix\n\n\ndef fuse_iou(cost_matrix, tracks, detections):\n    if cost_matrix.size == 0:\n        return cost_matrix\n    reid_sim = 1 - cost_matrix\n    iou_dist = iou_distance(tracks, detections)\n    iou_sim = 1 - iou_dist\n    fuse_sim = reid_sim * (1 + iou_sim) / 2\n    det_scores = np.array([det.score for det in detections])\n    det_scores = np.expand_dims(det_scores, axis=0).repeat(cost_matrix.shape[0], axis=0)\n    #fuse_sim = fuse_sim * (1 + det_scores) / 2\n    fuse_cost = 1 - fuse_sim\n    return fuse_cost\n\n\ndef fuse_score(cost_matrix, detections):\n    if cost_matrix.size == 0:\n        return cost_matrix\n    iou_sim = 1 - cost_matrix\n    det_scores = np.array([det.score for det in detections])\n    det_scores = np.expand_dims(det_scores, axis=0).repeat(cost_matrix.shape[0], axis=0)\n    fuse_sim = iou_sim * det_scores\n    fuse_cost = 1 - fuse_sim\n    return fuse_cost"
  },
  {
    "path": "opencv/python/byte_tracker/utils/yolox_utils.py",
    "content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\nimport cv2\nimport numpy as np\n\n\ndef nms(boxes, scores, nms_thr):\n    \"\"\"Single class NMS implemented in Numpy.\"\"\"\n    x1 = boxes[:, 0]\n    y1 = boxes[:, 1]\n    x2 = boxes[:, 2]\n    y2 = boxes[:, 3]\n\n    areas = (x2 - x1 + 1) * (y2 - y1 + 1)\n    order = scores.argsort()[::-1]\n\n    keep = []\n    while order.size > 0:\n        i = order[0]\n        keep.append(i)\n        xx1 = np.maximum(x1[i], x1[order[1:]])\n        yy1 = np.maximum(y1[i], y1[order[1:]])\n        xx2 = np.minimum(x2[i], x2[order[1:]])\n        yy2 = np.minimum(y2[i], y2[order[1:]])\n\n        w = np.maximum(0.0, xx2 - xx1 + 1)\n        h = np.maximum(0.0, yy2 - yy1 + 1)\n        inter = w * h\n        ovr = inter / (areas[i] + areas[order[1:]] - inter)\n\n        inds = np.where(ovr <= nms_thr)[0]\n        order = order[inds + 1]\n\n    return keep\n\n\ndef multiclass_nms(boxes, scores, nms_thr, score_thr):\n    \"\"\"Multiclass NMS implemented in Numpy\"\"\"\n    final_dets = []\n    num_classes = scores.shape[1]\n    for cls_ind in range(num_classes):\n        cls_scores = scores[:, cls_ind]\n        valid_score_mask = cls_scores > score_thr\n        if valid_score_mask.sum() == 0:\n            continue\n        else:\n            valid_scores = cls_scores[valid_score_mask]\n            valid_boxes = boxes[valid_score_mask]\n            keep = nms(valid_boxes, valid_scores, nms_thr)\n            if len(keep) > 0:\n                cls_inds = np.ones((len(keep), 1)) * cls_ind\n                dets = np.concatenate(\n                    [valid_boxes[keep], valid_scores[keep, None], cls_inds], 1)\n                final_dets.append(dets)\n    if len(final_dets) == 0:\n        return None\n    return np.concatenate(final_dets, 0)\n\n\ndef pre_process(image, input_size, mean, std, swap=(2, 0, 1)):\n    if len(image.shape) == 3:\n        padded_img = np.ones((input_size[0], input_size[1], 3)) * 114.0\n    else:\n        padded_img = np.ones(input_size) * 114.0\n    img = np.array(image)\n    r = min(input_size[0] / img.shape[0], input_size[1] / img.shape[1])\n    resized_img = cv2.resize(\n        img,\n        (int(img.shape[1] * r), int(img.shape[0] * r)),\n        interpolation=cv2.INTER_LINEAR,\n    ).astype(np.float32)\n    padded_img[:int(img.shape[0] * r), :int(img.shape[1] * r)] = resized_img\n\n    padded_img = padded_img[:, :, ::-1]\n    padded_img /= 255.0\n    if mean is not None:\n        padded_img -= mean\n    if std is not None:\n        padded_img /= std\n    padded_img = padded_img.transpose(swap)\n    padded_img = np.ascontiguousarray(padded_img, dtype=np.float32)\n    return padded_img, r\n\n\ndef post_process(outputs, img_size, p6=False):\n    grids = []\n    expanded_strides = []\n\n    if not p6:\n        strides = [8, 16, 32]\n    else:\n        strides = [8, 16, 32, 64]\n\n    hsizes = [img_size[0] // stride for stride in strides]\n    wsizes = [img_size[1] // stride for stride in strides]\n\n    for hsize, wsize, stride in zip(hsizes, wsizes, strides):\n        xv, yv = np.meshgrid(np.arange(wsize), np.arange(hsize))\n        grid = np.stack((xv, yv), 2).reshape(1, -1, 2)\n        grids.append(grid)\n        shape = grid.shape[:2]\n        expanded_strides.append(np.full((*shape, 1), stride))\n\n    grids = np.concatenate(grids, 1)\n    expanded_strides = np.concatenate(expanded_strides, 1)\n    outputs[..., :2] = (outputs[..., :2] + grids) * expanded_strides\n    outputs[..., 2:4] = np.exp(outputs[..., 2:4]) * expanded_strides\n\n    return outputs\n"
  },
  {
    "path": "opencv/python/main.py",
    "content": "import os\r\nimport copy\r\nimport time\r\nimport argparse\r\nimport cv2\r\nfrom loguru import logger\r\nimport numpy as np\r\nfrom byte_tracker.utils.yolox_utils import (\r\n    post_process,\r\n    multiclass_nms,\r\n)\r\nfrom byte_tracker.tracker.byte_tracker import BYTETracker\r\n\r\ndef pre_process(image, input_size, mean, std):\r\n    if len(image.shape) == 3:\r\n        padded_img = np.ones((input_size[0], input_size[1], 3)) * 114.0\r\n    else:\r\n        padded_img = np.ones(input_size) * 114.0\r\n    img = np.array(image)\r\n    r = min(input_size[0] / img.shape[0], input_size[1] / img.shape[1])\r\n    resized_img = cv2.resize(\r\n        img,\r\n        (int(img.shape[1] * r), int(img.shape[0] * r)),\r\n        interpolation=cv2.INTER_LINEAR,\r\n    ).astype(np.float32)\r\n    padded_img[:int(img.shape[0] * r), :int(img.shape[1] * r)] = resized_img\r\n\r\n    padded_img = padded_img[:, :, ::-1]\r\n    padded_img /= 255.0\r\n    if mean is not None:\r\n        padded_img -= mean\r\n    if std is not None:\r\n        padded_img /= std\r\n    padded_img = np.ascontiguousarray(padded_img, dtype=np.float32)\r\n    return padded_img, r\r\n\r\nclass ByteTracker(object):\r\n    def __init__(self, args):\r\n        self.args = args\r\n\r\n        self.rgb_means = (0.485, 0.456, 0.406)\r\n        self.std = (0.229, 0.224, 0.225)\r\n\r\n        self.net = cv2.dnn.readNet(args.model)\r\n        self.input_shape = tuple(map(int, args.input_shape.split(',')))\r\n\r\n        self.tracker = BYTETracker(args, frame_rate=30)\r\n\r\n    def _pre_process(self, image):\r\n        image_info = {'id': 0}\r\n\r\n        image_info['image'] = copy.deepcopy(image)\r\n        image_info['width'] = image.shape[1]\r\n        image_info['height'] = image.shape[0]\r\n\r\n        preprocessed_image, ratio = pre_process(\r\n            image,\r\n            self.input_shape,\r\n            self.rgb_means,\r\n            self.std,\r\n        )\r\n        image_info['ratio'] = ratio\r\n\r\n        return preprocessed_image, image_info\r\n\r\n    def inference(self, image):\r\n        image, image_info = self._pre_process(image)\r\n\r\n        blob = cv2.dnn.blobFromImage(image)\r\n        self.net.setInput(blob)\r\n        result = self.net.forward()\r\n\r\n        dets = self._post_process(result, image_info)\r\n\r\n        bboxes, ids, scores = self._tracker_update(\r\n            dets,\r\n            image_info,\r\n        )\r\n\r\n        return image_info, bboxes, ids, scores\r\n\r\n    def _post_process(self, result, image_info):\r\n        predictions = post_process(\r\n            result,\r\n            self.input_shape,\r\n            p6=self.args.with_p6,\r\n        )\r\n        predictions = predictions[0]\r\n        boxes = predictions[:, :4]\r\n        scores = predictions[:, 4:5] * predictions[:, 5:]\r\n\r\n        boxes_xyxy = np.ones_like(boxes)\r\n        boxes_xyxy[:, 0] = boxes[:, 0] - boxes[:, 2] / 2.\r\n        boxes_xyxy[:, 1] = boxes[:, 1] - boxes[:, 3] / 2.\r\n        boxes_xyxy[:, 2] = boxes[:, 0] + boxes[:, 2] / 2.\r\n        boxes_xyxy[:, 3] = boxes[:, 1] + boxes[:, 3] / 2.\r\n        boxes_xyxy /= image_info['ratio']\r\n\r\n        dets = multiclass_nms(\r\n            boxes_xyxy,\r\n            scores,\r\n            nms_thr=self.args.nms_th,\r\n            score_thr=self.args.score_th,\r\n        )\r\n\r\n        return dets\r\n\r\n    def _tracker_update(self, dets, image_info):\r\n        online_targets = []\r\n        if dets is not None:\r\n            online_targets = self.tracker.update(\r\n                dets[:, :-1],\r\n                [image_info['height'], image_info['width']],\r\n                [image_info['height'], image_info['width']],\r\n            )\r\n\r\n        online_tlwhs = []\r\n        online_ids = []\r\n        online_scores = []\r\n        for online_target in online_targets:\r\n            tlwh = online_target.tlwh\r\n            track_id = online_target.track_id\r\n            vertical = tlwh[2] / tlwh[3] > 1.6\r\n            if tlwh[2] * tlwh[3] > self.args.min_box_area and not vertical:\r\n                online_tlwhs.append(tlwh)\r\n                online_ids.append(track_id)\r\n                online_scores.append(online_target.score)\r\n\r\n        return online_tlwhs, online_ids, online_scores\r\n\r\n\r\ndef get_args():\r\n    parser = argparse.ArgumentParser()\r\n\r\n    parser.add_argument(\r\n        '--use_debug_window',\r\n        action='store_true',\r\n    )\r\n\r\n    parser.add_argument(\r\n        '--model',\r\n        type=str,\r\n        default='byte_tracker/model/bytetrack_s.onnx',\r\n    )\r\n    parser.add_argument(\r\n        '--video',\r\n        type=str,\r\n        default='sample.mp4',\r\n    )\r\n    parser.add_argument(\r\n        '--output_dir',\r\n        type=str,\r\n        default='output',\r\n    )\r\n    parser.add_argument(\r\n        '--score_th',\r\n        type=float,\r\n        default=0.1,\r\n    )\r\n    parser.add_argument(\r\n        '--nms_th',\r\n        type=float,\r\n        default=0.7,\r\n    )\r\n    parser.add_argument(\r\n        '--input_shape',\r\n        type=str,\r\n        default='608,1088',\r\n    )\r\n    parser.add_argument(\r\n        '--with_p6',\r\n        action='store_true',\r\n        help='Whether your model uses p6 in FPN/PAN.',\r\n    )\r\n\r\n    # tracking args\r\n    parser.add_argument(\r\n        '--track_thresh',\r\n        type=float,\r\n        default=0.5,\r\n        help='tracking confidence threshold',\r\n    )\r\n    parser.add_argument(\r\n        '--track_buffer',\r\n        type=int,\r\n        default=30,\r\n        help='the frames for keep lost tracks',\r\n    )\r\n    parser.add_argument(\r\n        '--match_thresh',\r\n        type=float,\r\n        default=0.8,\r\n        help='matching threshold for tracking',\r\n    )\r\n    parser.add_argument(\r\n        '--min-box-area',\r\n        type=float,\r\n        default=10,\r\n        help='filter out tiny boxes',\r\n    )\r\n    parser.add_argument(\r\n        '--mot20',\r\n        dest='mot20',\r\n        default=False,\r\n        action='store_true',\r\n        help='test mot20.',\r\n    )\r\n\r\n    args = parser.parse_args()\r\n\r\n    return args\r\n\r\n\r\ndef main():\r\n    args = get_args()\r\n\r\n    use_debug_window = args.use_debug_window\r\n\r\n    video_path = args.video\r\n    output_dir = args.output_dir\r\n\r\n    byte_tracker = ByteTracker(args)\r\n\r\n    cap = cv2.VideoCapture(video_path)\r\n    width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)\r\n    height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)\r\n    fps = cap.get(cv2.CAP_PROP_FPS)\r\n    frame_count = cap.get(cv2.CAP_PROP_FRAME_COUNT)\r\n\r\n    if not use_debug_window:\r\n        os.makedirs(output_dir, exist_ok=True)\r\n        save_path = os.path.join(output_dir, video_path.split(\"/\")[-1])\r\n        logger.info(f\"video save path is {save_path}\")\r\n\r\n        video_writer = cv2.VideoWriter(\r\n            save_path,\r\n            cv2.VideoWriter_fourcc(*\"mp4v\"),\r\n            fps,\r\n            (int(width), int(height)),\r\n        )\r\n\r\n    frame_id = 1\r\n    winName = 'Deep learning object detection in OpenCV'\r\n    while True:\r\n        start_time = time.time()\r\n\r\n        ret, frame = cap.read()\r\n        if not ret:\r\n            break\r\n        debug_image = copy.deepcopy(frame)\r\n\r\n        _, bboxes, ids, scores = byte_tracker.inference(frame)\r\n\r\n        elapsed_time = time.time() - start_time\r\n\r\n        debug_image = draw_tracking_info(\r\n            debug_image,\r\n            bboxes,\r\n            ids,\r\n            scores,\r\n            frame_id,\r\n            elapsed_time,\r\n        )\r\n\r\n        if use_debug_window:\r\n            key = cv2.waitKey(1)\r\n            if key == 27:  # ESC\r\n                break\r\n\r\n            cv2.namedWindow(winName, 0)\r\n            cv2.imshow(winName, debug_image)\r\n        else:\r\n            video_writer.write(debug_image)\r\n\r\n        logger.info(\r\n            'frame {}/{} ({:.2f} ms)'.format(frame_id, int(frame_count),\r\n                                             elapsed_time * 1000), )\r\n        frame_id += 1\r\n\r\n    if use_debug_window:\r\n        cap.release()\r\n        cv2.destroyAllWindows()\r\n\r\n\r\ndef get_id_color(index):\r\n    temp_index = abs(int(index)) * 3\r\n    color = ((37 * temp_index) % 255, (17 * temp_index) % 255,\r\n             (29 * temp_index) % 255)\r\n    return color\r\n\r\n\r\ndef draw_tracking_info(\r\n    image,\r\n    tlwhs,\r\n    ids,\r\n    scores,\r\n    frame_id=0,\r\n    elapsed_time=0.,\r\n):\r\n    text_scale = 1.5\r\n    text_thickness = 2\r\n    line_thickness = 2\r\n\r\n    text = 'frame: %d ' % (frame_id)\r\n    text += 'elapsed time: %.0fms ' % (elapsed_time * 1000)\r\n    text += 'num: %d' % (len(tlwhs))\r\n    cv2.putText(\r\n        image,\r\n        text,\r\n        (0, int(15 * text_scale)),\r\n        cv2.FONT_HERSHEY_PLAIN,\r\n        2,\r\n        (0, 255, 0),\r\n        thickness=text_thickness,\r\n    )\r\n\r\n    for index, tlwh in enumerate(tlwhs):\r\n        x1, y1 = int(tlwh[0]), int(tlwh[1])\r\n        x2, y2 = x1 + int(tlwh[2]), y1 + int(tlwh[3])\r\n\r\n        color = get_id_color(ids[index])\r\n        cv2.rectangle(image, (x1, y1), (x2, y2), color, line_thickness)\r\n\r\n        # text = str(ids[index]) + ':%.2f' % (scores[index])\r\n        text = str(ids[index])\r\n        cv2.putText(image, text, (x1, y1 - 5), cv2.FONT_HERSHEY_PLAIN,\r\n                    text_scale, (0, 0, 0), text_thickness + 3)\r\n        cv2.putText(image, text, (x1, y1 - 5), cv2.FONT_HERSHEY_PLAIN,\r\n                    text_scale, (255, 255, 255), text_thickness)\r\n    return image\r\n\r\n\r\nif __name__ == '__main__':\r\n    main()\r\n"
  },
  {
    "path": "requirements.txt",
    "content": "Cython\npycocotools\nscipy\nloguru\nthop\nlap\ncython_bbox\n"
  }
]