派生自 Algorithm/baseDetector

Scheaven
2021-08-11 8e10c57c7e053d8789747cf1e2c5fa78f2f65cc7
add t
14个文件已修改
30个文件已添加
4391 ■■■■■ 已修改文件
CMakeLists.txt 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config.json 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
demo.cpp 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Munkres_assign/hungarianoper.cpp 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Munkres_assign/hungarianoper.h 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Munkres_assign/munkres/matrix.h 248 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Munkres_assign/munkres/munkres.cpp 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Munkres_assign/munkres/munkres.h 463 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/additional/fall_run_wander.cpp 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/additional/fall_run_wander.h 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/config.h 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/ari_manager.cpp 365 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/ari_manager.h 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/detecter_manager.cpp 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/core/detecter_manager.h 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/detecter_tools/detector.cpp 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/detecter_tools/model.cpp 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/detecter_tools/model.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/h_interface.cpp 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/h_interface.h 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tracker_tools/dataType.h 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tracker_tools/feature_util.cpp 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tracker_tools/feature_util.h 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tracker_tools/kalmfilter.cpp 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tracker_tools/kalmfilter.h 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tracker_tools/linear_assignment.cpp 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tracker_tools/linear_assignment.h 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tracker_tools/model.cpp 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tracker_tools/model.h 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tracker_tools/nn_matching.cpp 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tracker_tools/nn_matching.h 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tracker_tools/track.cpp 312 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tracker_tools/track.h 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tracker_tools/tracker.cpp 343 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/tracker_tools/tracker.h 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/draw_util.cpp 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/draw_util.h 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/geometry_util.cpp 445 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/geometry_util.h 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/queue_util.hpp 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/stack_util.hpp 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/time_util.cpp 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/time_util.h 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/timer_utils.hpp 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
CMakeLists.txt
@@ -3,8 +3,8 @@
enable_language(CUDA)
set(CMAKE_CXX_COMPILIER "/usr/bin/g++")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -O3 -Wno-write-strings")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,$ORIGIN")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -O3 -DS_DEBUG -Wno-write-strings")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -DS_DEBUG -Wl,-rpath -Wl,$ORIGIN")
set(CUDA_Path /usr/local/cuda)
find_package(OpenCV REQUIRED PATHS "/data/disk2/opt/01_opencv/opencv4.5.2")
@@ -34,10 +34,10 @@
  set(
          CUDA_NVCC_FLAGS
          ${CUDA_NVCC_FLAGS};
          -gencode arch=compute_61,code=sm_61 -std=c++14# 不同GPU有不同的算力指数,可查看算力表
          -gencode arch=compute_80,code=sm_80 -std=c++14# 不同GPU有不同的算力指数,可查看算力表
          -gencode arch=compute_72,code=sm_72 -std=c++14# 不同GPU有不同的算力指数,可查看算力表
          -gencode arch=compute_75,code=sm_75 -std=c++14# 不同GPU有不同的算力指数,可查看算力表
          -gencode arch=compute_61,code=sm_61 -std=c++14
          -gencode arch=compute_80,code=sm_80 -std=c++14
          -gencode arch=compute_72,code=sm_72 -std=c++14
          -gencode arch=compute_75,code=sm_75 -std=c++14
  )
  set(CUDA_NVCC_FLAGS_RELWITHDEBINFO "--device-debug;-lineinfo")
  #find_package(OpenCV REQUIRED) # 查找系统的默认opencv环境
@@ -46,11 +46,11 @@
cuda_add_library(${PROJECT_NAME} SHARED ${sources})
target_include_directories(${PROJECT_NAME} PRIVATE ${OpenCV_INCLUDE_DIRS} src/ src/core src/utils/ src/detecter_tools/)
target_include_directories(${PROJECT_NAME} PRIVATE ${OpenCV_INCLUDE_DIRS} src/ src/core src/utils/  src/tracker_tools/ src/Munkers_assign/ src/detecter_tools/ src/additional/)
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS} ${LIBS})
add_executable(demo demo.cpp)
target_include_directories(demo PRIVATE src/ src/core src/utils/ src/detecter_tools/)
target_include_directories(demo PRIVATE src/ src/core src/utils/ src/detecter_tools/ src/tracker_tools/ src/Munkers_assign/ src/additional/)
target_link_libraries(demo ${PROJECT_NAME})
# add_executable(demo demo.cpp ${sources})
config.json
@@ -4,6 +4,11 @@
  "param": {
    "model_path": "/data/disk1/project/model_dump/02_yolo/baseDetect-kFLOAT-batch1.engine", // para里边自己算法可能用到的参数
    //"model_path": "/data/disk1/project/model_dump/02_yolo/baseDetetor_small.bin", // para里边自己算法可能用到的参数
    "type":1
    "type":1,
    "max_cam_num": 8,
    "wander_time": 5,
    "mv_velocity": 10.0,
    "fall_rate":1.3,
    "isTrack":false
  }
}
demo.cpp
@@ -9,6 +9,36 @@
using namespace std;
using namespace cv;
void* handle;
bool do_frame(Mat frame, TImage *img, void *sr, void* handle, int cam_id)
{
    if(!frame.empty())
    {
        img->width = frame.cols;
        img->height = frame.rows;
        img->channel = frame.channels();
        img->data = frame.data;
        const char * img_time = fa_getSysTime();
        const char* mode = "video";
//        printf("===%s\n",img_time);
        std::cout<< "===%s:" << img_time << std::endl;
        sr = get_result2(handle, img, cam_id, img_time, mode);
        TResult * t_result = (TResult*) sr;
        cout << "=======t_result->count==" << t_result->count  << endl;
        for (int i=0; i<t_result->count; i++)
        {
            cout << "====1111111111===confidence:" << t_result->targets[i].confidence << endl;
            cout << "====1111111111===attri:" << t_result->targets[i].attribute << endl;
        }
        return true;
    }else{
        cout << "-----------------------over--" << endl;
        release(handle);
        release_result(sr);
        return false;
    }
}
int main(int argc, char *argv[])
{
@@ -38,18 +68,10 @@
        cap >> frame;
        if(!frame.empty())
        {
            img->width = frame.cols;
            img->height = frame.rows;
            img->channel = frame.channels();
            img->data = frame.data;
            sr = get_result(handle, img, 0);
            TResult * t_result = (TResult*) sr;
            cout << "t_result->count==" << t_result->count  << endl;
            for (int i=0; i<t_result->count; i++)
            {
                cout << "confidence:" << t_result->targets[i].confidence << endl;
                // draw_SDK_result(frame, t_result->targets[i]);
            }
            // std::clock_t t_strat2 = std::clock();
            if(!do_frame(frame, img, sr, handle, i))
                return 0;
            cout << "-------------" << endl;
        }else{
            cout << "------------over--" << endl;
            release(handle);
src/Munkres_assign/hungarianoper.cpp
New file
@@ -0,0 +1,33 @@
#include "hungarianoper.h"
Eigen::Matrix<float, -1, 2, Eigen::RowMajor> HungarianOper::Solve(const DYNAMICM &cost_matrix)
{
    int rows = cost_matrix.rows();
    int cols = cost_matrix.cols();
    Matrix<double> matrix(rows, cols);
    for (int row = 0; row < rows; row++) {
        for (int col = 0; col < cols; col++) {
            matrix(row, col) = cost_matrix(row, col);
        }
    }
    //Munkres get matrix;
    Munkres<double> m;
    m.solve(matrix);
    //
    std::vector<std::pair<int, int>> pairs;
    for (int row = 0; row < rows; row++) {
        for (int col = 0; col < cols; col++) {
            int tmp = (int)matrix(row, col);
            if (tmp == 0) pairs.push_back(std::make_pair(row, col));
        }
    }
    //
    int count = pairs.size();
    Eigen::Matrix<float, -1, 2, Eigen::RowMajor> re(count, 2);
    for (int i = 0; i < count; i++) {
        re(i, 0) = pairs[i].first;
        re(i, 1) = pairs[i].second;
    }
    return re;
}//end Solve;
src/Munkres_assign/hungarianoper.h
New file
@@ -0,0 +1,12 @@
#ifndef HUNGARIANOPER_H
#define HUNGARIANOPER_H
#include "munkres/munkres.h"
//#include "munkres/adapters/boostmatrixadapter.h"
#include "../tracker_tools/dataType.h"
class HungarianOper {
public:
    static Eigen::Matrix<float, -1, 2, Eigen::RowMajor> Solve(const DYNAMICM &cost_matrix);
};
#endif // HUNGARIANOPER_H
src/Munkres_assign/munkres/matrix.h
New file
@@ -0,0 +1,248 @@
/*
 *   Copyright (c) 2007 John Weaver
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 */
#ifndef _MATRIX_H_
#define _MATRIX_H_
#include <initializer_list>
#include <cstdlib>
#include <ostream>
#include <cassert>
#include <cstdlib>
#include <algorithm>
#define XYZMIN(x, y) (x)<(y)?(x):(y)
#define XYZMAX(x, y) (x)>(y)?(x):(y)
template <class T>
class Matrix {
public:
    Matrix(){
        m_rows = 0;
        m_columns = 0;
        m_matrix = nullptr;
    }
    Matrix(const size_t rows, const size_t columns)  {
        m_matrix = nullptr;
        resize(rows, columns);
    }
    Matrix(const std::initializer_list<std::initializer_list<T>> init) {
        m_matrix = nullptr;
        m_rows = init.size();
        if ( m_rows == 0 ) {
            m_columns = 0;
        } else {
            m_columns = init.begin()->size();
            if ( m_columns > 0 ) {
                resize(m_rows, m_columns);
            }
        }
        size_t i = 0, j;
        for ( auto row = init.begin() ; row != init.end() ; ++row, ++i ) {
            assert ( row->size() == m_columns && "All rows must have the same number of columns." );
            j = 0;
            for ( auto value = row->begin() ; value != row->end() ; ++value, ++j ) {
                m_matrix[i][j] = *value;
            }
        }
    }
    Matrix(const Matrix<T> &other)  {
        if ( other.m_matrix != nullptr ) {
            // copy arrays
            m_matrix = nullptr;
            resize(other.m_rows, other.m_columns);
            for ( size_t i = 0 ; i < m_rows ; i++ ) {
                for ( size_t j = 0 ; j < m_columns ; j++ ) {
                    m_matrix[i][j] = other.m_matrix[i][j];
                }
            }
        } else {
            m_matrix = nullptr;
            m_rows = 0;
            m_columns = 0;
        }
    }
    Matrix<T> & operator= (const Matrix<T> &other){
        if ( other.m_matrix != nullptr ) {
            // copy arrays
            resize(other.m_rows, other.m_columns);
            for ( size_t i = 0 ; i < m_rows ; i++ ) {
                for ( size_t j = 0 ; j < m_columns ; j++ ) {
                    m_matrix[i][j] = other.m_matrix[i][j];
                }
            }
        } else {
            // free arrays
            for ( size_t i = 0 ; i < m_columns ; i++ ) {
                delete [] m_matrix[i];
            }
            delete [] m_matrix;
            m_matrix = nullptr;
            m_rows = 0;
            m_columns = 0;
        }
        return *this;
    }
    ~Matrix(){
        if ( m_matrix != nullptr ) {
            // free arrays
            for ( size_t i = 0 ; i < m_rows ; i++ ) {
                delete [] m_matrix[i];
            }
            delete [] m_matrix;
        }
        m_matrix = nullptr;
    }
    // all operations modify the matrix in-place.
    void resize(const size_t rows, const size_t columns, const T default_value = 0) {
        assert ( rows > 0 && columns > 0 && "Columns and rows must exist." );
        if ( m_matrix == nullptr ) {
            // alloc arrays
            m_matrix = new T*[rows]; // rows
            for ( size_t i = 0 ; i < rows ; i++ ) {
                m_matrix[i] = new T[columns]; // columns
            }
            m_rows = rows;
            m_columns = columns;
            clear();
        } else {
            // save array pointer
            T **new_matrix;
            // alloc new arrays
            new_matrix = new T*[rows]; // rows
            for ( size_t i = 0 ; i < rows ; i++ ) {
                new_matrix[i] = new T[columns]; // columns
                for ( size_t j = 0 ; j < columns ; j++ ) {
                    new_matrix[i][j] = default_value;
                }
            }
            // copy data from saved pointer to new arrays
            size_t minrows = XYZMIN(rows, m_rows);
            size_t mincols = XYZMIN(columns, m_columns);
            for ( size_t x = 0 ; x < minrows ; x++ ) {
                for ( size_t y = 0 ; y < mincols ; y++ ) {
                    new_matrix[x][y] = m_matrix[x][y];
                }
            }
            // delete old arrays
            if ( m_matrix != nullptr ) {
                for ( size_t i = 0 ; i < m_rows ; i++ ) {
                    delete [] m_matrix[i];
                }
                delete [] m_matrix;
            }
            m_matrix = new_matrix;
        }
        m_rows = rows;
        m_columns = columns;
    }
    void clear() {
        assert( m_matrix != nullptr );
        for ( size_t i = 0 ; i < m_rows ; i++ ) {
            for ( size_t j = 0 ; j < m_columns ; j++ ) {
                m_matrix[i][j] = 0;
            }
        }
    }
    T& operator () (const size_t x, const size_t y) {
        assert ( x < m_rows );
        assert ( y < m_columns );
        assert ( m_matrix != nullptr );
        return m_matrix[x][y];
    }
    const T& operator () (const size_t x, const size_t y) const {
        assert ( x < m_rows );
        assert ( y < m_columns );
        assert ( m_matrix != nullptr );
        return m_matrix[x][y];
    }
    const T mmin() const {
        assert( m_matrix != nullptr );
        assert ( m_rows > 0 );
        assert ( m_columns > 0 );
        T min = m_matrix[0][0];
        for ( size_t i = 0 ; i < m_rows ; i++ ) {
            for ( size_t j = 0 ; j < m_columns ; j++ ) {
                min = std::min<T>(min, m_matrix[i][j]);
            }
        }
        return min;
    }
    const T mmax() const {
        assert( m_matrix != nullptr );
        assert ( m_rows > 0 );
        assert ( m_columns > 0 );
        T max = m_matrix[0][0];
        for ( size_t i = 0 ; i < m_rows ; i++ ) {
            for ( size_t j = 0 ; j < m_columns ; j++ ) {
                max = std::max<T>(max, m_matrix[i][j]);
            }
        }
        return max;
    }
    inline size_t minsize() { return ((m_rows < m_columns) ? m_rows : m_columns); }
    inline size_t columns() const { return m_columns;}
    inline size_t rows() const { return m_rows;}
    friend std::ostream& operator<<(std::ostream& os, const Matrix &matrix)
    {
        os << "Matrix:" << std::endl;
        for (size_t row = 0 ; row < matrix.rows() ; row++ )
        {
            for (size_t col = 0 ; col < matrix.columns() ; col++ )
            {
                os.width(8);
                os << matrix(row, col) << ",";
            }
            os << std::endl;
        }
        return os;
    }
private:
    T **m_matrix;
    size_t m_rows;
    size_t m_columns;
};
//#ifndef USE_EXPORT_KEYWORD
//#include "matrix.cpp"
////#define export /*export*/
//#endif
#endif /* !defined(_MATRIX_H_) */
src/Munkres_assign/munkres/munkres.cpp
New file
@@ -0,0 +1,25 @@
/*
 *   Copyright (c) 2007 John Weaver
 *   Copyright (c) 2015 Miroslav Krajicek
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 */
#include "munkres.h"
template class Munkres<double>;
template class Munkres<float>;
template class Munkres<int>;
src/Munkres_assign/munkres/munkres.h
New file
@@ -0,0 +1,463 @@
/*
 *   Copyright (c) 2007 John Weaver
 * *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 */
#if !defined(_MUNKRES_H_)
#define _MUNKRES_H_
#include "matrix.h"
#include <list>
#include <utility>
#include <iostream>
#include <cmath>
#include <limits>
template<typename Data> class Munkres
{
    static constexpr int NORMAL = 0;
    static constexpr int STAR   = 1;
    static constexpr int PRIME  = 2;
public:
    /*
     *
     * Linear assignment problem solution
     * [modifies matrix in-place.]
     * matrix(row,col): row major format assumed.
     *
     * Assignments are remaining 0 values
     * (extra 0 values are replaced with -1)
     *
     */
    void solve(Matrix<Data> &m) {
        const size_t rows = m.rows(),
                columns = m.columns(),
                size = XYZMAX(rows, columns);
#ifdef DEBUG
        std::cout << "Munkres input: " << m << std::endl;
#endif
        // Copy input matrix
        this->matrix = m;
        if ( rows != columns ) {
            // If the input matrix isn't square, make it square
            // and fill the empty values with the largest value present
            // in the matrix.
            matrix.resize(size, size, matrix.mmax());
        }
        // STAR == 1 == starred, PRIME == 2 == primed
        mask_matrix.resize(size, size);
        row_mask = new bool[size];
        col_mask = new bool[size];
        for ( size_t i = 0 ; i < size ; i++ ) {
            row_mask[i] = false;
        }
        for ( size_t i = 0 ; i < size ; i++ ) {
            col_mask[i] = false;
        }
        // Prepare the matrix values...
        // If there were any infinities, replace them with a value greater
        // than the maximum value in the matrix.
        replace_infinites(matrix);
        minimize_along_direction(matrix, rows >= columns);
        minimize_along_direction(matrix, rows <  columns);
        // Follow the steps
        int step = 1;
        while ( step ) {
            switch ( step ) {
            case 1:
                step = step1();
                // step is always 2
                break;
            case 2:
                step = step2();
                // step is always either 0 or 3
                break;
            case 3:
                step = step3();
                // step in [3, 4, 5]
                break;
            case 4:
                step = step4();
                // step is always 2
                break;
            case 5:
                step = step5();
                // step is always 3
                break;
            }
        }
        // Store results
        for ( size_t row = 0 ; row < size ; row++ ) {
            for ( size_t col = 0 ; col < size ; col++ ) {
                if ( mask_matrix(row, col) == STAR ) {
                    matrix(row, col) = 0;
                } else {
                    matrix(row, col) = -1;
                }
            }
        }
#ifdef DEBUG
        std::cout << "Munkres output: " << matrix << std::endl;
#endif
        // Remove the excess rows or columns that we added to fit the
        // input to a square matrix.
        matrix.resize(rows, columns);
        m = matrix;
        delete [] row_mask;
        delete [] col_mask;
    }
    static void replace_infinites(Matrix<Data> &matrix) {
      const size_t rows = matrix.rows(),
                columns = matrix.columns();
      //assert( rows > 0 && columns > 0 );
      double max = matrix(0, 0);
      constexpr auto infinity = std::numeric_limits<double>::infinity();
      // Find the greatest value in the matrix that isn't infinity.
      for ( size_t row = 0 ; row < rows ; row++ ) {
        for ( size_t col = 0 ; col < columns ; col++ ) {
          if ( matrix(row, col) != infinity ) {
            if ( max == infinity ) {
              max = matrix(row, col);
            } else {
              max = XYZMAX(max, matrix(row, col));
            }
          }
        }
      }
      // a value higher than the maximum value present in the matrix.
      if ( max == infinity ) {
        // This case only occurs when all values are infinite.
        max = 0;
      } else {
        max++;
      }
      for ( size_t row = 0 ; row < rows ; row++ ) {
        for ( size_t col = 0 ; col < columns ; col++ ) {
          if ( matrix(row, col) == infinity ) {
            matrix(row, col) = max;
          }
        }
      }
    }
    static void minimize_along_direction(Matrix<Data> &matrix, const bool over_columns) {
      const size_t outer_size = over_columns ? matrix.columns() : matrix.rows(),
                   inner_size = over_columns ? matrix.rows() : matrix.columns();
      // Look for a minimum value to subtract from all values along
      // the "outer" direction.
      for ( size_t i = 0 ; i < outer_size ; i++ ) {
        double min = over_columns ? matrix(0, i) : matrix(i, 0);
        // As long as the current minimum is greater than zero,
        // keep looking for the minimum.
        // Start at one because we already have the 0th value in min.
        for ( size_t j = 1 ; j < inner_size && min > 0 ; j++ ) {
          min = XYZMIN(
            min,
            over_columns ? matrix(j, i) : matrix(i, j));
        }
        if ( min > 0 ) {
          for ( size_t j = 0 ; j < inner_size ; j++ ) {
            if ( over_columns ) {
              matrix(j, i) -= min;
            } else {
              matrix(i, j) -= min;
            }
          }
        }
      }
    }
private:
  inline bool find_uncovered_in_matrix(const double item, size_t &row, size_t &col) const {
    const size_t rows = matrix.rows(),
              columns = matrix.columns();
    for ( row = 0 ; row < rows ; row++ ) {
      if ( !row_mask[row] ) {
        for ( col = 0 ; col < columns ; col++ ) {
          if ( !col_mask[col] ) {
            if ( matrix(row,col) == item ) {
              return true;
            }
          }
        }
      }
    }
    return false;
  }
  bool pair_in_list(const std::pair<size_t,size_t> &needle, const std::list<std::pair<size_t,size_t> > &haystack) {
    for ( std::list<std::pair<size_t,size_t> >::const_iterator i = haystack.begin() ; i != haystack.end() ; i++ ) {
      if ( needle == *i ) {
        return true;
      }
    }
    return false;
  }
  int step1() {
    const size_t rows = matrix.rows(),
              columns = matrix.columns();
    for ( size_t row = 0 ; row < rows ; row++ ) {
      for ( size_t col = 0 ; col < columns ; col++ ) {
        if ( 0 == matrix(row, col) ) {
          for ( size_t nrow = 0 ; nrow < row ; nrow++ )
            if ( STAR == mask_matrix(nrow,col) )
              goto next_column;
          mask_matrix(row,col) = STAR;
          goto next_row;
        }
        next_column:;
      }
      next_row:;
    }
    return 2;
  }
  int step2() {
    const size_t rows = matrix.rows(),
              columns = matrix.columns();
    size_t covercount = 0;
    for ( size_t row = 0 ; row < rows ; row++ )
      for ( size_t col = 0 ; col < columns ; col++ )
        if ( STAR == mask_matrix(row, col) ) {
          col_mask[col] = true;
          covercount++;
        }
    if ( covercount >= matrix.minsize() ) {
  #ifdef DEBUG
      std::cout << "Final cover count: " << covercount << std::endl;
  #endif
      return 0;
    }
  #ifdef DEBUG
    std::cout << "Munkres matrix has " << covercount << " of " << matrix.minsize() << " Columns covered:" << std::endl;
    std::cout << matrix << std::endl;
  #endif
    return 3;
  }
  int step3() {
    /*
    Main Zero Search
     1. Find an uncovered Z in the distance matrix and prime it. If no such zero exists, go to Step 5
     2. If No Z* exists in the row of the Z', go to Step 4.
     3. If a Z* exists, cover this row and uncover the column of the Z*. Return to Step 3.1 to find a new Z
    */
    if ( find_uncovered_in_matrix(0, saverow, savecol) ) {
      mask_matrix(saverow,savecol) = PRIME; // prime it.
    } else {
      return 5;
    }
    for ( size_t ncol = 0 ; ncol < matrix.columns() ; ncol++ ) {
      if ( mask_matrix(saverow,ncol) == STAR ) {
        row_mask[saverow] = true; //cover this row and
        col_mask[ncol] = false; // uncover the column containing the starred zero
        return 3; // repeat
      }
    }
    return 4; // no starred zero in the row containing this primed zero
  }
  int step4() {
    const size_t rows = matrix.rows(),
              columns = matrix.columns();
    // seq contains pairs of row/column values where we have found
    // either a star or a prime that is part of the ``alternating sequence``.
    std::list<std::pair<size_t,size_t> > seq;
    // use saverow, savecol from step 3.
    std::pair<size_t,size_t> z0(saverow, savecol);
    seq.insert(seq.end(), z0);
    // We have to find these two pairs:
    std::pair<size_t,size_t> z1(-1, -1);
    std::pair<size_t,size_t> z2n(-1, -1);
    size_t row, col = savecol;
    /*
    Increment Set of Starred Zeros
     1. Construct the ``alternating sequence'' of primed and starred zeros:
           Z0 : Unpaired Z' from Step 4.2
           Z1 : The Z* in the column of Z0
           Z[2N] : The Z' in the row of Z[2N-1], if such a zero exists
           Z[2N+1] : The Z* in the column of Z[2N]
        The sequence eventually terminates with an unpaired Z' = Z[2N] for some N.
    */
    bool madepair;
    do {
      madepair = false;
      for ( row = 0 ; row < rows ; row++ ) {
        if ( mask_matrix(row,col) == STAR ) {
          z1.first = row;
          z1.second = col;
          if ( pair_in_list(z1, seq) ) {
            continue;
          }
          madepair = true;
          seq.insert(seq.end(), z1);
          break;
        }
      }
      if ( !madepair )
        break;
      madepair = false;
      for ( col = 0 ; col < columns ; col++ ) {
        if ( mask_matrix(row, col) == PRIME ) {
          z2n.first = row;
          z2n.second = col;
          if ( pair_in_list(z2n, seq) ) {
            continue;
          }
          madepair = true;
          seq.insert(seq.end(), z2n);
          break;
        }
      }
    } while ( madepair );
    for ( std::list<std::pair<size_t,size_t> >::iterator i = seq.begin() ;
        i != seq.end() ;
        i++ ) {
      // 2. Unstar each starred zero of the sequence.
      if ( mask_matrix(i->first,i->second) == STAR )
        mask_matrix(i->first,i->second) = NORMAL;
      // 3. Star each primed zero of the sequence,
      // thus increasing the number of starred zeros by one.
      if ( mask_matrix(i->first,i->second) == PRIME )
        mask_matrix(i->first,i->second) = STAR;
    }
    // 4. Erase all primes, uncover all columns and rows,
    for ( size_t row = 0 ; row < mask_matrix.rows() ; row++ ) {
      for ( size_t col = 0 ; col < mask_matrix.columns() ; col++ ) {
        if ( mask_matrix(row,col) == PRIME ) {
          mask_matrix(row,col) = NORMAL;
        }
      }
    }
    for ( size_t i = 0 ; i < rows ; i++ ) {
      row_mask[i] = false;
    }
    for ( size_t i = 0 ; i < columns ; i++ ) {
      col_mask[i] = false;
    }
    // and return to Step 2.
    return 2;
  }
  int step5() {
    const size_t rows = matrix.rows(),
              columns = matrix.columns();
    /*
    New Zero Manufactures
     1. Let h be the smallest uncovered entry in the (modified) distance matrix.
     2. Add h to all covered rows.
     3. Subtract h from all uncovered columns
     4. Return to Step 3, without altering stars, primes, or covers.
    */
    double h = 100000;//xyzoylz std::numeric_limits<double>::max();
    for ( size_t row = 0 ; row < rows ; row++ ) {
      if ( !row_mask[row] ) {
        for ( size_t col = 0 ; col < columns ; col++ ) {
          if ( !col_mask[col] ) {
            if ( h > matrix(row, col) && matrix(row, col) != 0 ) {
              h = matrix(row, col);
            }
          }
        }
      }
    }
    for ( size_t row = 0 ; row < rows ; row++ ) {
      if ( row_mask[row] ) {
        for ( size_t col = 0 ; col < columns ; col++ ) {
          matrix(row, col) += h;
        }
      }
    }
    for ( size_t col = 0 ; col < columns ; col++ ) {
      if ( !col_mask[col] ) {
        for ( size_t row = 0 ; row < rows ; row++ ) {
          matrix(row, col) -= h;
        }
      }
    }
    return 3;
  }
  Matrix<int> mask_matrix;
  Matrix<Data> matrix;
  bool *row_mask;
  bool *col_mask;
  size_t saverow = 0, savecol = 0;
};
#endif /* !defined(_MUNKRES_H_) */
src/additional/fall_run_wander.cpp
New file
@@ -0,0 +1,193 @@
#include <unistd.h>
#include <cstdlib>
#include <algorithm>
#include "fall_run_wander.h"
/** 判断跌倒:
    两个特征:1、宽高的比率;2、比率的变化速度(取变化后的和最初设计的小值)3、跌倒后的重心下降 4、跌倒过程小于1.5s
     return 跌倒的概率,以及持续的时间
    */
//void detect_fall(DETECTBOX tmpbox, std::shared_ptr<Track>& track)
//{
//    float rate = tmpbox(2)/tmpbox(3);
//    if(rate < track->rate)
//    {
//        track->rate = rate;
//        track->isFall = false;
//    }
//
//
//    // 更新track->rate_queue以及记录minRate的相关信息
//    if(track->rate_queue.size()>=5)
//    {
//        track->rate_queue.pop();
//
//    }else if(track->rate_queue.isEmpty())
//    {
//        track->minRate = rate;
//        gettimeofday(&track->min_rate_time,0);
//
//        track->center_point.x = float(tmpbox(0)+tmpbox(2)/2);
//        track->center_point.y = float(tmpbox(1)+tmpbox(3)/2);
//        track->human_h = tmpbox(3);
//    }
//
//    if(track->rate_queue.size()>0)
//    {
//        if(track->rate_queue.min()>=rate)
//        {
//            track->minRate = rate;
//            gettimeofday(&track->min_rate_time,0);
//            track->center_point.x = float(tmpbox(0)+tmpbox(2)/2);
//            track->center_point.y = float(tmpbox(1)+tmpbox(3)/2);
//            if(rate>0.25)
//            {
//                track->human_h = tmpbox(3);
//                track->human_w = tmpbox(2);
//            }
//        }
//    }
//
//    if(track->hisMinRate>=rate)
//    {
//        track->hisMinRate=rate;
//        track->min_center_point.x = float(tmpbox(0)+tmpbox(2)/2);
//        track->min_center_point.y = float(tmpbox(1)+tmpbox(3)/2);
//    }
//
//    track->rate_queue.push(rate);
//
//    // 判断是否跌倒
////    float fall_threshold = 1.3; //默认调参1.3(能和蹲下区分的参数)
//    gettimeofday(&track->fall_e_time,0); // 当前比例时间
//    track->time_substract(&track->fall_diff_time,&track->min_rate_time,&track->fall_e_time); //距离最小比例的时间
//    int fall_rate_time = (int)(track->fall_diff_time.tv_sec*1000 + track->fall_diff_time.tv_usec/1000);
//    float fall_threshold = m_staticStruct::fall_rate;
//
//    if((rate > std::min(fall_threshold, 5*track->rate)||track->human_h>=tmpbox(3)*2*track->human_w/tmpbox(2)) && fall_rate_time<2000 && std::min(track->min_center_point.y, track->center_point.y)<float(tmpbox(1)+tmpbox(3)/2))
//    {
//        track->isFall = true;
////                std::cout << fall_threshold <<"-- fall_threshold--:" << rate << ":" << 5*track->rate <<std::endl;
//    }
//    else if(rate < 0.9)
//    {
//        track->isFall = false;
//        track->fall_total_time = 0 ;
//        track->first_Fall = true;
//    }
//
//    // 计算跌倒置信度
//    if(track->isFall)
//    {
//        /**-- start计算累积跌倒时间*/
//        if(track->first_Fall) //是否开始计算跌倒时间
//        {
//            track->first_Fall = false;
//            gettimeofday(&track->fall_s_time,0);
//        }
//        gettimeofday(&track->fall_e_time,0);
//        track->time_substract(&track->fall_diff_time,&track->fall_s_time,&track->fall_e_time); //距离最小比例的时间
//        track->fall_total_time = (int)(track->fall_diff_time.tv_sec + track->fall_diff_time.tv_usec/1000000);
//
//        /** -- end计算累积跌倒时间*/
//
//        track->rateScale = int(std::min(float((rate - 0.6)*72), 100.0f));
//
//        if(track->rateScale<0)
//        {
//            track->rateScale = 0-track->rateScale;
//        }
//    }else
//    {
//        track->rateScale = int(std::max(float(10 - (fall_threshold - rate)*10), 0.0f));
//    }
//
//    //    std::cout << track->fall_total_time << "::" << fall_rate_time << ":" <<track->min_center_point.y <<"-"<< track->center_point.y << ":"<<float(tmpbox(1)+tmpbox(3)/2) <<"-- fall--:" << rate << ":" << track->isFall <<std::endl;
//    //    std::cout << track->human_h << ":::f:::" << tmpbox(3)*4*track->human_w/tmpbox(2) <<std::endl;
//}
/**
    算法思想: 判断点的人体脚点的移动移动速度,移动的速度为单帧的移动距离比上单帧画面所花费的时间
    做了一个10帧的队列,对队列中的速度进行平滑处理
    改进点:根据不同的画面位置 进行移动距离的放缩
           横纵画面距离的权重平衡(横纵的变化速度不一样)
*/
float detect_runing(DETECTBOX tmpbox, std::shared_ptr<Track>& track, cv::Mat img)
{
    float human_pointX =  tmpbox(0) + tmpbox(2)/2;
    float human_pointY = tmpbox(1);
    double rate = tmpbox(2)/tmpbox(3);
    double curr_area = tmpbox(2)*tmpbox(3);
    float move_velocity = 0;
    float ave_velocity = 0;
    if(track->is_runing_p)
    {
        track->last_point.x = human_pointX;
        track->last_point.y = human_pointY;
        track->is_runing_p = false;
    }else
    {
        SPoint curr_point(human_pointX, human_pointY);
        float move_distance = calDistance(curr_point, track->last_point);
        if(tmpbox(1)<0 ||tmpbox(1)+tmpbox(3)>=img.rows)
        {
            ave_velocity=0;
            queue<float> empty;
            swap(empty,track->velocity_queue);
            track->sum_velocity=0;
            track->run_rate = rate;
        }
        move_velocity = move_distance/track->single_time;
//        std::cout << curr_point.x << ":" << curr_point.y <<"-------------------" <<track->last_point.x<< "::" << track->last_point.y <<std::endl;
//        std::cout << move_distance <<"-------- move_velocity:" << track->single_time << "::" << move_velocity <<std::endl;
        track->last_point.x = human_pointX;
        track->last_point.y = human_pointY;
        if(track->velocity_queue.size()==10)
        {
            float last_velocity = track->velocity_queue.front();
            track->sum_velocity -= last_velocity;
            track->velocity_queue.pop();
//                    std::cout << "-------- last_velocity:" << last_velocity <<std::endl;
        }
        track->velocity_queue.push(move_velocity);
        track->sum_velocity += move_velocity;
    }
    if (track->velocity_queue.size()>0)
    {
        ave_velocity = track->sum_velocity/track->velocity_queue.size();
    }else
    {
        ave_velocity = 0;
    }
    double diff_rate = fabs(rate - track->run_rate);
    double min_area = curr_area>track->rate_area?track->rate_area:curr_area;
    double max_area = curr_area>track->rate_area?curr_area:track->rate_area;
    double rate_area = fabs(min_area/max_area); //面积比例变化
    double last_diff_rate = fabs(rate - track->last_rate);
//    std::cout <<rate_area<<"::::"<< rate << " ---------------------------------rate:"<<track->run_rate <<"===== diff_rate:" << diff_rate  <<":::" << last_diff_rate <<std::endl;
    if(diff_rate>0.2 || last_diff_rate>0.2 || tmpbox(1)<0 || rate_area<0.8 ||tmpbox(1)+tmpbox(3)>=img.rows)
    {
        ave_velocity=0;
        queue<float> empty;
        swap(empty,track->velocity_queue);
        track->sum_velocity=0;
        track->run_rate = rate;
    }
    track->last_rate = rate;
    track->rate_area = curr_area;
//    std::cout << move_velocity << " :"<<track->sum_velocity <<"===== sum_velocity:" << track->velocity_queue.size() << "::" << ave_velocity <<std::endl;
//    std::cout << ave_velocity << "===== m_staticStruct::mv_velocity:" << std::endl;
    return ave_velocity;
}
src/additional/fall_run_wander.h
New file
@@ -0,0 +1,16 @@
//
// Created by Scheaven on 2020/6/1.
//
#ifndef INC_01_DARKNET_SORT_FALL_RUN_WANDER_H
#define INC_01_DARKNET_SORT_FALL_RUN_WANDER_H
#include "../tracker_tools/track.h"
#include "../config.h"
void detect_fall(DETECTBOX tmpbox, std::shared_ptr<Track>& track);
float detect_runing(DETECTBOX tmpbox, std::shared_ptr<Track>& track, cv::Mat img);
#endif //INC_01_DARKNET_SORT_FALL_RUN_WANDER_H
src/config.h
@@ -4,7 +4,7 @@
#ifndef INC_01_CPP_SORT_CONFIG_H
#define INC_01_CPP_SORT_CONFIG_H
#include "utils/timer_utils.hpp"
#include "utils/time_util.h"
#include <opencv2/opencv.hpp>
#include <algorithm>
@@ -29,6 +29,16 @@
#include "cuda_runtime_api.h"
#include "NvInfer.h"
const int nn_budget=100;
const float max_cosine_distance=0.7;
#define NN_BUDGET 100
#define MAX_COSINE_DISTANCE 0.7
#define MAX_IOU_DISTANCE 0.9
#define MAX_AGE 450
#define MAX_OUT_TIME 30.0
#define N_INIT 5
struct bbox_t {
    unsigned int x, y, w, h;       // (x,y) - top-left corner, (w, h) - width & height of bounded box
    float prob;                    // confidence - probability that the object was found correctly
@@ -42,6 +52,11 @@
{
    static std::string model_path;
    static int type;
    static bool isTrack;
    static int max_cam_num;
    static int wander_time;
    static float mv_velocity;
    static float fall_rate;
}M_STATICSTRUCT, *P_STATICSTRUCT;
#endif //INC_01_CPP_SORT_CONFIG_H
src/core/ari_manager.cpp
@@ -3,7 +3,7 @@
//
#include "ari_manager.h"
#include "../additional/fall_run_wander.h"
AriManager::AriManager()
{
@@ -25,7 +25,90 @@
}
void AriManager::single_SDK(const int cam_id, const void *img, TResult& t_result)
void AriManager::release()
{
    DetecterManager::getInstance()->release();
}
void AriManager::init_load_model()
{
    DEBUG("::loading detecter model!");
    DetecterManager::getInstance();
}
bool AriManager::add_cam(const int cam_id)
{
    if (cam_id==(this->CAMERAS_VCT.size()+1))
    {
        auto cam_tracker = std::make_shared<tracker>(max_cosine_distance, nn_budget);
        this->CAMERAS_VCT.push_back(cam_tracker);
        return true;
    }else if(cam_id<this->CAMERAS_VCT.size())
    {
        WARN("The camera ID " + to_string(cam_id) + "is occupied!");
        return false;
    }else
    {
        WARN("Camera ID" + to_string(cam_id) + "discontinuous!");
        return false;
    }
}
void AriManager::single_SDK(const int cam_id, const void *img, TResult *t_result, char* img_time, const char* mode)
{
    TImage *frame_img = (TImage*)img;
    // DEBUG((boost::format("%f, %f")%frame_img->width %frame_img->height).str());
    cv::Mat frame(Size(frame_img->width, frame_img->height), CV_8UC3); // size 是w,h    Mat是h,w
    frame.data = (uchar*)frame_img->data;   //注意不能写为:(uchar*)pFrameBGR->data
    cv::Mat draw_frame = frame.clone();
    Timer s_timer;
    s_timer.reset();
    DETECTIONS detections;
    DetecterManager::getInstance()->detecter_main(draw_frame, detections);
    s_timer.out("eve detecter_main");
    std::string mode_type = mode;
    DEBUG("detections human size::" + to_string(detections.size()));
    if(detections.size()>0)
    {
        if (mode_type == "video")
        {
            // if(HUMAN_STRUCT::reid_Extractor->featsEncoder(frame, detections) == false)
            // {
            //     WARN("Encoder human feature failed!");
            // }
            // auto t_strat2 =  std::chrono::steady_clock::now();
            // s_timer.out(to_string(detections.size())+" :eve reid_Extractor");
            single_tracker(cam_id, detections, img_time);
            s_timer.out("eve single_tracker");
            // auto t_strat3 =  std::chrono::steady_clock::now();
        //        std::cout<< "detections.size()" << detections.size()<< std::endl;
            switch_SDK_TResult(cam_id, frame, detections, t_result);
            // auto t_strat4 =  std::chrono::steady_clock::now();
            s_timer.out("eve switch_SDK_TResult");
            // double t_9 = std::chrono::duration<double, std::milli>(t_strat8 - t_strat9).count();
            // double t_8 = std::chrono::duration<double, std::milli>(t_strat7 - t_strat8).count();
            // double t_7 = std::chrono::duration<double, std::milli>(t_strat6 - t_strat7).count();
            // double t_6 = std::chrono::duration<double, std::milli>(t_strat1 - t_strat6).count();
            // double t_1 = std::chrono::duration<double, std::milli>(t_strat2 - t_strat1).count();
            // double t_2 = std::chrono::duration<double, std::milli>(t_strat3 - t_strat2).count();
            // double t_3 = std::chrono::duration<double, std::milli>(t_strat4 - t_strat3).count();
            // double t_0 = std::chrono::duration<double, std::milli>(t_strat4 - t_strat9).count();
            // std::cout << "fps time:" << to_string(t_9) << " : " <<  to_string(t_8) <<  " : " << to_string(t_7) << " : " << to_string(t_6) <<std::endl;
            // std::cout << "fps runing_time:" << to_string(t_1) << " : " <<  to_string(t_2) <<  " : " << to_string(t_3) << std::endl;
            // std::cout << "fps all time " << t_0<< std::endl;
        //    }
            DEBUG(":::::::::single_SDK end:::::");
        }
        else
        {
            switch_SDK_TResult(detections, t_result);
        }
    }
}
void AriManager::single_SDK(const int cam_id, const void *img, TResult* t_result)
{
    TImage *frame_img = (TImage*)img;
    cv::Mat frame(Size(frame_img->width, frame_img->height), CV_8UC3);
@@ -59,8 +142,7 @@
    // cv::waitKey(0);
    this->detector->detect(batch_img, batch_res);
    t_result.targets = (Target*)malloc(sizeof(Target)*batch_res[0].size());
    // 将算法结果转化为标准的格式(以目标检测为例)""
    t_result->targets = (Target*)malloc(sizeof(Target)*batch_res[0].size());
    int w_count = 0;
    for (const auto &result_box:batch_res[0])
    {
@@ -74,31 +156,277 @@
            target.rect.right =  result_box.rect.x + result_box.rect.width;
            target.rect.bottom = result_box.rect.y + result_box.rect.height;
            target.confidence = result_box.prob*100;  // 置信度转化成百分制
            target.confidence = result_box.prob*100;
            // target.id = 1; //
            //  target.attribute 可根据实际情况来添加,输出格式要求是json格式
            //string attribute_json = "{";
            //attribute_json += "\"smokingScore\":" + to_string(track->smokeScore)+",";
            //if(attribute_json.length()>2)
            //{
            //    attribute_json = attribute_json.substr(0, attribute_json.length()-1) +"}";
            //    target.attribute = new char[strlen(attribute_json.c_str())+1];
            //    target.attribute_size = strlen(attribute_json.c_str());
            //    strcpy(target.attribute, attribute_json.c_str());
            //}
            float mv_velocity = 0;
            int runScore = 0;
            string attribute_json = "{";
            t_result.targets[w_count] = target;
            if (m_staticStruct::fall_rate!=0)
            {
                // detect_fall(tmpbox, track);
                attribute_json += "\"fallScore\":" + to_string(0)+",";
            }
            if (m_staticStruct::mv_velocity!=0)
            {
                attribute_json += "\"runScore\":" + to_string(0)+",";
            }
            attribute_json += "\"hatScore\":" + to_string(0)+",";
            attribute_json += "\"helmetScore\":" + to_string(0)+",";
            attribute_json += "\"headScore\":" + to_string(0)+",";
            attribute_json += "\"maskScore\":" + to_string(0)+",";
            attribute_json += "\"smokingScore\":" + to_string(0)+",";
            DEBUG("image attribute_json:: "+ attribute_json);
            if(attribute_json.length()>2)
            {
                //转换输出的json格式 {"fallScore":100,"runScore":15.8,"wanderScore":10}
                attribute_json = attribute_json.substr(0, attribute_json.length()-1) +"}";
                target.attribute = new char[strlen(attribute_json.c_str())+1];
                target.attribute_size = strlen(attribute_json.c_str());
                strcpy(target.attribute, attribute_json.c_str());
            }
            t_result->targets[w_count] = target;
            w_count ++;
        }
    }
    std::cout << "eve batch_res size:: "<< batch_res[0].size() << " w_count: " << w_count <<std::endl;
    t_result.count = w_count;
    draw_SDK_result(cam_id, frame, t_result); //多线程无法调用绘图
    t_result->count = w_count;
    // draw_SDK_result(cam_id, frame, t_result);
}
void AriManager::init_target(Target *t){
void AriManager::switch_SDK_TResult(DETECTIONS detections, TResult *t_result)
{
    t_result->targets = (Target*)malloc(sizeof(Target) * detections.size());
    int w_count = 0;
    for(auto& detection :detections)
    {
        Target target;
        init_target(&target);
        // RESULT_STRUCT result;
        DETECTBOX tmpbox = detection.tlwh;
        istringstream iss(random_int(6));
        iss >> target.id;
        target.rect.left = tmpbox(0);
        target.rect.top =  tmpbox(1);
        target.rect.right = tmpbox(0) + tmpbox(2);
        target.rect.bottom = tmpbox(1) + tmpbox(3);
        target.confidence = detection.confidence*100;
        float mv_velocity = 0;
        int runScore = 0;
        string attribute_json = "{";
        if (m_staticStruct::fall_rate!=0)
        {
            // detect_fall(tmpbox, track);
            attribute_json += "\"fallScore\":" + to_string(detection.fallScore)+",";
        }
        if (m_staticStruct::mv_velocity!=0)
        {
            attribute_json += "\"runScore\":" + to_string(detection.runScore)+",";
        }
        attribute_json += "\"hatScore\":" + to_string(detection.hatScore)+",";
        attribute_json += "\"helmetScore\":" + to_string(detection.helmetScore)+",";
        attribute_json += "\"headScore\":" + to_string(detection.headScore)+",";
        attribute_json += "\"maskScore\":" + to_string(detection.maskScore)+",";
        attribute_json += "\"smokingScore\":" + to_string(detection.smokeScore)+",";
        DEBUG("image attribute_json:: "+ attribute_json);
        if(attribute_json.length()>2)
        {
            //转换输出的json格式 {"fallScore":100,"runScore":15.8,"wanderScore":10}
            attribute_json = attribute_json.substr(0, attribute_json.length()-1) +"}";
            target.attribute = new char[strlen(attribute_json.c_str())+1];
            target.attribute_size = strlen(attribute_json.c_str());
            strcpy(target.attribute, attribute_json.c_str());
        }
        t_result->targets[w_count] = target;
        w_count ++;
    }
    t_result->count = w_count;
}
// 转换成SDK 想要的结果
void AriManager::switch_SDK_TResult(int cam_id, cv::Mat img, DETECTIONS detections, TResult *t_result)
{
    t_result->targets = (Target*)malloc(sizeof(Target) * this->CAMERAS_VCT[cam_id]->tracks.size());
    int w_count = 0;
    for(auto& track :this->CAMERAS_VCT[cam_id]->tracks)
    {
        // if(not track->isCurrent) //当前画面没有则返回
        //     continue;
        Target target;
        init_target(&target);
        // RESULT_STRUCT result;
       if(!track->is_confirmed() || track->time_since_update >= 1) continue;
        // if(track->is_confirmed() && track->time_since_update >= 1) continue;
        /*
         * 算法思想:跟踪器跟踪的时候,是否能够强制将预测错位置的box框强制更新成新的box框,而id不发生变化
         * */
//         DETECTBOX tmpbox = track->to_tlwh();
        DETECTBOX tmpbox = track->to_xywh();
        target.rect.left = tmpbox(0);
        target.rect.top =  tmpbox(1);
        target.rect.right = tmpbox(0) + tmpbox(2);
        target.rect.bottom = tmpbox(1) + tmpbox(3);
        // DEBUG((boost::format("%s:%d, %s:%d, %s:%d, %s:%d") %"id:" %track->track_id %"conf:" %track->confidence %", to tmpbox y:" %tmpbox(1) %", tmpbox(3) h:" %tmpbox(3)).str());
        target.id = track->track_id;
        target.confidence = track->confidence;
        float mv_velocity = 0;
        int runScore = 0;
        string attribute_json = "{";
        if (m_staticStruct::fall_rate!=0)
        {
            // detect_fall(tmpbox, track);
            attribute_json += "\"fallScore\":" + to_string(track->rateScale)+"," + "\"fallTime\":" + to_string(track->fall_total_time) + ",";
        }
        if (m_staticStruct::mv_velocity!=0)
        {
            if(track->isRuning)
            {
                mv_velocity = detect_runing(tmpbox, track, img);
                float run_velocity = mv_velocity;
                if(tmpbox(2)/tmpbox(3)<0)
                {
                    run_velocity*=(img.cols*img.rows)/(tmpbox(2)*tmpbox(3));
                }else
                {
                    run_velocity*=10;
                }
//                    std::cout << mv_velocity <<  "mv_velocity::::::::::" << run_velocity << "::::::::::::"<<img.cols*img.rows<<":::"<<tmpbox(2)*tmpbox(3)<<std::endl;
                runScore = (track->confidence+2)*int(std::min(4*run_velocity, 100.0f));
                attribute_json += "\"runScore\":" + to_string(runScore)+",";
            }else if(track->is_hat)
            {
                mv_velocity = detect_runing(tmpbox, track, img);
                float run_velocity = mv_velocity;
                if(tmpbox(2)/tmpbox(3)<0)
                {
                    run_velocity*=(img.cols*img.rows)/(tmpbox(2)*tmpbox(3));
                }else
                {
                    run_velocity*=15;
                }
//                    std::cout << mv_velocity <<  "mv_velocity::::::::::" << run_velocity << "::::::::::::"<<img.cols*img.rows<<":::"<<tmpbox(2)*tmpbox(3)<<std::endl;
                runScore = int(std::min(4*run_velocity, 100.0f));
                attribute_json += "\"runScore\":" + to_string(runScore)+",";
            }else
            attribute_json += "\"runScore\":" + to_string(runScore)+",";
        }
        //std::cout << track->track_id <<"-- human wander last time:" << track->last_time << ":" << m_staticStruct::wander_time <<std::endl;
        if(m_staticStruct::wander_time!=0)
        {
            if (track->last_time>m_staticStruct::wander_time)
                track->isWander = true;
            else
                track->isWander = false;
            attribute_json += "\"wanderTime\":" + to_string(track->last_time)+",";
        }
       if(track->is_hat)
       {
           attribute_json += "\"hatScore\":" + to_string(track->hatScore)+",";
       }else
       {
           attribute_json += "\"hatScore\":" + to_string(10)+",";
       }
       if(track->is_mask)
       {
           attribute_json += "\"maskScore\":" + to_string(track->maskScore)+",";
       }else
       {
           attribute_json += "\"maskScore\":" + to_string(10)+",";
       }
        if(track->is_smoke)
        {
            attribute_json += "\"smokingScore\":" + to_string(track->smokeScore)+",";
        }else
        {
            attribute_json += "\"smokingScore\":" + to_string(10)+",";
        }
//            cout << ":::::::::::::"<<attribute_json << endl;
        if(attribute_json.length()>2)
        {
            //转换输出的json格式 {"fallScore":100,"runScore":15.8,"wanderScore":10}
            attribute_json = attribute_json.substr(0, attribute_json.length()-1) +"}";
            target.attribute = new char[strlen(attribute_json.c_str())+1];
            target.attribute_size = strlen(attribute_json.c_str());
            strcpy(target.attribute, attribute_json.c_str());
        }
        t_result->targets[w_count] = target;
        w_count ++;
    }
    t_result->count = w_count;
//    printf("================================%d\n\n\n\n", t_result->count);
#ifdef S_DEBUG
    draw_SDK_result(cam_id, img, t_result);
#endif
}
void AriManager::single_tracker(int cam_id, DETECTIONS& detections, char* img_time)
{
//    DETECTIONS detections = deal_features(boxes, feats_vec); // 使用传递特征追踪时需要打开该方法
//    printf("cam_id::::%d",cam_id);
    std::string str2 = img_time;
    img_time[str2.find_last_of(":")] = '.';
//    DEBUG( img_time);
    auto cam_tracker = this->CAMERAS_VCT[cam_id];
    DEBUG("single_tracker start:: ");
    cam_tracker->predict();
    cam_tracker->update(CAMERAS_VCT, detections, cam_id, img_time);
    DEBUG("single_tracker::");
    this->CAMERAS_VCT[cam_id] = cam_tracker;
}
void AriManager::init_target(Target *t)
{
    t->attribute = NULL;
    t->feature = NULL;
    t->id = 0;
@@ -107,3 +435,4 @@
    t->attribute_size = 0;
    t->feature_size = 0;
}
src/core/ari_manager.h
@@ -8,6 +8,10 @@
#include "config.h"
#include "detector.h"
#include "../utils/draw_util.h"
#include "../tracker_tools/tracker.h"
#include "detecter_manager.h"
// #include "../utils/result_util.h"
using namespace std;
using namespace cv;
@@ -18,14 +22,26 @@
    int cam_id; //指定待追踪摄像机编号
    Mat frame;
    std::vector<std::shared_ptr<tracker>> CAMERAS_VCT;
    std::vector<DETECTIONS> DETECTION_VCT;
private:
    std::shared_ptr<Detector> detector;
    static void init_target(Target *t);
    void switch_SDK_TResult(int cam_id, cv::Mat img, DETECTIONS detections, TResult *t_result);
    void switch_SDK_TResult(DETECTIONS detections, TResult *t_result);
    void single_tracker(int cam_id, DETECTIONS& detections, char* img_time);
public:
    AriManager();
    ~AriManager();
    void single_SDK(const int cam_id, const void *img, TResult& t_result); // 检测+追踪 接口(SDK封装)
    void release();
    void init_load_model();
    bool add_cam(int cam_id);
    // void single_detect_tracking(int cam_id, cv::Mat frame, FRAME_RESULT result_vec); // 检测+追踪 接口
    void single_SDK(const int cam_id, const void *img, TResult *t_result, char* img_time, const char* mode);
    void single_SDK(const int cam_id, const void *img, TResult* t_result);
    // void mul_detect_tracking(std::vector<int> cam_ids, std::vector<cv::Mat> frame_vec, std::vector<FRAME_RESULT>&  results_vec); // 多摄像头追踪
};
#endif //INC_01_CPP_SORT_TRACKER_MANAGER_H
src/core/detecter_manager.cpp
New file
@@ -0,0 +1,126 @@
//
// Created by Scheaven on 2019/11/19.
//
#include "detecter_manager.h"
#include <thread>
#include <unistd.h>
#include <cstdlib>
DetecterManager* DetecterManager::instance = NULL;
DetecterManager* DetecterManager::getInstance()
{
    if(instance==NULL)
    {
        instance = new DetecterManager();
    }
    return instance;
}
DetecterManager::DetecterManager()
{
    Config config;
    // config.net_type = COMMON;
    if(m_staticStruct::type==2)
        config.net_type = SMALL;
    else
        config.net_type = COMMON;
    this->detector = std::shared_ptr<Detector>(new Detector());
    this->detector->init(config);
    std::cout << "loading detector model......" << std::endl;
}
DetecterManager::~DetecterManager()
{
}
void DetecterManager::release()
{
    // Detector::getInstance()->release();
    delete DetecterManager::instance;
    DetecterManager::instance = NULL;
}
void DetecterManager::detecter_main(cv::Mat &mat_image, DETECTIONS& detection)
{
    std::vector<BatchResult> batch_res;
    std::vector<cv::Mat> batch_img;
    batch_img.push_back(mat_image.clone());
    this->detector->detect(batch_img, batch_res);
    encoder_features(batch_res, detection);
  //  show_result(result_vec);
//    draw_boxes(mat_image, result_vec);
}
void DetecterManager::encoder_features(std::vector<BatchResult> boxes,  DETECTIONS &detection)
{
    std::vector<float> confidences;
    std::vector<int> human_index;
    int result_index=0;
    for (const auto &result_box:boxes[0])
    {
//        #ifdef S_DEBUG
//                printf("--%d-%d-%d-%d-%d---result_box-----\n", result_box.obj_id, result_box.x, result_box.y, result_box.w, result_box.h);
//        #endif
        if(result_box.id == 1)
        {
            // cv::Rect box = cv::Rect(result_box.x,result_box.y,result_box.w,result_box.h);
            // get_detections(DETECTBOX(box.x, box.y,box.width,  box.height), confidences[idx],d);
            DETECTION_ROW tmpRow;
            tmpRow.tlwh = DETECTBOX(result_box.rect.x,result_box.rect.y,result_box.rect.width,result_box.rect.height); //DETECTBOX(x, y, w, h);
            tmpRow.confidence = result_box.prob*100;
            tmpRow.obj_id = 0;
            tmpRow.is_hat = true;
            tmpRow.is_mask = true;
            tmpRow.is_smoke = true;
            tmpRow.hatScore = 0;
            tmpRow.maskScore = 0;
            tmpRow.smokeScore = 0;
            // tmpRow.img_time = this->img_time;
            tmpRow.isFall = false;
            tmpRow.fallScore = 0;
            tmpRow.runScore = 0;
            tmpRow.isRun = false;
//            tmpRow.human_face = nullptr;
            int sub_box_index=0;
            human_index.push_back(result_index);
            detection.push_back(tmpRow);
        }
        result_index++;
    }
}
// bool DetecterManager::sort_score(bbox_t box1, bbox_t box2)
// {
//     return (box1.prob>box2.prob);
// }
// float DetecterManager::box_iou(bbox_t box1, bbox_t box2)
// {
//     int x1 = std::max(box1.x, box2.x);
//     int y1 = std::max(box1.y, box2.y);
//     int x2 = std::min((box1.x+box1.w),(box2.x+box2.w));
//     int y2 = std::min((box1.y+box1.h),(box2.y+box2.h));
//     float over_area = (x2-x1)*(y2-y1);
// //    printf("over_ares---%f ----%d----%d\n", over_area, box1.w*box1.h, box2.w*box2.h);
//     float iou = over_area/((box1.w*box1.h<box2.w*box2.h)?box1.w*box1.h:box2.w*box2.h);
//     return iou;
// }
void DetecterManager::set_imgTime(long img_time)
{
    this->img_time = img_time;
}
src/core/detecter_manager.h
New file
@@ -0,0 +1,46 @@
//
// Created by Scheaven on 2019/11/19.
//
#ifndef DETECTER_MANAGER_H
#define DETECTER_MANAGER_H
#include "../config.h"
#include "../tracker_tools/model.h"
#include "../utils/draw_util.h"
// #include "../utils/config_util.h"
#include "../utils/time_util.h"
#include "../std_target.h"
#include "detector.h"
using namespace std;
class DetecterManager {
private:
    std::vector<cv::Rect> boxes;
    std::shared_ptr<Detector> detector;
    struct timeval sys_t1, sys_t2, diff1;
//    Detector detector("../cfg/yolov3.cfg", "../model_dump/yolov3.weights");
    // bool sort_score(bbox_t box1, bbox_t box2);
    // float box_iou(bbox_t box1, bbox_t box2);
public:
    static DetecterManager* instance;
    static DetecterManager* getInstance();
    long img_time;
public:
    DetecterManager();
    ~DetecterManager();
    void release();
    void detecter_main(cv::Mat &mat_image,  DETECTIONS& detection);
    void ex_features(string in_path);
public:
    void encoder_features(std::vector<BatchResult> boxes, DETECTIONS& detection);
    void set_imgTime(long img_time);
};
#endif //INC_04_S_MUTICAM_TRACKING_DETECTER_MANAGER_H
src/detecter_tools/detector.cpp
@@ -95,9 +95,9 @@
void Detector::build_net()
{
    if(_config.net_type == COMMON)
        _p_net = std::unique_ptr<Detecter>{new Detecter(_info,_infer_param,1)};
    else{
    if(_config.net_type == SMALL)
        _p_net = std::unique_ptr<Detecter>{new Detecter(_info,_infer_param,2)};
    else{
        _p_net = std::unique_ptr<Detecter>{new Detecter(_info,_infer_param,1)};
    }
}
src/detecter_tools/model.cpp
@@ -268,10 +268,10 @@
void Detecter::setOutput(int type)
{
    m_OutputTensors.clear();
    printf("0-0-0-0-0-0------------------%d",type);
    if(type==2)
        for (int i = 0; i < 2; ++i)
        {
            TensorInfo outputTensor;
            outputTensor.numClasses = CLASS_BUM;
            outputTensor.blobName = "yolo_" + std::to_string(i);
@@ -323,17 +323,7 @@
        {
            TensorInfo outputTensor;
            outputTensor.numClasses = CLASS_BUM;
            outputTensor.blobName = "yolo_" + to_string(i);
            // if (i==0)
            // {
            //     outputTensor.blobName = "139_convolutional_reshape_2";
            // }else if (i==1)
            // {
            //     outputTensor.blobName = "150_convolutional_reshape_2";
            // }else if (i==2)
            // {
            //     outputTensor.blobName = "161_convolutional_reshape_2";
            // }
            outputTensor.blobName = "yolo_" + std::to_string(i);
            outputTensor.gridSize = (m_InputH / 32) * pow(2, 2-i);
            outputTensor.grid_h = (m_InputH / 32) * pow(2, 2-i);
            outputTensor.grid_w = (m_InputW / 32) * pow(2, 2-i);
src/detecter_tools/model.h
@@ -13,7 +13,7 @@
#include <stdint.h>
#include <string>
#include <vector>
#include "../utils/timer_utils.hpp"
#include "../utils/time_util.h"
#include "../config.h"
#include "opencv2/opencv.hpp"
src/h_interface.cpp
@@ -9,23 +9,68 @@
string m_staticStruct::model_path = "path";
int m_staticStruct::type = 1;
bool m_staticStruct::isTrack= true;
int m_staticStruct::max_cam_num = 0;
int m_staticStruct::wander_time = 0;
float m_staticStruct::mv_velocity = 0;
float m_staticStruct::fall_rate = 0;
// 创建
API void* create(const char *conf, int *max_chan)
{
    // CLog::Initialize("/opt/vasystem/bin/models/baseDetector/log.properties");
    CLog::Initialize("../config/log4cplus.properties");
    ReadJsonFromFile(conf);
    AriManager *handle = new AriManager();
    *max_chan = m_staticStruct::max_cam_num;
    for (int i = 1; i <= m_staticStruct::max_cam_num; ++i)
    {
        handle->add_cam(i);
    }
    Timer::getInstance()->reset();
    return handle;
}
// 原查找结果接口
API void* get_result(void *handle, const void *img, const int chan)
{
    AriManager *h = (AriManager*)handle;
    TResult *t_result = (TResult*)malloc(sizeof(TResult));
    init_TResult(t_result);
    h->single_SDK(chan, img, *t_result);
    Timer::getInstance()->out("eveTime before yolo");
    // h->single_SDK(chan, img, *t_result);
    Timer::getInstance()->out("eveTime runing yolo");
    return t_result;
}
API void* get_result2(void *handle, const void *img, const int chan, const char* timestamp, const char* mode)
{
    DEBUG("-----------------------begin------------ ");
    AriManager *h = (AriManager*)handle;
    TResult *t_result = (TResult*)malloc(sizeof(TResult));
    init_TResult(t_result);
    if(!m_staticStruct::isTrack)
    {
        Timer::getInstance()->out("get_result2 before yolo");
        h->single_SDK(chan, img, t_result);
        Timer::getInstance()->out("get_result2 runing yolo");
        return t_result;
    }
    h->single_SDK(chan, img, t_result, const_cast<char*>(timestamp), mode);
    DEBUG("--cam id:" + to_string(chan) + "  image human_count:" + to_string(t_result->count));
    for (int i = 0; i < t_result->count; ++i)
    {
        if(mode == "video"){
            DEBUG("--human_id:" + to_string(t_result->targets[i].id)+"  human_confidence:" + to_string(t_result->targets[i].confidence) + "  human_attribute:" + std::string(t_result->targets[i].attribute) +  "  human_top:" + to_string(t_result->targets[i].rect.top)+" human_left:" + to_string(t_result->targets[i].rect.left) + "  human_right:" + to_string(t_result->targets[i].rect.right)+ "  human_bottom:" + to_string(t_result->targets[i].rect.bottom));
        }
        else{
            DEBUG("human_confidence:" + to_string(t_result->targets[i].confidence) + "  human_top:" + to_string(t_result->targets[i].rect.top)+" human_left:" + to_string(t_result->targets[i].rect.left) + "  human_right:" + to_string(t_result->targets[i].rect.right)+ "  human_bottom:" + to_string(t_result->targets[i].rect.bottom));
        }
    }
    DEBUG("---------------------end over------------------------\n\n");
    return t_result;
}
@@ -51,7 +96,6 @@
    h = NULL;
}
// 读取Json文件
void ReadJsonFromFile(const char* filename)
{
    Json::Reader reader;
@@ -72,8 +116,19 @@
    {
        std::string model_path = root["param"]["model_path"].asString();
        int type = root["param"]["type"].asInt();
        bool isTrack = root["param"]["isTrack"].asBool();
        int max_cam_num = root["param"]["max_cam_num"].asInt();
        int wander_time = root["param"]["wander_time"].asInt();
        int mv_velocity = root["param"]["mv_velocity"].asFloat();
        int fall_rate = root["param"]["fall_rate"].asFloat();
        m_staticStruct::model_path  = model_path;
        m_staticStruct::type  = type;
        m_staticStruct::isTrack = isTrack;
        m_staticStruct::max_cam_num  = max_cam_num;
        m_staticStruct::wander_time = wander_time;
        m_staticStruct::mv_velocity = mv_velocity;
        m_staticStruct::fall_rate = fall_rate;
    }
    in.close();
}
@@ -83,4 +138,3 @@
    t->count = 0;
    t->targets = nullptr;
}
src/h_interface.h
@@ -11,12 +11,14 @@
#endif
#define API extern "C" __attribute__((visibility ("default")))
API void* create(const char *conf, int *max_chan);
API void release(void* handle);
API void* get_result(void *handle, const void *img, const int chan);
API void* get_result2(void *handle, const void *img, const int chan,const char* timestamp, const char* mode);
API void release_result(void *res);
void ReadJsonFromFile(const char* filename); // 读取json文件
void ReadJsonFromFile(const char* filename);
int setCamConfig(const char* data);
int ReadJsonStr(void* handle, const char* data);
src/tracker_tools/dataType.h
New file
@@ -0,0 +1,45 @@
#pragma once
#ifndef DATATYPE_H
#define DATATYPEH
#include <cstddef>
#include <vector>
#include <Eigen/Core>
#include <Eigen/Dense>
#define FEATURE_DIM 128 // 特征抽取的維度
typedef unsigned char uint8;
typedef Eigen::Matrix<float, 1, 4, Eigen::RowMajor> DETECTBOX;
typedef Eigen::Matrix<float, -1, 4, Eigen::RowMajor> DETECTBOXSS;
typedef Eigen::Matrix<float, 1, 128, Eigen::RowMajor> FEATURE;
typedef Eigen::Matrix<float, Eigen::Dynamic, 128, Eigen::RowMajor> FEATURESS;
//typedef std::vector<FEATURE> FEATURESS;
//Kalmanfilter
//typedef Eigen::Matrix<float, 8, 8, Eigen::RowMajor> KAL_FILTER;
typedef Eigen::Matrix<float, 1, 8, Eigen::RowMajor> KAL_MEAN;
typedef Eigen::Matrix<float, 8, 8, Eigen::RowMajor> KAL_COVA;
typedef Eigen::Matrix<float, 1, 4, Eigen::RowMajor> KAL_HMEAN;
typedef Eigen::Matrix<float, 4, 4, Eigen::RowMajor> KAL_HCOVA;
using KAL_DATA = std::pair<KAL_MEAN, KAL_COVA>;
using KAL_HDATA = std::pair<KAL_HMEAN, KAL_HCOVA>;
//main
using RESULT_DATA = std::pair<int, DETECTBOX>;
//tracker:
using TRACKER_DATA = std::pair<uint64_t, FEATURESS>;
using MATCH_DATA = std::pair<int, int>;
typedef struct t{
    std::vector<MATCH_DATA> matches;
    std::vector<int> unmatched_tracks;
    std::vector<int> unmatched_detections;
}TRACHER_MATCHD;
//linear_assignment:
typedef Eigen::Matrix<float, -1, -1, Eigen::RowMajor> DYNAMICM;
#endif // DATATYPE_H
src/tracker_tools/feature_util.cpp
New file
@@ -0,0 +1,28 @@
//
// Created by Scheaven on 2020/9/3.
//
#include "feature_util.h"
double feature_distance(FEATURE feat1, FEATURE feat2)
{
    double FeatA=0.0, FeatB=0.0, score=0.0;
    for (int i = 0; i < 128; i++)
    {
        FeatA += double(feat1[i])*double(feat1[i]);
        FeatB += double(feat2[i])*double(feat2[i]);
        score += double(feat1[i])*double(feat2[i]);
    }
    FeatA = sqrt(FeatA);
    FeatB = sqrt(FeatB);
    score = score / (FeatA * FeatB);
    if (score < 0) {
        score = 0;
    }
    printf("--评分---%f--",score);
    return score;
}
src/tracker_tools/feature_util.h
New file
@@ -0,0 +1,14 @@
//
// Created by Scheaven on 2020/9/3.
//
#ifndef FEATURE_UTIL_H
#define FEATURE_UTIL_H
#include "dataType.h"
#include "../config.h"
double feature_distance(FEATURE feat1, FEATURE feat2);
#endif //FEATURE_UTIL_H
src/tracker_tools/kalmfilter.cpp
New file
@@ -0,0 +1,155 @@
#include "kalmfilter.h"
#include <Eigen/Cholesky>
const double KalmFilter::chi2inv95[10] = {
    0,
    3.8415,
    5.9915,
    7.8147,
    9.4877,
    11.070,
    12.592,
    14.067,
    15.507,
    16.919
};
KalmFilter::KalmFilter()
{
    int ndim = 4;
    double dt = 1.;
    _motion_mat = Eigen::MatrixXf::Identity(8, 8);
    for(int i = 0; i < ndim; i++) {
        _motion_mat(i, ndim+i) = dt;
    }
    _update_mat = Eigen::MatrixXf::Identity(4, 8);
    this->_std_weight_position = 1. / 20;
    this->_std_weight_velocity = 1. / 160;
}
KalmFilter::~KalmFilter()
{
}
KAL_DATA KalmFilter::initiate(const DETECTBOX &measurement)
{
    DETECTBOX mean_pos = measurement;
    DETECTBOX mean_vel;
    for(int i = 0; i < 4; i++) mean_vel(i) = 0;
    KAL_MEAN mean;
    for(int i = 0; i < 8; i++){
        if(i < 4) mean(i) = mean_pos(i);
        else mean(i) = mean_vel(i - 4);
    }
    KAL_MEAN std;
    std(0) = 2 * _std_weight_position * measurement[3];
    std(1) = 2 * _std_weight_position * measurement[3];
    std(2) = 1e-2;
    std(3) = 2 * _std_weight_position * measurement[3];
    std(4) = 10 * _std_weight_velocity * measurement[3];
    std(5) = 10 * _std_weight_velocity * measurement[3];
    std(6) = 1e-5;
    std(7) = 10 * _std_weight_velocity * measurement[3];
    KAL_MEAN tmp = std.array().square();
    KAL_COVA var = tmp.asDiagonal();
    return std::make_pair(mean, var);
}
void KalmFilter::predict(KAL_MEAN &mean, KAL_COVA &covariance)
{
    //revise the data;
    DETECTBOX std_pos;
    std_pos << _std_weight_position * mean(3),
            _std_weight_position * mean(3),
            1e-2,
            _std_weight_position * mean(3);
    DETECTBOX std_vel;
    std_vel << _std_weight_velocity * mean(3),
            _std_weight_velocity * mean(3),
            1e-5,
            _std_weight_velocity * mean(3);
    KAL_MEAN tmp;
    tmp.block<1,4>(0,0) = std_pos;
    tmp.block<1,4>(0,4) = std_vel;
    tmp = tmp.array().square();
    KAL_COVA motion_cov = tmp.asDiagonal();
    KAL_MEAN mean1 = this->_motion_mat * mean.transpose();
    KAL_COVA covariance1 = this->_motion_mat * covariance *(_motion_mat.transpose());
    covariance1 += motion_cov;
    mean = mean1;
    covariance = covariance1;
}
KAL_HDATA KalmFilter::project(const KAL_MEAN &mean, const KAL_COVA &covariance)
{
    DETECTBOX std;
    std << _std_weight_position * mean(3), _std_weight_position * mean(3),
            1e-1, _std_weight_position * mean(3);
    KAL_HMEAN mean1 = _update_mat * mean.transpose();
    KAL_HCOVA covariance1 = _update_mat * covariance * (_update_mat.transpose());
    Eigen::Matrix<float, 4, 4> diag = std.asDiagonal();
    diag = diag.array().square().matrix();
    covariance1 += diag;
//    covariance1.diagonal() << diag;
    return std::make_pair(mean1, covariance1);
}
KAL_DATA
KalmFilter::update(
        const KAL_MEAN &mean,
        const KAL_COVA &covariance,
        const DETECTBOX &measurement)
{
    KAL_HDATA pa = project(mean, covariance);
    KAL_HMEAN projected_mean = pa.first;
    KAL_HCOVA projected_cov = pa.second;
    //chol_factor, lower =
    //scipy.linalg.cho_factor(projected_cov, lower=True, check_finite=False)
    //kalmain_gain =
    //scipy.linalg.cho_solve((cho_factor, lower),
    //np.dot(covariance, self._upadte_mat.T).T,
    //check_finite=False).T
    Eigen::Matrix<float, 4, 8> B = (covariance * (_update_mat.transpose())).transpose();
    Eigen::Matrix<float, 8, 4> kalman_gain = (projected_cov.llt().solve(B)).transpose(); // eg.8x4
    Eigen::Matrix<float, 1, 4> innovation = measurement - projected_mean; //eg.1x4
    auto tmp = innovation*(kalman_gain.transpose());
    KAL_MEAN new_mean = (mean.array() + tmp.array()).matrix();
    KAL_COVA new_covariance = covariance - kalman_gain*projected_cov*(kalman_gain.transpose());
    return std::make_pair(new_mean, new_covariance);
}
Eigen::Matrix<float, 1, -1>
KalmFilter::gating_distance(
        const KAL_MEAN &mean,
        const KAL_COVA &covariance,
        const std::vector<DETECTBOX> &measurements,
        bool only_position)
{
    KAL_HDATA pa = this->project(mean, covariance);
    // if(only_position) {
    //     printf("not implement!");
    //     exit(0);
    // }
    KAL_HMEAN mean1 = pa.first;
    KAL_HCOVA covariance1 = pa.second;
//    Eigen::Matrix<float, -1, 4, Eigen::RowMajor> d(size, 4);
    DETECTBOXSS d(measurements.size(), 4);
    int pos = 0;
    for(DETECTBOX box:measurements) {
        d.row(pos++) = box - mean1;
    }
    Eigen::Matrix<float, -1, -1, Eigen::RowMajor> factor = covariance1.llt().matrixL();
    Eigen::Matrix<float, -1, -1> z = factor.triangularView<Eigen::Lower>().solve<Eigen::OnTheRight>(d).transpose();
    auto zz = ((z.array())*(z.array())).matrix();
    auto square_maha = zz.colwise().sum();
    return square_maha;
}
src/tracker_tools/kalmfilter.h
New file
@@ -0,0 +1,32 @@
#ifndef KALMFILTER_H
#define KALMFILTER_H
#include "dataType.h"
class KalmFilter
{
public:
    static const double chi2inv95[10];
    KalmFilter();
    ~KalmFilter();
    KAL_DATA initiate(const DETECTBOX& measurement);
    void predict(KAL_MEAN& mean, KAL_COVA& covariance);
    KAL_HDATA project(const KAL_MEAN& mean, const KAL_COVA& covariance);
    KAL_DATA update(const KAL_MEAN& mean,
                    const KAL_COVA& covariance,
                    const DETECTBOX& measurement);
    Eigen::Matrix<float, 1, -1> gating_distance(
            const KAL_MEAN& mean,
            const KAL_COVA& covariance,
            const std::vector<DETECTBOX>& measurements,
            bool only_position = false);
private:
    Eigen::Matrix<float, 8, 8, Eigen::RowMajor> _motion_mat;
    Eigen::Matrix<float, 4, 8, Eigen::RowMajor> _update_mat;
    float _std_weight_position;
    float _std_weight_velocity;
};
#endif // KALMFILTER_H
src/tracker_tools/linear_assignment.cpp
New file
@@ -0,0 +1,161 @@
#include "linear_assignment.h"
#include "../Munkres_assign/hungarianoper.h"
#include <map>
linear_assignment *linear_assignment::instance = NULL;
linear_assignment::linear_assignment()
{
}
linear_assignment *linear_assignment::getInstance()
{
    if(instance == NULL) instance = new linear_assignment();
    return instance;
}
linear_assignment::~linear_assignment()
{
    delete instance;
}
TRACHER_MATCHD
linear_assignment::matching_cascade(
        tracker *distance_metric,
        tracker::GATED_METRIC_FUNC distance_metric_func,
        float max_distance,
        int cascade_depth,
        std::vector<std::shared_ptr<Track>> &tracks,
        const DETECTIONS &detections,
        std::vector<int>& track_indices,
        std::vector<int> detection_indices)
{
    TRACHER_MATCHD res;
    for(size_t i = 0; i < detections.size(); i++) {
        detection_indices.push_back(int(i));
    }
    std::vector<int> unmatched_detections;
    unmatched_detections.assign(detection_indices.begin(), detection_indices.end());
    res.matches.clear();
    std::vector<int> track_indices_l;
    std::map<int, int> matches_trackid;
    for(int level = 0; level < cascade_depth; level++) {
        if(unmatched_detections.size() == 0) break; //No detections left;
        track_indices_l.clear();
        for(int k:track_indices) {
            if(tracks[k]->time_since_update == 1+level)
                track_indices_l.push_back(k);
        }
        if(track_indices_l.size() == 0) continue; //Nothing to match at this level.
        TRACHER_MATCHD tmp = min_cost_matching(
                    distance_metric, distance_metric_func,
                    max_distance, tracks, detections, track_indices_l,
                    unmatched_detections);
        unmatched_detections.assign(tmp.unmatched_detections.begin(), tmp.unmatched_detections.end());
        for(size_t i = 0; i < tmp.matches.size(); i++) {
            MATCH_DATA pa = tmp.matches[i];
            res.matches.push_back(pa);
            matches_trackid.insert(pa);
        }
    }
    res.unmatched_detections.assign(unmatched_detections.begin(), unmatched_detections.end());
    for(size_t i = 0; i < track_indices.size(); i++) {
        int tid = track_indices[i];
        if(matches_trackid.find(tid) == matches_trackid.end())
            res.unmatched_tracks.push_back(tid);     // 未匹配的追加
    }
    return res;
}
TRACHER_MATCHD
linear_assignment::min_cost_matching(tracker *distance_metric,
        tracker::GATED_METRIC_FUNC distance_metric_func,
        float max_distance,
        std::vector<std::shared_ptr<Track>> &tracks,
        const DETECTIONS &detections,
        std::vector<int> &track_indices,
        std::vector<int> &detection_indices)
{
    TRACHER_MATCHD res;
    if((detection_indices.size() == 0) || (track_indices.size() == 0)) {
        res.matches.clear();
        res.unmatched_tracks.assign(track_indices.begin(), track_indices.end());
        res.unmatched_detections.assign(detection_indices.begin(), detection_indices.end());
        return res;
    }
    DYNAMICM cost_matrix = (distance_metric->*(distance_metric_func))( // distance_metric_func其实是调用tracker.cpp中的iou_cost 函数
                tracks, detections, track_indices, detection_indices);
    for(int i = 0; i < cost_matrix.rows(); i++) {
        for(int j = 0; j < cost_matrix.cols(); j++) {
            float tmp = cost_matrix(i,j);
            if(tmp > max_distance) cost_matrix(i,j) = max_distance + 1e-5;
        }
    }
    Eigen::Matrix<float, -1, 2, Eigen::RowMajor> indices = HungarianOper::Solve(cost_matrix);
    res.matches.clear();
    res.unmatched_tracks.clear();
    res.unmatched_detections.clear();
    for(size_t col = 0; col < detection_indices.size(); col++) {
        bool flag = false;
        for(int i = 0; i < indices.rows(); i++)
            if(indices(i, 1) == col) { flag = true; break;}
        if(flag == false)res.unmatched_detections.push_back(detection_indices[col]);
    }
    for(size_t row = 0; row < track_indices.size(); row++) {
        bool flag = false;
        for(int i = 0; i < indices.rows(); i++)
            if(indices(i, 0) == row) { flag = true; break; }
        if(flag == false) res.unmatched_tracks.push_back(track_indices[row]);
    }
    for(int i = 0; i < indices.rows(); i++) {
        int row = indices(i, 0);
        int col = indices(i, 1);
        int track_idx = track_indices[row];
        int detection_idx = detection_indices[col];
        if(cost_matrix(row, col) > max_distance) {
            res.unmatched_tracks.push_back(track_idx);
            res.unmatched_detections.push_back(detection_idx);
        } else res.matches.push_back(std::make_pair(track_idx, detection_idx));
    }
    return res;
}
DYNAMICM
linear_assignment::gate_cost_matrix(
        KalmFilter *kf,
        DYNAMICM &cost_matrix,
        std::vector<std::shared_ptr<Track>> &tracks,
        const DETECTIONS &detections,
        const std::vector<int> &track_indices,
        const std::vector<int> &detection_indices,
        float gated_cost, bool only_position)
{
    int gating_dim = (only_position == true?2:4);
    double gating_threshold = KalmFilter::chi2inv95[gating_dim];
    std::vector<DETECTBOX> measurements;
    for(int i:detection_indices)
    {
        DETECTION_ROW t = detections[i];
        measurements.push_back(t.to_xyah());
    }
    for(size_t i  = 0; i < track_indices.size(); i++)
    {
        auto& track = tracks[track_indices[i]];
        Eigen::Matrix<float, 1, -1> gating_distance = kf->gating_distance(
                    track->mean, track->covariance, measurements, only_position);
        for (int j = 0; j < gating_distance.cols(); j++)
        {
            if (gating_distance(0, j) > gating_threshold)  cost_matrix(i, j) = gated_cost;
        }
    }
    return cost_matrix;
}
src/tracker_tools/linear_assignment.h
New file
@@ -0,0 +1,47 @@
#ifndef LINEAR_ASSIGNMENT_H
#define LINEAR_ASSIGNMENT_H
#include "dataType.h"
#include "tracker.h"
#define INFTY_COST 1e5
class tracker;
//for matching;
class linear_assignment
{
    linear_assignment();
    linear_assignment(const linear_assignment& );
    linear_assignment& operator=(const linear_assignment&);
    static linear_assignment* instance;
public:
    static linear_assignment* getInstance();
    ~linear_assignment();
    TRACHER_MATCHD matching_cascade(tracker* distance_metric,
            tracker::GATED_METRIC_FUNC distance_metric_func,
            float max_distance,
            int cascade_depth,
            std::vector<std::shared_ptr<Track>>& tracks,
            const DETECTIONS& detections,
            std::vector<int> &track_indices,
            std::vector<int> detection_indices = std::vector<int>());
    TRACHER_MATCHD min_cost_matching(
            tracker* distance_metric,
            tracker::GATED_METRIC_FUNC distance_metric_func,
            float max_distance,
            std::vector<std::shared_ptr<Track>>& tracks,
            const DETECTIONS& detections,
            std::vector<int>& track_indices,
            std::vector<int>& detection_indices);
    DYNAMICM gate_cost_matrix(
            KalmFilter* kf,
            DYNAMICM& cost_matrix,
            std::vector<std::shared_ptr<Track>>& tracks,
            const DETECTIONS& detections,
            const std::vector<int>& track_indices,
            const std::vector<int>& detection_indices,
            float gated_cost = INFTY_COST,
            bool only_position = true);
};
#endif // LINEAR_ASSIGNMENT_H
src/tracker_tools/model.cpp
New file
@@ -0,0 +1,23 @@
#include "model.h"
const float kRatio=0.5;
enum DETECTBOX_IDX {IDX_X = 0, IDX_Y, IDX_W, IDX_H };
DETECTBOX DETECTION_ROW::to_xyah() const
{//(centerx, centery, ration, h)
    DETECTBOX ret = tlwh;
    ret(0,IDX_X) += (ret(0, IDX_W)*kRatio);
    ret(0, IDX_Y) += (ret(0, IDX_H)*kRatio);
    ret(0, IDX_W) /= ret(0, IDX_H);
    return ret;
}
DETECTBOX DETECTION_ROW::to_tlbr() const
{//(x,y,xx,yy)
    DETECTBOX ret = tlwh;
    ret(0, IDX_X) += ret(0, IDX_W);
    ret(0, IDX_Y) += ret(0, IDX_H);
    return ret;
}
src/tracker_tools/model.h
New file
@@ -0,0 +1,46 @@
#ifndef MODEL_H
#define MODEL_H
#include "dataType.h"
#include <algorithm>
#include "../config.h"
// * Each rect's data structure.
// * tlwh: topleft point & (w,h).
// * confidence: detection confidence.
// * feature: the rect's 128d feature.
// */
class DETECTION_ROW
{
public:
    int obj_id;
    DETECTBOX tlwh;
    float confidence;
    FEATURE feature;
    DETECTBOX to_xyah() const;
    DETECTBOX to_tlbr() const;
    bool isFall;
    int fallScore;
    bool isRun;
    int runScore;
    bool is_hat;
    int hatScore;
    int helmetScore;
    int headScore;
    bool is_mask;
    int maskScore;
    bool is_smoke;
    int smokeScore;
};
typedef std::vector<DETECTION_ROW> DETECTIONS;
#endif // MODEL_H
src/tracker_tools/nn_matching.cpp
New file
@@ -0,0 +1,159 @@
#include "nn_matching.h"
using namespace Eigen;
NearNeighborDisMetric::NearNeighborDisMetric(
    NearNeighborDisMetric::METRIC_TYPE metric,
    float matching_threshold, int budget)
{
  if(metric == euclidean)
    {
      _metric = &NearNeighborDisMetric::_nneuclidean_distance;
    } else if (metric == cosine)
    {
      _metric = &NearNeighborDisMetric::_nncosine_distance;
    }
  this->mating_threshold = matching_threshold;
  this->budget = budget;
  this->samples.clear();
}
NearNeighborDisMetric::~NearNeighborDisMetric()
{
}
DYNAMICM
NearNeighborDisMetric::distance(
    const FEATURESS &features,
    const std::vector<uint64_t>& targets)
{
  DYNAMICM cost_matrix = Eigen::MatrixXf::Zero(targets.size(), features.rows());
  int idx = 0;
  for(uint64_t target:targets) {
      cost_matrix.row(idx) = (this->*_metric)(this->samples[target], features);
      idx++;
    }
  return cost_matrix;
}
DYNAMICM
NearNeighborDisMetric::cos_distance(const FEATURESS &features, std::map<uint64_t, FEATURESS> cos_samples)
{
  DYNAMICM cost_matrix = Eigen::MatrixXf::Zero(cos_samples.size(), features.rows());
  int idx = 0;
  std::map<uint64_t, FEATURESS>::iterator iter;
  for (iter=cos_samples.begin(); iter!= cos_samples.end(); iter++)
  {
    cost_matrix.row(idx) = (this->*_metric)(iter->second, features);
    idx++;
  }
  return cost_matrix;
}
void
NearNeighborDisMetric::partial_fit(
    std::vector<TRACKER_DATA> &tid_feats,
    std::vector<uint64_t> &active_targets)
{
  /*python code:
 * let feature(target_id) append to samples;
 * && delete not comfirmed target_id from samples.
 * update samples;
*/
  for(TRACKER_DATA& data:tid_feats) {
      uint64_t track_id = data.first;
      FEATURESS newFeatOne = data.second;
      if(samples.find(track_id) != samples.end()) {//append
          int oldSize = samples[track_id].rows();
          int addSize = newFeatOne.rows();
          int newSize = oldSize + addSize;
          if(newSize <= this->budget) {
              FEATURESS newSampleFeatures(newSize, 128);
              newSampleFeatures.block(0,0, oldSize, 128) = samples[track_id];
              newSampleFeatures.block(oldSize, 0, addSize, 128) = newFeatOne;
              samples[track_id] = newSampleFeatures;
            } else {
              if(oldSize < this->budget) {  //original space is not enough;
                  FEATURESS newSampleFeatures(this->budget, 128);
                  if(addSize >= this->budget) {
                      newSampleFeatures = newFeatOne.block(0, 0, this->budget, 128);
                    } else {
                      newSampleFeatures.block(0, 0, this->budget-addSize, 128) =
                          samples[track_id].block(addSize-1, 0, this->budget-addSize, 128).eval();
                      newSampleFeatures.block(this->budget-addSize, 0, addSize, 128) = newFeatOne;
                    }
                  samples[track_id] = newSampleFeatures;
                } else {//original space is ok;
                  if(addSize >= this->budget) {
                      samples[track_id] = newFeatOne.block(0,0, this->budget, 128);
                    } else {
                      samples[track_id].block(0, 0, this->budget-addSize, 128) =
                          samples[track_id].block(addSize-1, 0, this->budget-addSize, 128).eval();
                      samples[track_id].block(this->budget-addSize, 0, addSize, 128) = newFeatOne;
                    }
                }
            }
        } else {//not exit, create new one;
          samples[track_id] = newFeatOne;
        }
    }//add features;
  //erase the samples which not in active_targets;
  for(std::map<uint64_t, FEATURESS>::iterator i = samples.begin(); i != samples.end();) {
      bool flag = false;
      for(uint64_t j:active_targets) if(j == i->first) { flag=true; break; }
      if(flag == false)  samples.erase(i++);
      else i++;
    }
}
Eigen::VectorXf
NearNeighborDisMetric::_nncosine_distance(
    const FEATURESS &x, const FEATURESS &y)
{
  MatrixXf distances = _cosine_distance(x,y);
  VectorXf res = distances.colwise().minCoeff().transpose();
  return res;
}
Eigen::VectorXf
NearNeighborDisMetric::_nneuclidean_distance(
    const FEATURESS &x, const FEATURESS &y)
{
  MatrixXf distances = _pdist(x,y);
  VectorXf res = distances.colwise().maxCoeff().transpose();
  res = res.array().max(VectorXf::Zero(res.rows()).array());
  return res;
}
Eigen::MatrixXf
NearNeighborDisMetric::_pdist(const FEATURESS &x, const FEATURESS &y)
{
  int len1 = x.rows(), len2 = y.rows();
  if(len1 == 0 || len2 == 0) {
      return Eigen::MatrixXf::Zero(len1, len2);
    }
  MatrixXf res = x * y.transpose()* -2;
  res = res.colwise() + x.rowwise().squaredNorm();
  res = res.rowwise() + y.rowwise().squaredNorm().transpose();
  res = res.array().max(MatrixXf::Zero(res.rows(), res.cols()).array());
  return res;
}
Eigen::MatrixXf
NearNeighborDisMetric::_cosine_distance(
    const FEATURESS & a,
    const FEATURESS& b, bool data_is_normalized) {
  if(data_is_normalized == true) {
      //undo:
      assert(false);
    }
  MatrixXf res = 1. - (a*b.transpose()).array();
  return res;
}
src/tracker_tools/nn_matching.h
New file
@@ -0,0 +1,35 @@
#ifndef NN_MATCHING_H
#define NN_MATCHING_H
#include "dataType.h"
#include <map>
//A tool to calculate distance;
class NearNeighborDisMetric{
public:
    enum METRIC_TYPE{euclidean=1, cosine};
    NearNeighborDisMetric(METRIC_TYPE metric,
            float matching_threshold,
            int budget);
    ~NearNeighborDisMetric();
    DYNAMICM distance(const FEATURESS& features, const std::vector<uint64_t> &targets);
    DYNAMICM cos_distance(const FEATURESS& features, std::map<uint64_t, FEATURESS> cos_samples);
    //    void partial_fit(FEATURESS& features, std::vector<int> targets, std::vector<int> active_targets);
    void partial_fit(std::vector<TRACKER_DATA>& tid_feats, std::vector<uint64_t>& active_targets);
    float mating_threshold;
private:
    typedef Eigen::VectorXf (NearNeighborDisMetric::*PTRFUN)(const FEATURESS&, const FEATURESS&);
    Eigen::VectorXf _nncosine_distance(const FEATURESS& x, const FEATURESS& y);
    Eigen::VectorXf _nneuclidean_distance(const FEATURESS& x, const FEATURESS& y);
    Eigen::MatrixXf _pdist(const FEATURESS& x, const FEATURESS& y);
    Eigen::MatrixXf _cosine_distance(const FEATURESS & a, const FEATURESS& b, bool data_is_normalized = false);
private:
    PTRFUN _metric;
    int budget;
    std::map<uint64_t, FEATURESS > samples;
};
#endif // NN_MATCHING_H
src/tracker_tools/track.cpp
New file
@@ -0,0 +1,312 @@
#include "track.h"
Track::Track()
{
}
Track::~Track()
{
}
Track::Track(KAL_MEAN& mean, KAL_COVA& covariance, uint64_t track_id, int n_init, int max_age, const FEATURE& feature,char* img_time)
{
    this->mean = mean;
    this->covariance = covariance;
    this->track_id = track_id;
    this->hits = 1;
    this->age = 1;
    this->time_since_update = 0;
    this->state = TrackState::Tentative;
    features = FEATURESS(1, 128);
    features.row(0) = feature;//features.rows() must = 0;
    this->_n_init = n_init;
    this->_max_age = max_age;
    this->init_t = true;
    this->isCurrent = true;
    //初始化徘徊参数
    this->last_time = 0;
//    gettimeofday(&this->last_s_time,0); // 徘徊计时开启
    this->last_s_time = char_2_unix(img_time);
    std::cout<< "==track img time=%s:" << img_time << std::endl;
    this->isWander = false;
    //初始化跌倒的参数
    this->rate = 100;
    this->isFall = false;
    this->first_Fall = true;
    this->rateScale = 0;
    this->minRate = 0;
    this->center_point.x = 0;
    this->center_point.y = 0;
    this->fall_total_time = 0;
    this->hisMinRate = 100;
    this->human_h = 0;
    this->human_w = 0;
    //初始化奔跑的参数
    this->last_point.x = -1;
    this->last_point.y = -1;
    this->is_runing_p = true;
    this->is_runing_t = true;
    this->isRuning = false;
    this->sum_velocity = 0;
    this->confidence = 0;
    this->run_rate = 0;
    this->last_rate = 0;
    this->rate_area = 0.0;
    this->is_hat = false;
    this->hatScore = 0;
    this->headScore = 0;
    this->helmetScore = 0;
    this->is_mask=false;
    this->maskScore = 0;
    this->is_smoke=false;
    this->smokeScore = 0;
    // 添加当前的xy坐标
//    memset(&this->start,0,sizeof(struct this->timeval));
//    memset(&this->stop,0,sizeof(struct this->timeval));
//    memset(&this->diff,0,sizeof(struct this->timeval));
}
void Track::predit(KalmFilter *kf)
{
    /*Propagate the state distribution to the current time step using a
        Kalman filter prediction step.
        Parameters
        ----------
        kf : kalman_filter.KalmFilter
            The Kalman filter.
        */
    kf->predict(this->mean, this->covariance);
    this->age += 1;
    this->time_since_update += 1;
}
void Track::update(KalmFilter * const kf, const DETECTION_ROW& detection, char* img_time)
{
    // 判断消失三秒后删除该轨迹
    if(this->init_t){
//        gettimeofday(&this->start,0);
        this->start = char_2_unix(img_time);
        std::cout << "tracks start:: " << this->start << std::endl;
        this->init_t = false;
    }
//    gettimeofday(&this->stop,0);
    this->stop = char_2_unix(img_time);
//    this->time_substract(&this->diff, &this->start, &this->stop);
    this->diff = this->stop - this->start;
    std::cout << "tracks curr time:: " << this->stop << " tracks curr diff:: "<<(double)this->diff <<std::endl;
//    this->sum_timer = (double)((diff.tv_sec*1000000 + diff.tv_usec)/1000000);
    this->sum_timer = (double)(this->diff)/1000;
    printf("----Track update time------%f\n\n\n\n\n\n", this->sum_timer);
//    std::cout<< this->sum_timer  << "::" <<  MAX_OUT_TIME<<std::endl;
    if(this->sum_timer > MAX_OUT_TIME)
    {
        this->state = TrackState::Deleted;
        this->_max_age = 0;
        this->last_time = 0;
//        gettimeofday(&this->last_s_time,0); // 重新徘徊计时(这是离开不到三秒都算是徘徊)
        this->last_s_time = char_2_unix(img_time);
        std::cout<< "wander start "<< this->last_s_time << " : " << img_time <<std::endl;
//        std::cout<< "--------------------------delete -----------------------";
    }
//    gettimeofday(&this->start,0);
    this->start = char_2_unix(img_time);
    // 计算徘徊的时长
//    gettimeofday(&this->last_e_time,0);
    this->last_e_time = char_2_unix(img_time);
    std::cout<< "wander end "<< this->last_e_time << " : " << img_time <<std::endl;
//    this->time_substract(&this->last_diff_time,&this->last_s_time,&this->last_e_time);
    this->last_diff_time = this->last_e_time - this->last_s_time;
//    this->last_time = (int)(this->last_diff_time.tv_sec+this->last_diff_time.tv_usec/1000000);
    this->last_time = (int)(this->last_diff_time/1000);
    std::cout<< "wander time "<<  this->last_time << "::" <<  this->last_diff_time << "last_s_time" << this->last_s_time << " e: "<< this->last_e_time <<std::endl;
    // 奔跑记录单帧时间
    if(this->is_runing_t)
    {
//        gettimeofday(&this->single_s_time, 0);
        this->single_s_time = char_2_unix(img_time);
        this->is_runing_t = false;
    }else{
//        this->time_substract(&this->single_diff_time,&this->single_s_time,&this->last_e_time);
        this->single_diff_time = this->last_e_time - this->single_s_time;
//        this->single_time = (int)(this->single_diff_time.tv_sec*1000 + this->single_diff_time.tv_usec/1000);
        this->single_time = (int)(this->single_diff_time);
//        gettimeofday(&this->single_s_time, 0);
        this->single_s_time = char_2_unix(img_time);
    }
    KAL_DATA pa = kf->update(this->mean, this->covariance, detection.to_xyah());
    this->mean = pa.first;
    this->covariance = pa.second;
    // 添加当前的xy坐标
    this->xywh = detection.tlwh;
    this->confidence = (this->confidence*4+detection.confidence)/5;
    if(this->is_hat)
    {
        this->is_hat = detection.is_hat;
        this->hatScore =(int)((this->hatScore*9 + detection.hatScore)/10);
        this->helmetScore =(int)((this->helmetScore*9 + detection.helmetScore)/10);
        this->headScore =(int)((this->headScore*9 + detection.headScore)/10);
    }else
    {
        this->is_hat = detection.is_hat;
        this->hatScore = detection.hatScore;
        this->helmetScore = detection.helmetScore;
        this->headScore = detection.headScore;
    }
    this->is_mask = detection.is_mask;
    this->maskScore = detection.maskScore;
    this->is_smoke = detection.is_smoke;
    this->smokeScore = detection.smokeScore;
    /***yolo 直接测跌倒代码更新 s*/
    if(detection.obj_id==0)
    {
        this->fall_total_time = 0 ;
        this->first_Fall = true;
        this->rateScale = 0;
        this->isRuning = false;
    }else if(detection.obj_id==1)
    {
         /**-- start计算累积跌倒时间*/
        if(this->first_Fall) //是否开始计算跌倒时间
        {
            this->first_Fall = false;
//            gettimeofday(&this->fall_s_time,0);
            this->fall_s_time = char_2_unix(img_time);
        }
//        gettimeofday(&this->fall_e_time,0);
        this->fall_e_time = char_2_unix(img_time);
//        this->time_substract(&this->fall_diff_time,&this->fall_s_time,&this->fall_e_time); //距离最小比例的时间
        this->fall_diff_time = this->fall_e_time - this->fall_s_time;
//        this->fall_total_time = (int)(this->fall_diff_time.tv_sec + this->fall_diff_time.tv_usec/1000000);
        this->fall_total_time = (int)(this->fall_diff_time/1000);
        /** -- end计算累积跌倒时间*/
        this->rateScale = detection.confidence;
        this->isRuning = false;
    }else if(detection.obj_id==2)
    {
        this->isRuning = true;
    }
    /***yolo 直接测跌倒代码更新 end*/
    featuresAppendOne(detection.feature);
    //    this->features.row(features.rows()) = detection.feature;
    this->hits += 1;
    this->time_since_update = 0;
    if(this->state == TrackState::Tentative && this->hits >= this->_n_init) {
        this->state = TrackState::Confirmed;
    }
    this->isCurrent = true;
}
bool Track::mark_missed(char* img_time)
{
    if(this->init_t)
    {
//        gettimeofday(&this->start,0);
        this->start = char_2_unix(img_time);
        this->init_t = false;
    }
//    gettimeofday(&this->stop,0);
    this->stop = char_2_unix(img_time);
//    this->time_substract(&this->diff,&this->start,&this->stop);
    this->diff = this->stop - this->start;
//    this->sum_timer = (double)((diff.tv_sec*1000000 + diff.tv_usec)/1000000);
    this->sum_timer = (double)(this->diff)/1000;
    if(this->state == TrackState::Tentative) {
        this->state = TrackState::Deleted;
        return true;
    } else if(this->time_since_update > this->_max_age) {
        this->state = TrackState::Deleted;
        return true;
    } else if(this->sum_timer > MAX_OUT_TIME)
    {
        this->state = TrackState::Deleted;
        this->_max_age = 0;
        return true;
    }
    this->isCurrent = false;
    return false;
}
bool Track::is_confirmed()
{
    return this->state == TrackState::Confirmed;
}
bool Track::is_deleted()
{
    return this->state == TrackState::Deleted;
}
bool Track::is_tentative()
{
    return this->state == TrackState::Tentative;
}
DETECTBOX Track::to_tlwh()
{
    DETECTBOX ret = mean.leftCols(4);
    ret(2) *= ret(3);
    ret.leftCols(2) -= (ret.rightCols(2)/2);
    return ret;
}
DETECTBOX Track::to_xywh()
{
    return this->xywh;
}
void Track::featuresAppendOne(const FEATURE &f)
{
    int size = this->features.rows();
    FEATURESS newfeatures = FEATURESS(size+1, 128);
    newfeatures.block(0, 0, size, 128) = this->features;
    newfeatures.row(size) = f;
    features = newfeatures;
//    printf("--features size::---%d---%d--\n",size,features.rows());
}
int Track::time_substract(struct timeval *result, struct timeval *begin, struct timeval *end)
{
    if(begin->tv_sec > end->tv_sec)    return -1;
    if((begin->tv_sec == end->tv_sec) && (begin->tv_usec > end->tv_usec))    return -2;
    result->tv_sec    = (end->tv_sec - begin->tv_sec);
    result->tv_usec    = (end->tv_usec - begin->tv_usec);
    if(result->tv_usec < 0)
    {
        result->tv_sec--;
        result->tv_usec += 1000000;
    }
    return 0;
}
src/tracker_tools/track.h
New file
@@ -0,0 +1,121 @@
#ifndef TRACK_H
#define TRACK_H
#include "dataType.h"
#include "kalmfilter.h"
#include "model.h"
#include "time.h"
#include "stdio.h"
#include "stdlib.h"
#include <iostream>
#include<sys/time.h>
#include "../utils/geometry_util.h"
#include <queue>
#include "../utils/queue_util.hpp"
#include "../utils/log_util.h"
#include "../utils/time_util.h"
using namespace std;
class Track
{
    enum TrackState {Tentative = 1, Confirmed, Deleted}; // 轨迹的状态,Tentative 是刚开始的时候,Confirmed是确认了是人的轨迹,Deleted是删除的轨迹
public:
    bool isCurrent;
    DETECTBOX xywh;
    Track();
    ~Track();
    Track(KAL_MEAN& mean, KAL_COVA& covariance, uint64_t track_id,
          int n_init, int max_age, const FEATURE& feature, char* img_time);
    void predit(KalmFilter *kf);
    void update(KalmFilter * const kf, const DETECTION_ROW &detection, char* img_time);
    bool mark_missed(char* img_time);
    bool is_confirmed();
    bool is_deleted();
    bool is_tentative();
    DETECTBOX to_tlwh();
    DETECTBOX to_xywh();
    int time_since_update; //累积检测不到的次数
    uint64_t track_id;
    FEATURESS features;
    float confidence;
    KAL_MEAN mean;
    KAL_COVA covariance;
    int hits;
    int age;
    int _n_init;
    int _max_age;
    TrackState state;
    int time_substract(struct timeval *result, struct timeval *begin,struct timeval *end);
public:
    // 附加的其他算法
    // 逗留
//    struct timeval last_s_time, last_e_time, last_diff_time; // 逗留的开始时间、结束时间,和持续时间
    int last_s_time, last_e_time, last_diff_time; // 逗留的开始时间、结束时间,和持续时间
    int last_time; //持续逗留时间
    bool isWander;
    //跌倒
    float rate; //人体身高变化率
    bool isFall;
    bool first_Fall;
    int rateScale; //判断是否逐步跌倒(短时间内)
    MinQueue<float> rate_queue;
//    struct timeval fall_s_time, fall_e_time, fall_diff_time; // 跌倒的持续时间 ,字段fall_diff_time代表了两个含义。距离最小比例的时间+累积跌倒时间
//    struct timeval min_rate_time; //最大比例的定位时间
    int fall_s_time, fall_e_time, fall_diff_time; // 跌倒的持续时间 ,字段fall_diff_time代表了两个含义。距离最小比例的时间+累积跌倒时间
    int min_rate_time; //最大比例的定位时间
    int fall_total_time;
    float minRate;  // 队列中的最大比例
    float hisMinRate;
    SPoint center_point, min_center_point; //重心的高度
    float human_h;
    float human_w;
    //奔跑
    bool is_runing_t;
    bool is_runing_p;
    bool isRuning;
    SPoint last_point;
//    struct timeval single_s_time, single_diff_time; // 单帧的结束时间可以用逗留里的时间代替
    int single_s_time, single_diff_time; // 单帧的结束时间可以用逗留里的时间代替
    int single_time; // 单帧所花销的时长(ms)
    queue<float> velocity_queue;
    float sum_velocity;
    double run_rate;
    double last_rate;
    double rate_area;
    // 帽子、口罩、抽烟
    bool is_hat;
    int hatScore;
    int helmetScore;
    int headScore;
    bool is_mask;
    int maskScore;
    bool is_smoke;
    int smokeScore;
private:
//    struct timeval start,stop,diff;
    int start,stop,diff;
    double sum_timer;
    bool init_t;
    void init_track_time();
    void featuresAppendOne(const FEATURE& f);
};
#endif // TRACK_H
src/tracker_tools/tracker.cpp
New file
@@ -0,0 +1,343 @@
#include "tracker.h"
#include "nn_matching.h"
#include "model.h"
#include "linear_assignment.h"
#include <iostream>
using namespace std;
//#define MY_inner_DEBUG
#ifdef MY_inner_DEBUG
#include <string>
#include <iostream>
#endif
tracker::tracker(
        float max_cosine_distance, int nn_budget,
        float max_iou_distance, int max_age, int n_init)
{
    this->metric = new NearNeighborDisMetric(
            NearNeighborDisMetric::METRIC_TYPE::cosine,
            max_cosine_distance, nn_budget);
    this->max_iou_distance = max_iou_distance;
    this->max_age = max_age;
    this->n_init = n_init;
    this->kf = new KalmFilter();
    this->tracks.clear();
    this->_next_idx = 1;
}
tracker::~tracker()
{
    //    delete this->metric;
    //    delete this->kf;
}
void tracker::predict()
{
    for(auto& track:tracks)
    {
        track->predit(this->kf);
    }
}
void tracker::update(std::vector<std::shared_ptr<tracker>> &CAMERAS_VCT, const DETECTIONS &detections, int cam_id, char* img_time)
{
    TRACHER_MATCHD res;
//    for (map<uint64_t, std::shared_ptr<Track>>::iterator iter=candidate_track_map.begin();iter!=candidate_track_map.end();iter++)
//    {
//        this->tracks.push_back(iter->second);
//        printf("-------------------this->tracks.size:%d\n",this->tracks.size());
//    }
//    std::cout<< "size1:"<< detections.size() << std::endl;
//    if (detections.size()==2){
//        for (DETECTION_ROW det : detections)
//        {
//            std::cout<< det.feature <<std::endl;
//        }
//        exit(0);
//    }
    _match(detections, res);
    vector<MATCH_DATA>& matches = res.matches;
    //#ifdef MY_inner_DEBUG
    //    printf("res.matches size = %d:\n", matches.size());
    //#endif
    for(MATCH_DATA& data:matches) {
        int track_idx = data.first;
        int detection_idx = data.second;
        //#ifdef MY_inner_DEBUG
        //        printf("\t%d == %d;\n", track_idx, detection_idx);
        //#endif
        tracks[track_idx]->update(this->kf, detections[detection_idx], img_time);
//        LOG(INFO) << "=======match-track_idx::" << tracks[track_idx]->track_id;
//        DEBUG( "=======match-track_idx::" + to_string(tracks[track_idx]->track_id));
    }
    vector<int>& unmatched_tracks = res.unmatched_tracks;
    //#ifdef MY_inner_DEBUG
    //    printf("res.unmatched_tracks size = %d\n", unmatched_tracks.size());
    //#endif
    for(int& track_idx:unmatched_tracks)
    {
        this->tracks[track_idx]->mark_missed(img_time);
    }
    vector<int>& unmatched_detections = res.unmatched_detections;
    //#ifdef MY_inner_DEBUG
    //    printf("res.unmatched_detections size = %d\n", unmatched_detections.size());
    //#endif
    for(int& detection_idx:unmatched_detections) {
        this->_initiate_track(detections[detection_idx], cam_id, img_time);
    }
    //#ifdef MY_inner_DEBUG
    //    int size = tracks.size();
    //    printf("now track size = %d\n", size);
    //#endif
    vector<std::shared_ptr<Track>>::iterator it;
    for(it = tracks.begin(); it != tracks.end();) {
        if((*it)->is_deleted()) it = tracks.erase(it);
        else ++it;
    }
    //#ifdef MY_inner_DEBUG
    //    printf("update track size = %d\n", tracks.size());
    //#endif
    /* old version:
    //update distance metric:
    FEATURESS features;
    vector<int> targets;
    vector<int> active_targets;
    int pos = 0;
    for(Track track:tracks) {
        if(track.is_confirmed() == false) continue;
        active_targets.push_back(track.track_id);
        features.row(pos) = track.features;
        int rows = track.features.rows();
        pos += rows;
        for(int i = 0; i < rows; i++) targets.push_back(track.track_id);
        //attention!!!
        //track.features.clear();
        track.features = Eigen::Matrix<float, -1, 128, Eigen::RowMajor>(0,128);
    }
    this->metric->partial_fit(features, targets, active_targets);
    */
    vector<uint64_t> active_targets;
    vector<TRACKER_DATA> tid_features;
    for (auto& track:tracks)
    {
        if(track->is_confirmed() == false) continue;
        active_targets.push_back(track->track_id);
        tid_features.push_back(std::make_pair(track->track_id, track->features));
        FEATURESS t = FEATURESS(0, 128);
        track->features = t;
    }
    this->metric->partial_fit(tid_features, active_targets);
}
void tracker::_match(const DETECTIONS &detections, TRACHER_MATCHD &res)
{
    DEBUG("tracker.cpp _match start 147:: ");
    vector<int> confirmed_tracks;
    vector<int> unconfirmed_tracks;
    int idx = 0;
    for(auto& t:tracks) {
        if(t->is_confirmed()) confirmed_tracks.push_back(idx);
        else unconfirmed_tracks.push_back(idx);
        idx++;
    }
    TRACHER_MATCHD matcha = linear_assignment::getInstance()->matching_cascade(
                this, &tracker::gated_matric,
                this->metric->mating_threshold,
                this->max_age,
                this->tracks,
                detections,
                confirmed_tracks);
    vector<int> iou_track_candidates;
    iou_track_candidates.assign(unconfirmed_tracks.begin(), unconfirmed_tracks.end());
    vector<int>::iterator it;
    for(it = matcha.unmatched_tracks.begin(); it != matcha.unmatched_tracks.end();) {
        int idx = *it;
        if(tracks[idx]->time_since_update == 1) { //push into unconfirmed
            iou_track_candidates.push_back(idx);
            it = matcha.unmatched_tracks.erase(it);
            continue;
        }
        ++it;
    }
    TRACHER_MATCHD matchb = linear_assignment::getInstance()->min_cost_matching(
                this, &tracker::iou_cost,
                this->max_iou_distance,
                this->tracks,
                detections,
                iou_track_candidates,
                matcha.unmatched_detections);
    //get result:
    res.matches.assign(matcha.matches.begin(), matcha.matches.end());
    res.matches.insert(res.matches.end(), matchb.matches.begin(), matchb.matches.end());
    //unmatched_tracks;
    res.unmatched_tracks.assign(
                matcha.unmatched_tracks.begin(),
                matcha.unmatched_tracks.end());
    res.unmatched_tracks.insert(
                res.unmatched_tracks.end(),
                matchb.unmatched_tracks.begin(),
                matchb.unmatched_tracks.end());
    res.unmatched_detections.assign(
                matchb.unmatched_detections.begin(),
                matchb.unmatched_detections.end());
    DEBUG("tracker.cpp _match end 207:: ");
}
void tracker::_initiate_track(const DETECTION_ROW &detection, int cam_id, char* img_time)
{
    KAL_DATA data = kf->initiate(detection.to_xyah());
    KAL_MEAN mean = data.first;
    KAL_COVA covariance = data.second;
    uint64_t n_track_id;
    stringstream strValue;
    strValue << random_int(8);
    strValue >> n_track_id;
    // n_track_id = m_staticStruct::human_ids++;
    auto t = std::make_shared<Track>(mean, covariance, n_track_id, this->n_init, this->max_age, detection.feature, img_time);
    t->xywh = detection.tlwh;
    this->tracks.push_back(t);
//    auto t = std::make_shared<Track>(mean, covariance, this->_next_idx, this->n_init,this->max_age, detection.feature);
//    this->tracks.push_back(t);
//
//    _next_idx += 1;
}
DYNAMICM tracker::gated_matric(
        std::vector<std::shared_ptr<Track>> &tracks,
        const DETECTIONS &dets,
        const std::vector<int>& track_indices,
        const std::vector<int>& detection_indices)
{
    // FEATURESS features(detection_indices.size(), 128);
    // int pos = 0;
    // for(int i:detection_indices) {
    //     features.row(pos++) = dets[i].feature;
    // }
    vector<uint64_t> targets;
    for(int i:track_indices) {
        targets.push_back(tracks[i]->track_id);
    }
    // DYNAMICM cost_matrix = this->metric->distance(features, targets);
    DYNAMICM cost_matrix = Eigen::MatrixXf::Zero(targets.size(), detection_indices.size());
    DYNAMICM res = linear_assignment::getInstance()->gate_cost_matrix(
                this->kf, cost_matrix, tracks, dets, track_indices,
                detection_indices);
    return res;
}
DYNAMICM
tracker::cos_matric(
    std::vector<std::shared_ptr<Track> > &tracks,
    const DETECTIONS &dets, const std::vector<int>
    &track_indices, const std::vector<int>
    &detection_indices)
{
    FEATURESS features(detection_indices.size(), 128);
    int pos = 0;
    for(int i : detection_indices) {
        features.row(pos++) = dets[i].feature;
    }
    std::map<uint64_t, FEATURESS> simples;
    for(auto i : track_indices)
    {
        simples[tracks[i]->track_id] = tracks[i]->features;
    }
    DYNAMICM res = this->metric->cos_distance(features, simples);
    return res;
}
DYNAMICM
tracker::iou_cost(
        std::vector<std::shared_ptr<Track>> &tracks,
        const DETECTIONS &dets,
        const std::vector<int>& track_indices,
        const std::vector<int>& detection_indices)
{
    //!!!python diff: track_indices && detection_indices will never be None.
    //    if(track_indices.empty() == true) {
    //        for(size_t i = 0; i < tracks.size(); i++) {
    //            track_indices.push_back(i);
    //        }
    //    }
    //    if(detection_indices.empty() == true) {
    //        for(size_t i = 0; i < dets.size(); i++) {
    //            detection_indices.push_back(i);
    //        }
    //    }
    int rows = track_indices.size();
    int cols = detection_indices.size();
    DYNAMICM cost_matrix = Eigen::MatrixXf::Zero(rows, cols);
    for(int i = 0; i < rows; i++) {
        int track_idx = track_indices[i];
        if(tracks[track_idx]->time_since_update > 1) {
            cost_matrix.row(i) = Eigen::RowVectorXf::Constant(cols, INFTY_COST);
            continue;
        }
        DETECTBOX bbox = tracks[track_idx]->to_tlwh();
        int csize = detection_indices.size();
        DETECTBOXSS candidates(csize, 4);
        for(int k = 0; k < csize; k++) candidates.row(k) = dets[detection_indices[k]].tlwh;
        Eigen::RowVectorXf rowV = (1. - iou(bbox, candidates).array()).matrix().transpose();
        cost_matrix.row(i) = rowV;
    }
    return cost_matrix;
}
Eigen::VectorXf
tracker::iou(DETECTBOX& bbox, DETECTBOXSS& candidates)
{
    float bbox_tl_1 = bbox[0];
    float bbox_tl_2 = bbox[1];
    float bbox_br_1 = bbox[0] + bbox[2];
    float bbox_br_2 = bbox[1] + bbox[3];
    float area_bbox = bbox[2] * bbox[3];
    Eigen::Matrix<float, -1, 2> candidates_tl;
    Eigen::Matrix<float, -1, 2> candidates_br;
    candidates_tl = candidates.leftCols(2) ;
    candidates_br = candidates.rightCols(2) + candidates_tl;
    int size = int(candidates.rows());
    //    Eigen::VectorXf area_intersection(size);
    //    Eigen::VectorXf area_candidates(size);
    Eigen::VectorXf res(size);
    for(int i = 0; i < size; i++) {
        float tl_1 = std::max(bbox_tl_1, candidates_tl(i, 0));
        float tl_2 = std::max(bbox_tl_2, candidates_tl(i, 1));
        float br_1 = std::min(bbox_br_1, candidates_br(i, 0));
        float br_2 = std::min(bbox_br_2, candidates_br(i, 1));
        float w = br_1 - tl_1; w = (w < 0? 0: w);
        float h = br_2 - tl_2; h = (h < 0? 0: h);
        float area_intersection = w * h;
        float area_candidates = candidates(i, 2) * candidates(i, 3);
        res[i] = area_intersection/(area_bbox + area_candidates - area_intersection);
    }
    //#ifdef MY_inner_DEBUG
    //        std::cout << res << std::endl;
    //#endif
    return res;
}
src/tracker_tools/tracker.h
New file
@@ -0,0 +1,77 @@
#ifndef TRACKER_H
#define TRACKER_H
#include <vector>
#include "kalmfilter.h"
#include "track.h"
#include "model.h"
// #include "../utils/config_util.h"
#include "feature_util.h"
#include "../utils/geometry_util.h"
#include "../std_target.h"
typedef int (*fn)(void* args, const int sender_chan, const char *recver, const char *data, const  int len);
class NearNeighborDisMetric;
using CURRENT_ID_REG = std::pair<uint64_t, std::vector<bool>>;
class tracker
{
public:
    NearNeighborDisMetric* metric;
    float max_iou_distance;
    int max_age;
    int n_init;
    KalmFilter* kf;
    uint64_t _next_idx;
private:
    // bool P_in_Polygon(SPoint p, IntersectReg polygon);
//    std::vector<uint64_t> candidate_track_ids;  // 候选列表,也就是新加入的人员信息:id、 track信息(特征信息、 坐标信息)
//    std::vector<uint64_t> current_track_ids;  // 跟踪的id 信息
public:
    std::vector<std::shared_ptr<Track>> tracks;
    tracker(  /*NearNeighborDisMetric* metric,*/
            float max_cosine_distance, int nn_budget,
            float max_iou_distance = MAX_IOU_DISTANCE,
            int max_age = MAX_AGE, int n_init = N_INIT);
    ~tracker();
    void predict();
    void update(std::vector<std::shared_ptr<tracker>> &CAMERAS_VCT, const DETECTIONS& detections, int cam_id, char* img_time);
    typedef DYNAMICM (tracker::* GATED_METRIC_FUNC)(
            std::vector<std::shared_ptr<Track>>& tracks,
            const DETECTIONS& dets,
            const std::vector<int>& track_indices,
            const std::vector<int>& detection_indices);
private:
    void _match(const DETECTIONS& detections, TRACHER_MATCHD& res);
    void _initiate_track(const DETECTION_ROW& detection, int cam_id, char* img_time);
public:
    DYNAMICM gated_matric(
            std::vector<std::shared_ptr<Track>>& tracks,
            const DETECTIONS& dets,
            const std::vector<int>& track_indices,
            const std::vector<int>& detection_indices);
    DYNAMICM cos_matric(
        std::vector<std::shared_ptr<Track>>& tracks,
        const DETECTIONS& dets,
        const std::vector<int>& track_indices,
        const std::vector<int>& detection_indices);
    DYNAMICM iou_cost(
            std::vector<std::shared_ptr<Track>>& tracks,
            const DETECTIONS& dets,
            const std::vector<int>& track_indices,
            const std::vector<int>& detection_indices);
    Eigen::VectorXf iou(DETECTBOX& bbox,
                        DETECTBOXSS &candidates);
};
#endif // TRACKER_H
src/utils/draw_util.cpp
@@ -70,26 +70,26 @@
    cv::imwrite(file_path + name + "_" + to_string(type) + ".jpg", aaaa);
}
void draw_SDK_result(cv::Mat mat_img, Target& target)
void draw_SDK_result(cv::Mat mat_img, Target* target)
{
    cv::Rect tmp_rect = cv::Rect(target.rect.left,target.rect.top,target.rect.right-target.rect.left,target.rect.bottom-target.rect.top);
    cv::Rect tmp_rect = cv::Rect(target->rect.left,target->rect.top,target->rect.right-target->rect.left,target->rect.bottom-target->rect.top);
    cv::rectangle(mat_img, tmp_rect , cv::Scalar(50, 200, 50), 2);
    // cv::resize(mat_img, mat_img, frameSize);
    // cv::imwrite("1111.jpg", mat_img);
    cv::imshow(to_string(1), mat_img);
    cv::waitKey(0);
    cv::waitKey(1);
}
cv::VideoWriter writer("./01_baseDetector.avi", cv::VideoWriter::fourcc('M','J','P','G'),24, cv::Size(800,500), true);
// cv::VideoWriter writer("/opt/vasystem/valog/01_Scheanve/01_baseDetector.avi", cv::VideoWriter::fourcc('M','J','P','G'),24, cv::Size(800,500), true);
void draw_SDK_result(const int cam_id, cv::Mat mat_img, TResult& t_result)
void draw_SDK_result(const int cam_id, cv::Mat mat_img, TResult* t_result)
{
    cv::Rect tmp_rect;
    for (int i = 0; i < t_result.count; ++i)
    for (int i = 0; i < t_result->count; ++i)
    {
        auto &result = t_result.targets[i];
        auto &result = t_result->targets[i];
        tmp_rect = cv::Rect(result.rect.left,result.rect.top,result.rect.right-result.rect.left,result.rect.bottom-result.rect.top);
        cv::rectangle(mat_img, tmp_rect , cv::Scalar(50, 200, 50), 2);
//        cv::putText(mat_img, std::to_string(result.id), Point((result.rect.left+result.rect.right)/2,result.rect.top+150), CV_FONT_HERSHEY_SIMPLEX, 0.8, Scalar(255,255,0), 2);
src/utils/draw_util.h
@@ -11,8 +11,8 @@
void create_foldert(const char *path);
void draw_SDK_result(cv::Mat mat_img, Target& target);
void draw_SDK_result(const int cam_id, cv::Mat mat_img,  TResult& t_result);
void draw_SDK_result(cv::Mat mat_img, Target* target);
void draw_SDK_result(const int cam_id, cv::Mat mat_img,  TResult* t_result);
src/utils/geometry_util.cpp
New file
@@ -0,0 +1,445 @@
//
// Created by Scheaven on 2020/5/31.
//
#include "geometry_util.h"
using namespace std;
SPoint::_Point() {}
SPoint::_Point(float x, float y)
{
    this->x = x;
    this->y = y;
    this->z = 0;
}
SPoint::_Point(double a, double b, double c)
{
   x = a; y = b; z = c;
}
float calDistance(SPoint A, SPoint B)
{
    float x_d, y_d;
    x_d = A.x - B.x;
    y_d = A.y - B.y;
    float len = sqrt(x_d * x_d + 4*y_d * y_d);
    return len;
}
//bool Pt_in_Polygon(SPoint point, RegInfo* polygon)
//{
//    int nCross = 0;
//    for (int i = 0; i < polygon->count; ++i)
//    {
//        SPoint p1 = polygon[i];
//        SPoint p2 = polygon[(i+1)%polygon->count];
//
//        if ( p1.y == p2.y )
//            continue;
//        if ( p.y < min(p1.y, p2.y) )
//            continue;
//        if ( p.y >= max(p1.y, p2.y) )
//            continue;
//
//        float x = (float)(p.y - p1.y) * (float)(p2.x - p1.x) / (float)(p2.y - p1.y) + p1.x;
//
//        if ( x > p.x )
//        {
//            nCross++;
//        }
//
//    }
//
//    if ((nCross % 2) == 1)
//    {
//        return true;
//    }
//    else
//    {
//        return false;
//    }
//}
float computeArea(const SPoint * pt,int n ) {
    float area0 = 0.f;
    for (int i = 0 ; i < n ; i++ )
    {
        int j = (i+1)%n;
        area0 += pt[i].x * pt[j].y;
        area0 -= pt[i].y * pt[j].x;
    }
    return 0.5f * fabs(area0);
}
struct PointAngle{
    SPoint p;
    float angle;
};
float Polygon::area() const {
    return computeArea(pt,n);
}
static inline int cross(const SPoint* a,const SPoint* b) {
    return a->x * b->y - a->y * b->x;
}
static inline SPoint* vsub(const SPoint* a,const SPoint* b, SPoint* res) {
    res->x = a->x - b->x;
    res->y = a->y - b->y;
    return res;
}
static int line_sect(const SPoint* x0,const SPoint* x1,const SPoint* y0,const SPoint* y1, SPoint* res) {
    SPoint dx, dy, d;
    vsub(x1, x0, &dx);
    vsub(y1, y0, &dy);
    vsub(x0, y0, &d);
    float dyx = (float)cross(&dy, &dx);
    if (!dyx) return 0;
    dyx = cross(&d, &dx) / dyx;
    if (dyx <= 0 || dyx >= 1) return 0;
    res->x = int(y0->x + dyx * dy.x);
    res->y = int(y0->y + dyx * dy.y);
    return 1;
}
static int left_of(const SPoint* a,const SPoint* b,const SPoint* c) {
    SPoint tmp1, tmp2;
    int x;
    vsub(b, a, &tmp1);
    vsub(c, b, &tmp2);
    x = cross(&tmp1, &tmp2);
    return x < 0 ? -1 : x > 0;
}
static void poly_edge_clip(const Polygon* sub,const  SPoint* x0,const  SPoint* x1, int left, Polygon* res) {
    int i, side0, side1;
    SPoint tmp;
    const SPoint* v0 = sub->pt+ sub->n - 1;
    const SPoint* v1;
    res->clear();
    side0 = left_of(x0, x1, v0);
    if (side0 != -left) res->add(*v0);
    for (i = 0; i < sub->n; i++) {
        v1 = sub->pt + i;
        side1 = left_of(x0, x1, v1);
        if (side0 + side1 == 0 && side0)
            /* last point and current straddle the edge */
            if (line_sect(x0, x1, v0, v1, &tmp))
                res->add(tmp);
        if (i == sub->n - 1) break;
        if (side1 != -left) res->add(*v1);
        v0 = v1;
        side0 = side1;
    }
}
static int poly_winding(const Polygon* p) {
    return left_of(p->pt, p->pt + 1, p->pt + 2);
}
void intersectPolygonSHPC(const Polygon * sub, const Polygon* clip, Polygon* res)
{
    int i;
    Polygon P1,P2;
    Polygon *p1 = &P1;
    Polygon *p2 = &P2;
    Polygon *tmp;
    int dir = poly_winding(clip);
    poly_edge_clip(sub, clip->pt + clip->n - 1, clip->pt, dir, p2);
    for (i = 0; i < clip->n - 1; i++) {
        tmp = p2; p2 = p1; p1 = tmp;
        if(p1->n == 0) {
            p2->n = 0;
            break;
        }
        poly_edge_clip(p1, clip->pt + i, clip->pt + i + 1, dir, p2);
    }
    res->clear();
    for (i = 0 ; i < p2->n ; i++) res->add(p2->pt[i]);
}
void intersectPolygonSHPC(const Polygon & sub,const Polygon& clip,Polygon& res) {
    intersectPolygonSHPC(&sub, &clip, &res);
}
Line::Line(SPoint a, SPoint b, bool _is_seg)
{
    s = a; e = b; is_seg = _is_seg;
}
Line::Line() {}
bool PointCmp(const SPoint &a,const SPoint &b,const SPoint &center)
{
    if (a.x >= 0 && b.x < 0)
        return true;
    if (a.x == 0 && b.x == 0)
        return a.y > b.y;
    int det = (a.x - center.x) * (b.y - center.y) - (b.x - center.x) * (a.y - center.y);
    if (det < 0)
        return true;
    if (det > 0)
        return false;
    int d1 = (a.x - center.x) * (a.x - center.x) + (a.y - center.y) * (a.y - center.y);
    int d2 = (b.x - center.x) * (b.x - center.y) + (b.y - center.y) * (b.y - center.y);
    return d1 > d2;
}
SPoint ClockwiseSortPoints(std::vector<SPoint> &vPoints)
{
    SPoint center;
    double x = 0,y = 0;
    for (int i = 0;i < vPoints.size();i++)
    {
        x += vPoints[i].x;
        y += vPoints[i].y;
    }
    center.x = (int)x/vPoints.size();
    center.y = (int)y/vPoints.size();
    for(int i = 0;i < vPoints.size() - 1;i++)
    {
        for (int j = 0;j < vPoints.size() - i - 1;j++)
        {
            if (PointCmp(vPoints[j],vPoints[j+1],center))
            {
                SPoint tmp = vPoints[j];
                vPoints[j] = vPoints[j + 1];
                vPoints[j + 1] = tmp;
            }
        }
    }
    return center;
}
SPoint add(const SPoint& lhs, const SPoint& rhs)
{
    SPoint res;
    res.x = lhs.x + rhs.x;
    res.y = lhs.y + rhs.y;
    res.z = lhs.z + rhs.z;
    return res;
}
SPoint sub(const SPoint& lhs, const SPoint& rhs)
{
    SPoint res;
    res.x = lhs.x - rhs.x;
    res.y = lhs.y - rhs.y;
    res.z = lhs.z - rhs.z;
    return res;
}
SPoint mul(const SPoint& p, double ratio)
{
    SPoint res;
    res.x = p.x * ratio;
    res.y = p.y * ratio;
    res.z = p.z * ratio;
    return res;
}
SPoint div(const SPoint& p, double ratio)
{
    SPoint res;
    res.x = p.x / ratio;
    res.y = p.y / ratio;
    res.z = p.z / ratio;
    return res;
}
bool equal(const SPoint& lhs, const SPoint& rhs)
{
    return(lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z);
}
double length(const SPoint& vec)
{
    return (sqrt(pow(vec.x, 2) + pow(vec.y, 2) + pow(vec.z, 2)));
}
SPoint normalize(const SPoint& vec)
{
    SPoint res;
    res = div(vec, length(vec));
    return res;
}
double dotMultiply(const SPoint& op, const SPoint& p1, const SPoint& p2)
{
    return ((p1.x - op.x) * (p2.x - op.x) + (p1.y - op.y) * (p2.y - op.y) + (p1.z - op.z) * (p2.z - op.z));
}
double dotMultiply(const SPoint& vec1, const SPoint& vec2)
{
    return(vec1.x * vec2.x + vec1.y * vec2.y + vec1.z * vec2.z);
}
SPoint multiply(const SPoint& op, const SPoint& p1, const SPoint& p2)
{
    SPoint result;
    result.x = (p1.y - op.y) * (p2.z - op.z) - (p2.y - op.y) * (p1.z - op.z);
    result.y = (p1.z - op.z) * (p2.x - op.x) - (p2.z - op.z) * (p1.x - op.x);
    result.z = (p1.x - op.x) * (p2.y - op.y) - (p2.x - op.x) * (p1.y - op.y);
    return result;
}
SPoint multiply(const SPoint& vec1, const SPoint& vec2)
{
    SPoint result;
    result.x = vec1.y * vec2.z - vec2.y * vec1.z;
    result.y = vec1.z * vec2.x - vec2.z * vec1.x;
    result.z = vec1.x * vec2.y - vec2.x * vec1.y;
    return result;
}
bool isponl(const SPoint& p, const Line& l)
{
    SPoint line_vec = sub(l.e, l.s);
    SPoint point_vec1 = sub(p, l.s);
    SPoint point_vec2 = sub(p, l.e);
    SPoint mul_vec = multiply(line_vec, point_vec1);
    double dot = dotMultiply(point_vec1, point_vec2);
    if (l.is_seg)
    {
        if (equal(p,l.s) || equal(p,l.e))
            return true;
        return (0.0 == length(mul_vec) && dot < 0.0);
    }
    else
    {
        return (0.0 == length(mul_vec));
    }
}
double Cos(const SPoint& vec1, const SPoint& vec2)
{
    SPoint unit_vec1 = normalize(vec1);
    SPoint unit_vec2 = normalize(vec2);
    return dotMultiply(unit_vec1, unit_vec2);
}
double Cos(const SPoint& op, const SPoint& p1, const SPoint& p2)
{
    SPoint vec1 = sub(p1, op);
    SPoint vec2 = sub(p2, op);
    return Cos(vec1, vec2);
}
bool isSegIntersect(const Line& l1, const Line& l2, SPoint& inter_p)
{
    SPoint line1 = sub(l1.e, l1.s);
    SPoint line2 = sub(l2.e, l2.s);
    SPoint norm1 = normalize(line1);
    SPoint norm2 = normalize(line2);
    if (l1.is_seg)
    {
        if (isponl(l1.s, l2))
        {
            inter_p = l1.s;
            return true;
        }
        if (isponl(l1.e, l2))
        {
            inter_p = l1.e;
            return true;
        }
        if (isponl(l2.s, l1))
        {
            inter_p = l2.s;
            return true;
        }
        if (isponl(l2.e, l1))
        {
            inter_p = l2.e;
            return true;
        }
        double dot1 = dotMultiply(multiply(sub(l2.s, l1.s), line1), multiply(sub(l2.e, l1.s), line1));
        double dot2 = dotMultiply(multiply(sub(l1.s, l2.s), line2), multiply(sub(l1.e, l2.s), line2));
        if (dot1 < 0.0 && dot2 < 0.0)
        {
            double t1 = length(multiply(sub(l1.s, l2.s), norm2)) / length(multiply(norm2, norm1));
            double t2 = length(multiply(sub(l2.s, l1.s), norm1)) / length(multiply(norm1, norm2));
            inter_p = add(l1.s, mul(norm1, t1));
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        if (Cos(line1, line2) == 1.0)
            return false;
        double t1 = length(multiply(sub(l1.s, l2.s), norm2)) / length(multiply(norm2, norm1));
        double t2 = length(multiply(sub(l2.s, l1.s), norm1)) / length(multiply(norm1, norm2));
        inter_p = add(l1.s, mul(norm1, t1));
        return true;
    }
}
// bool p_inPolygon(Point p, vector<Point> point_vec)
// {
//     int nCross = 0;
//     for (int i = 0; i < point_vec.size(); ++i)
//     {
//         Point p1(point_vec[i].x, point_vec[i].y);
//         Point p2(point_vec[(i+1)%point_vec.size()].x, point_vec[(i+1)%point_vec.size()].y);
//         if ( p1.y == p2.y )
//             continue;
//         if ( p.y < min(p1.y, p2.y) )
//             continue;
//         if ( p.y >= max(p1.y, p2.y) )
//             continue;
//         float x = (float)(p.y - p1.y) * (float)(p2.x - p1.x) / (float)(p2.y - p1.y) + p1.x;
//         if ( x > p.x )
//         {
//             nCross++;
//         }
//     }
//     if ((nCross % 2) == 1)
//     {
//         return true;
//     }
//     else
//     {
//         return false;
//     }
// }
src/utils/geometry_util.h
New file
@@ -0,0 +1,129 @@
//
// Created by Scheaven on 2020/5/31.
//
#ifndef GEOMETRY_UTIL_H
#define GEOMETRY_UTIL_H
#include <vector>
#include <map>
#include <string>
#include <list>
#include <fstream>
#include <stdint.h>
#include "stdio.h"
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <cmath>
#include <cstring>
#include "assert.h"
const double PI = 3.14159265;
typedef struct _Point
{
public:
    float x;
    float y;
    float z;
public:
    _Point(float x, float y);
    _Point();
    _Point(double a , double b , double c );
}SPoint;
// 多边形区域结构
typedef struct _PInfo
{
    SPoint* point;
    int count;
}RegInfo;
float calDistance(SPoint A, SPoint B);
bool Pt_in_Polygon(SPoint point, RegInfo* polygon);
#define MAX_POINT_POLYGON 64
struct Polygon {
    SPoint pt[MAX_POINT_POLYGON];
    int     n;
    Polygon(int n_ = 0 ) { assert(n_>= 0 && n_ < MAX_POINT_POLYGON); n = n_;}
    virtual ~Polygon() {}
    void clear() { n = 0; }
    void add(const SPoint &p) {if(n < MAX_POINT_POLYGON) pt[n++] = p;}
    void push_back(const SPoint &p) {add(p);}
    int size() const { return n;}
    SPoint getCenter() const ;
    const SPoint & operator[] (int index) const { assert(index >= 0 && index < n); return pt[index];}
    SPoint& operator[] (int index) { assert(index >= 0 && index < n); return pt[index]; }
    void pointsOrdered() ;
    float area() const ;
    bool pointIsInPolygon(SPoint p) const ;
};
void intersectPolygonSHPC(const Polygon * sub,const Polygon* clip,Polygon* res) ;
void intersectPolygonSHPC(const Polygon & sub,const Polygon& clip,Polygon& res) ;
//struct Point
//{
//    double x;    // x坐标
//    double y;    // y坐标
//    double z;    // z坐标(默认为0,如果需要三维点则给z赋值)
//
//    Point(double a , double b , double c = 0); // 构造函数
//    Point(); // 构造函数
//};
struct Line
{
    SPoint s;
    SPoint e;
    bool is_seg;
    Line();
    Line(SPoint a, SPoint b, bool _is_seg = true);
};
bool PointCmp(const SPoint &a,const SPoint &b,const SPoint &center);
SPoint ClockwiseSortPoints(std::vector<SPoint> &vPoints); // 多边形的点按照逆时针排序
SPoint add(const SPoint& lhs, const SPoint& rhs);
SPoint sub(const SPoint& lhs, const SPoint& rhs);
SPoint mul(const SPoint& p, double ratio);
SPoint div(const SPoint& p, double ratio);
bool equal(const SPoint& lhs, const SPoint& rhs);
double length(const SPoint& vec);
SPoint normalize(const SPoint& vec);
double dotMultiply(const SPoint& op, const SPoint& p1, const SPoint& p2);
double dotMultiply(const SPoint& vec1, const SPoint& vec2);
SPoint multiply(const SPoint& op, const SPoint& p1, const SPoint& p2);
SPoint multiply(const SPoint& vec1, const SPoint& vec2);
bool isponl(const SPoint& p, const Line& l);
double Cos(const SPoint& vec1, const SPoint& vec2);
double Cos(const SPoint& op, const SPoint& p1, const SPoint& p2);
bool isSegIntersect(const Line& l1, const Line& l2, SPoint& inter_p);
#endif //GEOMETRY_UTIL_H
src/utils/queue_util.hpp
New file
@@ -0,0 +1,168 @@
//
// Created by Scheaven on 2020/6/8.
//
#ifndef _QUEUE_UTIL_H
#define _QUEUE_UTIL_H
#include "stack_util.hpp"
using namespace std;
template <typename T>
class MaxQueue
{
private:
    MaxStack<T> stackA;
    MaxStack<T> stackB;
public:
    MaxQueue(){};
    ~MaxQueue(){};
    void push(T ele)
    {
        stackA.push(ele);
    };
    void pop()
    {
        if(stackB.isEmpty())
        {
//        if(stackA.isEmpty())
//        {
//            return ;
//        }
            while (!stackA.isEmpty())
            {
                stackB.push(stackA.top());
                stackA.pop();
            }
        }
        stackB.pop();
    };
    T front()
    {
        if(stackB.isEmpty())
        {
//        if(stackA.isEmpty())
//        {
//            return ;
//        }
            while (!stackA.isEmpty())
            {
                stackB.push(stackA.top());
                stackA.pop();
            }
        }
        return stackB.top();
    };
    T max()
    {
        if(!stackA.isEmpty()&&!stackB.isEmpty())
        {
            return stackA.maxItem()>stackB.maxItem()?stackA.maxItem():stackB.maxItem();
        } else if(!stackA.isEmpty()&&stackB.isEmpty())
        {
            return stackA.maxItem();
        } else
        {
            return stackB.maxItem();
        }
    };
    int size()
    {
        return stackA.size()+stackB.size();
    }
    bool isEmpty()
    {
        return stackA.isEmpty()&&stackB.isEmpty();
    };
};
template <typename T>
class MinQueue
{
private:
    MinStack<T> stackA;
    MinStack<T> stackB;
public:
    MinQueue(){};
    ~MinQueue(){};
    void push(T ele)
    {
        stackA.push(ele);
    };
    void pop()
    {
        if(stackB.isEmpty())
        {
//        if(stackA.isEmpty())
//        {
//            return ;
//        }
            while (!stackA.isEmpty())
            {
                stackB.push(stackA.top());
                stackA.pop();
            }
        }
        stackB.pop();
    };
    T front()
    {
        if(stackB.isEmpty())
        {
//        if(stackA.isEmpty())
//        {
//            return ;
//        }
            while (!stackA.isEmpty())
            {
                stackB.push(stackA.top());
                stackA.pop();
            }
        }
        return stackB.top();
    };
    T min()
    {
        if(!stackA.isEmpty()&&!stackB.isEmpty())
        {
            return stackA.minItem()<stackB.minItem()?stackA.minItem():stackB.minItem();
        } else if(!stackA.isEmpty()&&stackB.isEmpty())
        {
            return stackA.minItem();
        } else
        {
            return stackB.minItem();
        }
    };
    int size()
    {
        return stackA.size()+stackB.size();
    }
    bool isEmpty()
    {
        return stackA.isEmpty()&&stackB.isEmpty();
    };
};
#endif //INC_05_MAX_STACK_QUEUE_QUEUE_UTIL_H
src/utils/stack_util.hpp
New file
@@ -0,0 +1,127 @@
//
// Created by Scheaven on 2020/6/8.
//
#ifndef _STACK_UTIL_H
#define _STACK_UTIL_H
#include <algorithm>
#include <memory.h>
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <stdlib.h>
#include <vector>
#include <stack>
#include <cstdio>
using namespace std;
template <typename T>
class MaxStack
{
private:
    stack<T> max_stack;
    stack<T> _data;
public:
    MaxStack(){};
    ~MaxStack(){};
    void push(T ele)
    {
        _data.push(ele);
        if(max_stack.empty() || ele>=max_stack.top())
        {
            max_stack.push(ele);
        }
    };
    void pop()
    {
        T tem = _data.top();
        _data.pop();
        if(tem==max_stack.top())
        {
            max_stack.pop();
        }
    };
    T top()
    {
        return _data.top();
    };
    bool isEmpty()
    {
        return _data.empty();
    };
    T maxItem()
    {
        return max_stack.top();
    };
    int size()
    {
        return _data.size();
    };
};
template <typename T>
class MinStack
{
private:
    stack<T> min_stack;
    stack<T> _data;
public:
    MinStack(){};
    ~MinStack(){};
    void push(T ele)
    {
        _data.push(ele);
        if(min_stack.empty() || ele<=min_stack.top())
        {
            min_stack.push(ele);
        }
    };
    void pop(){
        T tem = _data.top();
        _data.pop();
        if(tem==min_stack.top())
        {
            min_stack.pop();
        }
    };
    T top()
    {
        return _data.top();
    };
    bool isEmpty()
    {
        return _data.empty();
    };
    T minItem()
    {
        return min_stack.top();
    };
    int size()
    {
        return _data.size();
    };
};
#endif //INC_05_MAX_STACK_QUEUE_STACK_UTIL_H
src/utils/time_util.cpp
New file
@@ -0,0 +1,134 @@
//
// Created by Scheaven on 2020/5/14.
//
#include "time_util.h"
#include <stdio.h>
#include <memory.h>
#include <iostream>
#include <ctime>
#include <string>
#include "stdlib.h"
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
using namespace std;
int get_run_time(struct timeval *result, struct timeval *begin, struct timeval * end)
{
    if(begin->tv_sec > end->tv_sec)  return -1;
    if((begin->tv_sec == end->tv_sec) && (begin->tv_usec > end->tv_usec))  return -2;
    result->tv_sec = end->tv_sec - begin->tv_sec;
    result->tv_usec = end->tv_usec - begin->tv_usec;
    if(result->tv_usec<0)
    {
        result->tv_sec--;
        result->tv_usec += 1000000;
    }
    return 0;
}
time_t strTime2unix(char* timeStamp)
{
    struct tm tm;
    memset(&tm, 0, sizeof(tm));
    sscanf(timeStamp, "%d-%d-%d %d:%d:%d",
           &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
           &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
    tm.tm_year -= 1900;
    tm.tm_mon--;
    return mktime(&tm);
}
long char_2_unix(char* str1)
{
    char str[100];
//    std::cout<< "==char_2_unix=%s:" << str1<< std::endl;
    strcpy(str, str1);
    const char *mySplit = ".";
    char *p;
    char *p1;
    char *p2;
    p1 = strtok(str, mySplit);
    p2 = strtok(NULL, mySplit);
//    std::cout<< "--p1=:" << p1 << " : " << p2 << std::endl;
    time_t t = strTime2unix(p1);
//    std::cout<< "char_2_unix=t=%s:" << t << std::endl;
    return t*1000+atoi(p2);
}
char* fa_getSysTime()
{
    struct timeval tv;
    gettimeofday(&tv,NULL);
    struct tm* pTime;
    pTime = localtime(&tv.tv_sec);
    static char sTemp[30] = "0";
    snprintf(sTemp, sizeof(sTemp), "%04d-%02d-%02d %02d:%02d:%02d:%03d", pTime->tm_year+1900, \
            pTime->tm_mon+1, pTime->tm_mday, pTime->tm_hour, pTime->tm_min, pTime->tm_sec, \
            tv.tv_usec/1000);
    char* TP = sTemp;
    return TP;
}
string random_int(size_t length)
{
    long seed = (unsigned)time(NULL) + (unsigned)clock();
    srand(seed);
    auto randchar= []() ->char
    {
        const char  charset[] = "0123456789";
        const size_t max_index = (sizeof(charset) - 1);
        return charset[rand()%max_index];
    };
    std::string str(length,0);
    std::generate_n(str.begin(),length,randchar);
    //SLOG::getInstance()->addLog(0, str + "------seed and id--init-----id:" + to_string(seed));
    return str;
}
Timer* Timer::instance = NULL;
Timer* Timer::getInstance()
{
    if (instance==NULL)
    {
        instance = new Timer();
    }
    return instance;
}
Timer::Timer():beg_(clock_::now()){}
void Timer::reset()
{
    beg_ = clock_::now();
}
double Timer::elapsed() const
{
    return std::chrono::duration_cast<second_>(clock_::now() - beg_).count();
}
void Timer::out(std::string message)
{
    double t = elapsed();
    // std::cout << message << " elasped time:" << t << "ms" << std::endl;
    DEBUG((boost::format("%e: %f ms")%message %t).str());
    reset();
}
double Timer::get_duration() const
{
    return elapsed();
}
src/utils/time_util.h
New file
@@ -0,0 +1,49 @@
//
// Created by Scheaven on 2020/5/14.
//
#ifndef DEMO_TIME_UTIL_H
#define DEMO_TIME_UTIL_H
#include <sys/time.h>
#include <cstdio>
#include <time.h>
#include <stdlib.h>
#include <string>
#include <algorithm>
#include <sstream>
int get_run_time(struct timeval *result, struct timeval *begin, struct timeval *end);
time_t strTime2unix(char* timeStamp);
long char_2_unix(char* str1);
char* fa_getSysTime();
std::string random_int(size_t length);
#include <chrono>
#include "log_util.h"
#include <boost/format.hpp>
class Timer
{
    public:
        static Timer* instance;
        static Timer* getInstance();
        Timer();
    public:
        void reset();
        double elapsed() const;
        void out(std::string message="");
        // DEBUG((boost::format("nhao%d")%1).str());
        double get_duration() const;
    private:
        using clock_ = std::chrono::high_resolution_clock;
        using second_=std::chrono::duration<double,std::milli>;
        std::chrono::time_point<clock_>beg_;
};
#endif //DEMO_TIME_UTIL_H
src/utils/timer_utils.hpp
@@ -21,8 +21,8 @@
        void out(std::string message="")
        {
            double t = elapsed();
            std::cout << message << " elasped time:" << t << "ms" << std::endl;
            // DEBUG((boost::format("%e lasped time:%f ms")%message %t).str());
            // std::cout << message << " elasped time:" << t << "ms" << std::endl;
            DEBUG((boost::format("%e lasped time:%f ms")%message %t).str());
            reset();
        }
        // DEBUG((boost::format("nhao%d")%1).str());