未验证 提交 531bca9d 编写于 作者: W wangguanzhong 提交者: GitHub

[MOT] add cpplint & refine format in pptracking (#4501)

上级 305928b8
...@@ -25,3 +25,20 @@ ...@@ -25,3 +25,20 @@
files: \.(md|yml)$ files: \.(md|yml)$
- id: remove-tabs - id: remove-tabs
files: \.(md|yml)$ files: \.(md|yml)$
- repo: local
hooks:
- id: clang-format-with-version-check
name: clang-format
description: Format files with ClangFormat.
entry: bash ./.travis/codestyle/clang_format.hook -i
language: system
files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx|proto)$
- repo: local
hooks:
- id: cpplint-cpp-source
name: cpplint
description: Check C++ code style using cpplint.py.
entry: bash ./.travis/codestyle/cpplint_pre_commit.hook
language: system
files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx)$
#!/bin/bash
set -e
readonly VERSION="3.8"
version=$(clang-format -version)
if ! [[ $version == *"$VERSION"* ]]; then
echo "clang-format version check failed."
echo "a version contains '$VERSION' is needed, but get '$version'"
echo "you can install the right version, and make an soft-link to '\$PATH' env"
exit -1
fi
clang-format $@
#!/bin/bash
TOTAL_ERRORS=0
if [[ ! $TRAVIS_BRANCH ]]; then
# install cpplint on local machine.
if [[ ! $(which cpplint) ]]; then
pip install cpplint
fi
# diff files on local machine.
files=$(git diff --cached --name-status | awk '$1 != "D" {print $2}')
else
# diff files between PR and latest commit on Travis CI.
branch_ref=$(git rev-parse "$TRAVIS_BRANCH")
head_ref=$(git rev-parse HEAD)
files=$(git diff --name-status $branch_ref $head_ref | awk '$1 != "D" {print $2}')
fi
# The trick to remove deleted files: https://stackoverflow.com/a/2413151
for file in $files; do
if [[ $file =~ ^(patches/.*) ]]; then
continue;
else
cpplint --filter=-readability/fn_size,-build/include_what_you_use,-build/c++11 $file;
TOTAL_ERRORS=$(expr $TOTAL_ERRORS + $?);
fi
done
exit $TOTAL_ERRORS
...@@ -15,9 +15,9 @@ ...@@ -15,9 +15,9 @@
#pragma once #pragma once
#include <iostream> #include <iostream>
#include <vector>
#include <string>
#include <map> #include <map>
#include <string>
#include <vector>
#include "yaml-cpp/yaml.h" #include "yaml-cpp/yaml.h"
...@@ -47,8 +47,7 @@ class ConfigPaser { ...@@ -47,8 +47,7 @@ class ConfigPaser {
mode_ = config["mode"].as<std::string>(); mode_ = config["mode"].as<std::string>();
} else { } else {
std::cerr << "Please set mode, " std::cerr << "Please set mode, "
<< "support value : fluid/trt_fp16/trt_fp32." << "support value : fluid/trt_fp16/trt_fp32." << std::endl;
<< std::endl;
return false; return false;
} }
...@@ -136,4 +135,3 @@ class ConfigPaser { ...@@ -136,4 +135,3 @@ class ConfigPaser {
}; };
} // namespace PaddleDetection } // namespace PaddleDetection
...@@ -14,37 +14,37 @@ ...@@ -14,37 +14,37 @@
#pragma once #pragma once
#include <string> #include <ctime>
#include <vector>
#include <memory> #include <memory>
#include <string>
#include <utility> #include <utility>
#include <ctime> #include <vector>
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp> #include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "paddle_inference_api.h" // NOLINT #include "paddle_inference_api.h" // NOLINT
#include "include/preprocess_op.h"
#include "include/config_parser.h" #include "include/config_parser.h"
#include "include/preprocess_op.h"
#include "include/utils.h" #include "include/utils.h"
using namespace paddle_infer; using namespace paddle_infer; // NOLINT
namespace PaddleDetection { namespace PaddleDetection {
class JDEPredictor { class JDEPredictor {
public: public:
explicit JDEPredictor(const std::string& device="CPU", explicit JDEPredictor(const std::string& device = "CPU",
const std::string& model_dir="", const std::string& model_dir = "",
const double threshold=-1., const double threshold = -1.,
const std::string& run_mode="fluid", const std::string& run_mode = "fluid",
const int gpu_id=0, const int gpu_id = 0,
const bool use_mkldnn=false, const bool use_mkldnn = false,
const int cpu_threads=1, const int cpu_threads = 1,
bool trt_calib_mode=false, bool trt_calib_mode = false,
const int min_box_area=200) { const int min_box_area = 200) {
this->device_ = device; this->device_ = device;
this->gpu_id_ = gpu_id; this->gpu_id_ = gpu_id;
this->use_mkldnn_ = use_mkldnn; this->use_mkldnn_ = use_mkldnn;
...@@ -60,15 +60,14 @@ class JDEPredictor { ...@@ -60,15 +60,14 @@ class JDEPredictor {
} }
// Load Paddle inference model // Load Paddle inference model
void LoadModel( void LoadModel(const std::string& model_dir,
const std::string& model_dir, const std::string& run_mode = "fluid");
const std::string& run_mode = "fluid");
// Run predictor // Run predictor
void Predict(const std::vector<cv::Mat> imgs, void Predict(const std::vector<cv::Mat> imgs,
const double threshold = 0.5, const double threshold = 0.5,
MOTResult* result = nullptr, MOTResult* result = nullptr,
std::vector<double>* times = nullptr); std::vector<double>* times = nullptr);
private: private:
std::string device_ = "CPU"; std::string device_ = "CPU";
...@@ -82,9 +81,7 @@ class JDEPredictor { ...@@ -82,9 +81,7 @@ class JDEPredictor {
// Preprocess image and copy data to input buffer // Preprocess image and copy data to input buffer
void Preprocess(const cv::Mat& image_mat); void Preprocess(const cv::Mat& image_mat);
// Postprocess result // Postprocess result
void Postprocess( void Postprocess(const cv::Mat dets, const cv::Mat emb, MOTResult* result);
const cv::Mat dets, const cv::Mat emb,
MOTResult* result);
std::shared_ptr<Predictor> predictor_; std::shared_ptr<Predictor> predictor_;
Preprocessor preprocessor_; Preprocessor preprocessor_;
......
...@@ -17,9 +17,8 @@ ...@@ -17,9 +17,8 @@
// Ths copyright of gatagat/lap is as follows: // Ths copyright of gatagat/lap is as follows:
// MIT License // MIT License
#ifndef LAPJV_H #ifndef DEPLOY_PPTRACKING_INCLUDE_LAPJV_H_
#define LAPJV_H #define DEPLOY_PPTRACKING_INCLUDE_LAPJV_H_
#define LARGE 1000000 #define LARGE 1000000
#if !defined TRUE #if !defined TRUE
...@@ -29,9 +28,21 @@ ...@@ -29,9 +28,21 @@
#define FALSE 0 #define FALSE 0
#endif #endif
#define NEW(x, t, n) if ((x = (t *)malloc(sizeof(t) * (n))) == 0) {return -1;} #define NEW(x, t, n) \
#define FREE(x) if (x != 0) { free(x); x = 0; } if ((x = reinterpret_cast<t *>(malloc(sizeof(t) * (n)))) == 0) { \
#define SWAP_INDICES(a, b) { int_t _temp_index = a; a = b; b = _temp_index; } return -1; \
}
#define FREE(x) \
if (x != 0) { \
free(x); \
x = 0; \
}
#define SWAP_INDICES(a, b) \
{ \
int_t _temp_index = a; \
a = b; \
b = _temp_index; \
}
#include <opencv2/opencv.hpp> #include <opencv2/opencv.hpp>
namespace PaddleDetection { namespace PaddleDetection {
...@@ -42,11 +53,12 @@ typedef double cost_t; ...@@ -42,11 +53,12 @@ typedef double cost_t;
typedef char boolean; typedef char boolean;
typedef enum fp_t { FP_1 = 1, FP_2 = 2, FP_DYNAMIC = 3 } fp_t; typedef enum fp_t { FP_1 = 1, FP_2 = 2, FP_DYNAMIC = 3 } fp_t;
int lapjv_internal( int lapjv_internal(const cv::Mat &cost,
const cv::Mat &cost, const bool extend_cost, const float cost_limit, const bool extend_cost,
int *x, int *y); const float cost_limit,
int *x,
} // namespace PaddleDetection int *y);
#endif // LAPJV_H } // namespace PaddleDetection
#endif // DEPLOY_PPTRACKING_INCLUDE_LAPJV_H_
...@@ -12,16 +12,18 @@ ...@@ -12,16 +12,18 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#ifndef DEPLOY_PPTRACKING_INCLUDE_PIPELINE_H_
#define DEPLOY_PPTRACKING_INCLUDE_PIPELINE_H_
#include <glog/logging.h> #include <glog/logging.h>
#include <math.h>
#include <sys/types.h>
#include <algorithm>
#include <iostream> #include <iostream>
#include <numeric>
#include <string> #include <string>
#include <vector> #include <vector>
#include <numeric>
#include <sys/types.h>
#include <sys/stat.h>
#include <math.h>
#include <algorithm>
#ifdef _WIN32 #ifdef _WIN32
#include <direct.h> #include <direct.h>
...@@ -39,18 +41,18 @@ namespace PaddleDetection { ...@@ -39,18 +41,18 @@ namespace PaddleDetection {
class Pipeline { class Pipeline {
public: public:
explicit Pipeline(const std::string& device, explicit Pipeline(const std::string& device,
const double threshold, const double threshold,
const std::string& output_dir, const std::string& output_dir,
const std::string& run_mode="fluid", const std::string& run_mode = "fluid",
const int gpu_id=0, const int gpu_id = 0,
const bool use_mkldnn=false, const bool use_mkldnn = false,
const int cpu_threads=1, const int cpu_threads = 1,
const bool trt_calib_mode=false, const bool trt_calib_mode = false,
const bool count=false, const bool count = false,
const bool save_result=false, const bool save_result = false,
const std::string& scene="pedestrian", const std::string& scene = "pedestrian",
const bool tiny_obj=false, const bool tiny_obj = false,
const bool is_mtmct=false) { const bool is_mtmct = false) {
std::vector<std::string> input; std::vector<std::string> input;
this->input_ = input; this->input_ = input;
this->device_ = device; this->device_ = device;
...@@ -67,10 +69,8 @@ class Pipeline { ...@@ -67,10 +69,8 @@ class Pipeline {
InitPredictor(); InitPredictor();
} }
// Set input, it must execute before Run() // Set input, it must execute before Run()
void SetInput(std::string& input_video); void SetInput(const std::string& input_video);
void ClearInput(); void ClearInput();
// Run pipeline in video // Run pipeline in video
...@@ -79,16 +79,23 @@ class Pipeline { ...@@ -79,16 +79,23 @@ class Pipeline {
void PredictMTMCT(const std::vector<std::string> video_inputs); void PredictMTMCT(const std::vector<std::string> video_inputs);
// Run pipeline in stream // Run pipeline in stream
void RunMOTStream(const cv::Mat img, const int frame_id, cv::Mat& out_img, std::vector<std::string>& records, std::vector<int>& count_list, std::vector<int>& in_count_list, std::vector<int>& out_count_list); void RunMOTStream(const cv::Mat img,
void RunMTMCTStream(const std::vector<cv::Mat> imgs, std::vector<std::string>& records); const int frame_id,
cv::Mat out_img,
void PrintBenchmarkLog(std::vector<double> det_time, int img_num); std::vector<std::string>* records,
std::vector<int>* count_list,
std::vector<int>* in_count_list,
std::vector<int>* out_count_list);
void RunMTMCTStream(const std::vector<cv::Mat> imgs,
std::vector<std::string>* records);
void PrintBenchmarkLog(const std::vector<double> det_time, const int img_num);
private: private:
// Select model according to scenes, it must execute before Run() // Select model according to scenes, it must execute before Run()
void SelectModel(const std::string& scene="pedestrian", void SelectModel(const std::string& scene = "pedestrian",
const bool tiny_obj=false, const bool tiny_obj = false,
const bool is_mtmct=false); const bool is_mtmct = false);
void InitPredictor(); void InitPredictor();
std::shared_ptr<PaddleDetection::JDEPredictor> jde_sct_; std::shared_ptr<PaddleDetection::JDEPredictor> jde_sct_;
...@@ -111,4 +118,6 @@ class Pipeline { ...@@ -111,4 +118,6 @@ class Pipeline {
bool save_result_ = false; bool save_result_ = false;
}; };
} // namespace PaddleDetection } // namespace PaddleDetection
#endif // DEPLOY_PPTRACKING_INCLUDE_PIPELINE_H_
...@@ -14,15 +14,15 @@ ...@@ -14,15 +14,15 @@
#pragma once #pragma once
#include <string> #include <ctime>
#include <vector>
#include <memory> #include <memory>
#include <string>
#include <utility> #include <utility>
#include <ctime> #include <vector>
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp> #include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "include/utils.h" #include "include/utils.h"
...@@ -33,16 +33,20 @@ cv::Scalar GetColor(int idx); ...@@ -33,16 +33,20 @@ cv::Scalar GetColor(int idx);
// Visualize Tracking Results // Visualize Tracking Results
cv::Mat VisualizeTrackResult(const cv::Mat& img, cv::Mat VisualizeTrackResult(const cv::Mat& img,
const MOTResult& results, const MOTResult& results,
const float fps, const int frame_id); const float fps,
const int frame_id);
// Pedestrian/Vehicle Counting // Pedestrian/Vehicle Counting
void FlowStatistic(const MOTResult& results, const int frame_id, void FlowStatistic(const MOTResult& results,
std::vector<int>* count_list, const int frame_id,
std::vector<int>* in_count_list, std::vector<int>* count_list,
std::vector<int>* in_count_list,
std::vector<int>* out_count_list); std::vector<int>* out_count_list);
// Save Tracking Results // Save Tracking Results
void SaveMOTResult(const MOTResult& results, const int frame_id, std::vector<std::string>& records); void SaveMOTResult(const MOTResult& results,
const int frame_id,
std::vector<std::string>* records);
} // namespace PaddleDetection } // namespace PaddleDetection
...@@ -17,16 +17,16 @@ ...@@ -17,16 +17,16 @@
#include <glog/logging.h> #include <glog/logging.h>
#include <yaml-cpp/yaml.h> #include <yaml-cpp/yaml.h>
#include <vector> #include <iostream>
#include <string>
#include <utility>
#include <memory> #include <memory>
#include <string>
#include <unordered_map> #include <unordered_map>
#include <iostream> #include <utility>
#include <vector>
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp> #include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
namespace PaddleDetection { namespace PaddleDetection {
...@@ -40,7 +40,7 @@ class ImageBlob { ...@@ -40,7 +40,7 @@ class ImageBlob {
// in net data shape(after pad) // in net data shape(after pad)
std::vector<float> in_net_shape_; std::vector<float> in_net_shape_;
// Evaluation image width and height // Evaluation image width and height
//std::vector<float> eval_im_size_f_; // std::vector<float> eval_im_size_f_;
// Scale factor for image size to origin image size // Scale factor for image size to origin image size
std::vector<float> scale_factor_; std::vector<float> scale_factor_;
}; };
...@@ -52,7 +52,7 @@ class PreprocessOp { ...@@ -52,7 +52,7 @@ class PreprocessOp {
virtual void Run(cv::Mat* im, ImageBlob* data) = 0; virtual void Run(cv::Mat* im, ImageBlob* data) = 0;
}; };
class InitInfo : public PreprocessOp{ class InitInfo : public PreprocessOp {
public: public:
virtual void Init(const YAML::Node& item) {} virtual void Init(const YAML::Node& item) {}
virtual void Run(cv::Mat* im, ImageBlob* data); virtual void Run(cv::Mat* im, ImageBlob* data);
...@@ -79,7 +79,6 @@ class Permute : public PreprocessOp { ...@@ -79,7 +79,6 @@ class Permute : public PreprocessOp {
public: public:
virtual void Init(const YAML::Node& item) {} virtual void Init(const YAML::Node& item) {}
virtual void Run(cv::Mat* im, ImageBlob* data); virtual void Run(cv::Mat* im, ImageBlob* data);
}; };
class Resize : public PreprocessOp { class Resize : public PreprocessOp {
...@@ -88,7 +87,7 @@ class Resize : public PreprocessOp { ...@@ -88,7 +87,7 @@ class Resize : public PreprocessOp {
interp_ = item["interp"].as<int>(); interp_ = item["interp"].as<int>();
keep_ratio_ = item["keep_ratio"].as<bool>(); keep_ratio_ = item["keep_ratio"].as<bool>();
target_size_ = item["target_size"].as<std::vector<int>>(); target_size_ = item["target_size"].as<std::vector<int>>();
} }
// Compute best resize scale for x-dimension, y-dimension // Compute best resize scale for x-dimension, y-dimension
std::pair<float, float> GenerateScale(const cv::Mat& im); std::pair<float, float> GenerateScale(const cv::Mat& im);
...@@ -106,7 +105,7 @@ class LetterBoxResize : public PreprocessOp { ...@@ -106,7 +105,7 @@ class LetterBoxResize : public PreprocessOp {
public: public:
virtual void Init(const YAML::Node& item) { virtual void Init(const YAML::Node& item) {
target_size_ = item["target_size"].as<std::vector<int>>(); target_size_ = item["target_size"].as<std::vector<int>>();
} }
float GenerateScale(const cv::Mat& im); float GenerateScale(const cv::Mat& im);
...@@ -154,8 +153,9 @@ class Preprocessor { ...@@ -154,8 +153,9 @@ class Preprocessor {
} else if (name == "PadStride") { } else if (name == "PadStride") {
// use PadStride instead of PadBatch // use PadStride instead of PadBatch
return std::make_shared<PadStride>(); return std::make_shared<PadStride>();
} }
std::cerr << "can not find function of OP: " << name << " and return: nullptr" << std::endl; std::cerr << "can not find function of OP: " << name
<< " and return: nullptr" << std::endl;
return nullptr; return nullptr;
} }
...@@ -169,4 +169,3 @@ class Preprocessor { ...@@ -169,4 +169,3 @@ class Preprocessor {
}; };
} // namespace PaddleDetection } // namespace PaddleDetection
...@@ -14,38 +14,38 @@ ...@@ -14,38 +14,38 @@
#pragma once #pragma once
#include <string> #include <ctime>
#include <vector>
#include <memory> #include <memory>
#include <string>
#include <utility> #include <utility>
#include <ctime> #include <vector>
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp> #include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "paddle_inference_api.h" // NOLINT #include "paddle_inference_api.h" // NOLINT
#include "include/preprocess_op.h"
#include "include/config_parser.h" #include "include/config_parser.h"
#include "include/preprocess_op.h"
#include "include/utils.h" #include "include/utils.h"
using namespace paddle_infer; using namespace paddle_infer; // NOLINT
namespace PaddleDetection { namespace PaddleDetection {
class SDEPredictor { class SDEPredictor {
public: public:
explicit SDEPredictor(const std::string& device, explicit SDEPredictor(const std::string& device,
const std::string& det_model_dir="", const std::string& det_model_dir = "",
const std::string& reid_model_dir="", const std::string& reid_model_dir = "",
const double threshold=-1., const double threshold = -1.,
const std::string& run_mode="fluid", const std::string& run_mode = "fluid",
const int gpu_id=0, const int gpu_id = 0,
const bool use_mkldnn=false, const bool use_mkldnn = false,
const int cpu_threads=1, const int cpu_threads = 1,
bool trt_calib_mode=false, bool trt_calib_mode = false,
const int min_box_area=200) { const int min_box_area = 200) {
this->device_ = device; this->device_ = device;
this->gpu_id_ = gpu_id; this->gpu_id_ = gpu_id;
this->use_mkldnn_ = use_mkldnn; this->use_mkldnn_ = use_mkldnn;
...@@ -65,16 +65,15 @@ class SDEPredictor { ...@@ -65,16 +65,15 @@ class SDEPredictor {
} }
// Load Paddle inference model // Load Paddle inference model
void LoadModel( void LoadModel(const std::string& det_model_dir,
const std::string& det_model_dir, const std::string& reid_model_dir,
const std::string& reid_model_dir, const std::string& run_mode = "fluid");
const std::string& run_mode = "fluid");
// Run predictor // Run predictor
void Predict(const std::vector<cv::Mat> imgs, void Predict(const std::vector<cv::Mat> imgs,
const double threshold = 0.5, const double threshold = 0.5,
MOTResult* result = nullptr, MOTResult* result = nullptr,
std::vector<double>* times = nullptr); std::vector<double>* times = nullptr);
private: private:
std::string device_ = "CPU"; std::string device_ = "CPU";
...@@ -88,9 +87,7 @@ class SDEPredictor { ...@@ -88,9 +87,7 @@ class SDEPredictor {
// Preprocess image and copy data to input buffer // Preprocess image and copy data to input buffer
void Preprocess(const cv::Mat& image_mat); void Preprocess(const cv::Mat& image_mat);
// Postprocess result // Postprocess result
void Postprocess( void Postprocess(const cv::Mat dets, const cv::Mat emb, MOTResult* result);
const cv::Mat dets, const cv::Mat emb,
MOTResult* result);
std::shared_ptr<Predictor> det_predictor_; std::shared_ptr<Predictor> det_predictor_;
std::shared_ptr<Predictor> reid_predictor_; std::shared_ptr<Predictor> reid_predictor_;
......
...@@ -15,49 +15,58 @@ ...@@ -15,49 +15,58 @@
// The code is based on: // The code is based on:
// https://github.com/CnybTseng/JDE/blob/master/platforms/common/jdetracker.h // https://github.com/CnybTseng/JDE/blob/master/platforms/common/jdetracker.h
// Ths copyright of CnybTseng/JDE is as follows: // Ths copyright of CnybTseng/JDE is as follows:
// MIT License // MIT License
#pragma once #pragma once
#include <map> #include <map>
#include <vector> #include <vector>
#include <opencv2/opencv.hpp>
#include "trajectory.h" #include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "include/trajectory.h"
namespace PaddleDetection { namespace PaddleDetection {
typedef std::map<int, int> Match; typedef std::map<int, int> Match;
typedef std::map<int, int>::iterator MatchIterator; typedef std::map<int, int>::iterator MatchIterator;
struct Track struct Track {
{ int id;
int id; float score;
float score; cv::Vec4f ltrb;
cv::Vec4f ltrb;
}; };
class JDETracker class JDETracker {
{ public:
public: static JDETracker *instance(void);
static JDETracker *instance(void); virtual bool update(const cv::Mat &dets,
virtual bool update(const cv::Mat &dets, const cv::Mat &emb, std::vector<Track> &tracks); const cv::Mat &emb,
private: std::vector<Track> *tracks);
JDETracker(void);
virtual ~JDETracker(void) {} private:
cv::Mat motion_distance(const TrajectoryPtrPool &a, const TrajectoryPool &b); JDETracker(void);
void linear_assignment(const cv::Mat &cost, float cost_limit, Match &matches, virtual ~JDETracker(void) {}
std::vector<int> &mismatch_row, std::vector<int> &mismatch_col); cv::Mat motion_distance(const TrajectoryPtrPool &a, const TrajectoryPool &b);
void remove_duplicate_trajectory(TrajectoryPool &a, TrajectoryPool &b, float iou_thresh=0.15f); void linear_assignment(const cv::Mat &cost,
private: float cost_limit,
static JDETracker *me; Match *matches,
int timestamp; std::vector<int> *mismatch_row,
TrajectoryPool tracked_trajectories; std::vector<int> *mismatch_col);
TrajectoryPool lost_trajectories; void remove_duplicate_trajectory(TrajectoryPool *a,
TrajectoryPool removed_trajectories; TrajectoryPool *b,
int max_lost_time; float iou_thresh = 0.15f);
float lambda;
float det_thresh; private:
static JDETracker *me;
int timestamp;
TrajectoryPool tracked_trajectories;
TrajectoryPool lost_trajectories;
TrajectoryPool removed_trajectories;
int max_lost_time;
float lambda;
float det_thresh;
}; };
} // namespace PaddleDetection } // namespace PaddleDetection
...@@ -20,183 +20,211 @@ ...@@ -20,183 +20,211 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/video/tracking.hpp"
namespace PaddleDetection { namespace PaddleDetection {
typedef enum typedef enum { New = 0, Tracked = 1, Lost = 2, Removed = 3 } TrajectoryState;
{
New = 0,
Tracked = 1,
Lost = 2,
Removed = 3
} TrajectoryState;
class Trajectory; class Trajectory;
typedef std::vector<Trajectory> TrajectoryPool; typedef std::vector<Trajectory> TrajectoryPool;
typedef std::vector<Trajectory>::iterator TrajectoryPoolIterator; typedef std::vector<Trajectory>::iterator TrajectoryPoolIterator;
typedef std::vector<Trajectory *>TrajectoryPtrPool; typedef std::vector<Trajectory *> TrajectoryPtrPool;
typedef std::vector<Trajectory *>::iterator TrajectoryPtrPoolIterator; typedef std::vector<Trajectory *>::iterator TrajectoryPtrPoolIterator;
class TKalmanFilter : public cv::KalmanFilter class TKalmanFilter : public cv::KalmanFilter {
{ public:
public: TKalmanFilter(void);
TKalmanFilter(void); virtual ~TKalmanFilter(void) {}
virtual ~TKalmanFilter(void) {} virtual void init(const cv::Mat &measurement);
virtual void init(const cv::Mat &measurement); virtual const cv::Mat &predict();
virtual const cv::Mat &predict(); virtual const cv::Mat &correct(const cv::Mat &measurement);
virtual const cv::Mat &correct(const cv::Mat &measurement); virtual void project(cv::Mat *mean, cv::Mat *covariance) const;
virtual void project(cv::Mat &mean, cv::Mat &covariance) const;
private: private:
float std_weight_position; float std_weight_position;
float std_weight_velocity; float std_weight_velocity;
}; };
inline TKalmanFilter::TKalmanFilter(void) : cv::KalmanFilter(8, 4) inline TKalmanFilter::TKalmanFilter(void) : cv::KalmanFilter(8, 4) {
{ cv::KalmanFilter::transitionMatrix = cv::Mat::eye(8, 8, CV_32F);
cv::KalmanFilter::transitionMatrix = cv::Mat::eye(8, 8, CV_32F); for (int i = 0; i < 4; ++i)
for (int i = 0; i < 4; ++i) cv::KalmanFilter::transitionMatrix.at<float>(i, i + 4) = 1;
cv::KalmanFilter::transitionMatrix.at<float>(i, i + 4) = 1; cv::KalmanFilter::measurementMatrix = cv::Mat::eye(4, 8, CV_32F);
cv::KalmanFilter::measurementMatrix = cv::Mat::eye(4, 8, CV_32F); std_weight_position = 1 / 20.f;
std_weight_position = 1/20.f; std_weight_velocity = 1 / 160.f;
std_weight_velocity = 1/160.f;
} }
class Trajectory : public TKalmanFilter class Trajectory : public TKalmanFilter {
{ public:
public: Trajectory();
Trajectory(); Trajectory(const cv::Vec4f &ltrb, float score, const cv::Mat &embedding);
Trajectory(cv::Vec4f &ltrb, float score, const cv::Mat &embedding); Trajectory(const Trajectory &other);
Trajectory(const Trajectory &other); Trajectory &operator=(const Trajectory &rhs);
Trajectory &operator=(const Trajectory &rhs); virtual ~Trajectory(void) {}
virtual ~Trajectory(void) {};
static int next_id();
static int next_id(); virtual const cv::Mat &predict(void);
virtual const cv::Mat &predict(void); virtual void update(Trajectory *traj,
virtual void update(Trajectory &traj, int timestamp, bool update_embedding=true); int timestamp,
virtual void activate(int timestamp); bool update_embedding = true);
virtual void reactivate(Trajectory &traj, int timestamp, bool newid=false); virtual void activate(int timestamp);
virtual void mark_lost(void); virtual void reactivate(Trajectory *traj, int timestamp, bool newid = false);
virtual void mark_removed(void); virtual void mark_lost(void);
virtual void mark_removed(void);
friend TrajectoryPool operator+(const TrajectoryPool &a, const TrajectoryPool &b);
friend TrajectoryPool operator+(const TrajectoryPool &a, const TrajectoryPtrPool &b); friend TrajectoryPool operator+(const TrajectoryPool &a,
friend TrajectoryPool &operator+=(TrajectoryPool &a, const TrajectoryPtrPool &b); const TrajectoryPool &b);
friend TrajectoryPool operator-(const TrajectoryPool &a, const TrajectoryPool &b); friend TrajectoryPool operator+(const TrajectoryPool &a,
friend TrajectoryPool &operator-=(TrajectoryPool &a, const TrajectoryPool &b); const TrajectoryPtrPool &b);
friend TrajectoryPtrPool operator+(const TrajectoryPtrPool &a, const TrajectoryPtrPool &b); friend TrajectoryPool &operator+=(TrajectoryPool &a, // NOLINT
friend TrajectoryPtrPool operator+(const TrajectoryPtrPool &a, TrajectoryPool &b); const TrajectoryPtrPool &b);
friend TrajectoryPtrPool operator-(const TrajectoryPtrPool &a, const TrajectoryPtrPool &b); friend TrajectoryPool operator-(const TrajectoryPool &a,
const TrajectoryPool &b);
friend cv::Mat embedding_distance(const TrajectoryPool &a, const TrajectoryPool &b); friend TrajectoryPool &operator-=(TrajectoryPool &a, // NOLINT
friend cv::Mat embedding_distance(const TrajectoryPtrPool &a, const TrajectoryPtrPool &b); const TrajectoryPool &b);
friend cv::Mat embedding_distance(const TrajectoryPtrPool &a, const TrajectoryPool &b); friend TrajectoryPtrPool operator+(const TrajectoryPtrPool &a,
const TrajectoryPtrPool &b);
friend cv::Mat mahalanobis_distance(const TrajectoryPool &a, const TrajectoryPool &b); friend TrajectoryPtrPool operator+(const TrajectoryPtrPool &a,
friend cv::Mat mahalanobis_distance(const TrajectoryPtrPool &a, const TrajectoryPtrPool &b); TrajectoryPool *b);
friend cv::Mat mahalanobis_distance(const TrajectoryPtrPool &a, const TrajectoryPool &b); friend TrajectoryPtrPool operator-(const TrajectoryPtrPool &a,
const TrajectoryPtrPool &b);
friend cv::Mat iou_distance(const TrajectoryPool &a, const TrajectoryPool &b);
friend cv::Mat iou_distance(const TrajectoryPtrPool &a, const TrajectoryPtrPool &b); friend cv::Mat embedding_distance(const TrajectoryPool &a,
friend cv::Mat iou_distance(const TrajectoryPtrPool &a, const TrajectoryPool &b); const TrajectoryPool &b);
private: friend cv::Mat embedding_distance(const TrajectoryPtrPool &a,
void update_embedding(const cv::Mat &embedding); const TrajectoryPtrPool &b);
public: friend cv::Mat embedding_distance(const TrajectoryPtrPool &a,
TrajectoryState state; const TrajectoryPool &b);
cv::Vec4f ltrb;
cv::Mat smooth_embedding; friend cv::Mat mahalanobis_distance(const TrajectoryPool &a,
int id; const TrajectoryPool &b);
bool is_activated; friend cv::Mat mahalanobis_distance(const TrajectoryPtrPool &a,
int timestamp; const TrajectoryPtrPool &b);
int starttime; friend cv::Mat mahalanobis_distance(const TrajectoryPtrPool &a,
float score; const TrajectoryPool &b);
private:
static int count; friend cv::Mat iou_distance(const TrajectoryPool &a, const TrajectoryPool &b);
cv::Vec4f xyah; friend cv::Mat iou_distance(const TrajectoryPtrPool &a,
cv::Mat current_embedding; const TrajectoryPtrPool &b);
float eta; friend cv::Mat iou_distance(const TrajectoryPtrPool &a,
int length; const TrajectoryPool &b);
private:
void update_embedding(const cv::Mat &embedding);
public:
TrajectoryState state;
cv::Vec4f ltrb;
cv::Mat smooth_embedding;
int id;
bool is_activated;
int timestamp;
int starttime;
float score;
private:
static int count;
cv::Vec4f xyah;
cv::Mat current_embedding;
float eta;
int length;
}; };
inline cv::Vec4f ltrb2xyah(cv::Vec4f &ltrb) inline cv::Vec4f ltrb2xyah(const cv::Vec4f &ltrb) {
{ cv::Vec4f xyah;
cv::Vec4f xyah; xyah[0] = (ltrb[0] + ltrb[2]) * 0.5f;
xyah[0] = (ltrb[0] + ltrb[2]) * 0.5f; xyah[1] = (ltrb[1] + ltrb[3]) * 0.5f;
xyah[1] = (ltrb[1] + ltrb[3]) * 0.5f; xyah[3] = ltrb[3] - ltrb[1];
xyah[3] = ltrb[3] - ltrb[1]; xyah[2] = (ltrb[2] - ltrb[0]) / xyah[3];
xyah[2] = (ltrb[2] - ltrb[0]) / xyah[3]; return xyah;
return xyah;
} }
inline Trajectory::Trajectory() : inline Trajectory::Trajectory()
state(New), ltrb(cv::Vec4f()), smooth_embedding(cv::Mat()), id(0), : state(New),
is_activated(false), timestamp(0), starttime(0), score(0), eta(0.9), length(0) ltrb(cv::Vec4f()),
{ smooth_embedding(cv::Mat()),
id(0),
is_activated(false),
timestamp(0),
starttime(0),
score(0),
eta(0.9),
length(0) {}
inline Trajectory::Trajectory(const cv::Vec4f &ltrb_,
float score_,
const cv::Mat &embedding)
: state(New),
ltrb(ltrb_),
smooth_embedding(cv::Mat()),
id(0),
is_activated(false),
timestamp(0),
starttime(0),
score(score_),
eta(0.9),
length(0) {
xyah = ltrb2xyah(ltrb);
update_embedding(embedding);
} }
inline Trajectory::Trajectory(cv::Vec4f &ltrb_, float score_, const cv::Mat &embedding) : inline Trajectory::Trajectory(const Trajectory &other)
state(New), ltrb(ltrb_), smooth_embedding(cv::Mat()), id(0), : state(other.state),
is_activated(false), timestamp(0), starttime(0), score(score_), eta(0.9), length(0) ltrb(other.ltrb),
{ id(other.id),
xyah = ltrb2xyah(ltrb); is_activated(other.is_activated),
update_embedding(embedding); timestamp(other.timestamp),
starttime(other.starttime),
xyah(other.xyah),
score(other.score),
eta(other.eta),
length(other.length) {
other.smooth_embedding.copyTo(smooth_embedding);
other.current_embedding.copyTo(current_embedding);
// copy state in KalmanFilter
other.statePre.copyTo(cv::KalmanFilter::statePre);
other.statePost.copyTo(cv::KalmanFilter::statePost);
other.errorCovPre.copyTo(cv::KalmanFilter::errorCovPre);
other.errorCovPost.copyTo(cv::KalmanFilter::errorCovPost);
} }
inline Trajectory::Trajectory(const Trajectory &other): inline Trajectory &Trajectory::operator=(const Trajectory &rhs) {
state(other.state), ltrb(other.ltrb), id(other.id), is_activated(other.is_activated), this->state = rhs.state;
timestamp(other.timestamp), starttime(other.starttime), xyah(other.xyah), this->ltrb = rhs.ltrb;
score(other.score), eta(other.eta), length(other.length) rhs.smooth_embedding.copyTo(this->smooth_embedding);
{ this->id = rhs.id;
other.smooth_embedding.copyTo(smooth_embedding); this->is_activated = rhs.is_activated;
other.current_embedding.copyTo(current_embedding); this->timestamp = rhs.timestamp;
// copy state in KalmanFilter this->starttime = rhs.starttime;
this->xyah = rhs.xyah;
other.statePre.copyTo(cv::KalmanFilter::statePre); this->score = rhs.score;
other.statePost.copyTo(cv::KalmanFilter::statePost); rhs.current_embedding.copyTo(this->current_embedding);
other.errorCovPre.copyTo(cv::KalmanFilter::errorCovPre); this->eta = rhs.eta;
other.errorCovPost.copyTo(cv::KalmanFilter::errorCovPost); this->length = rhs.length;
// copy state in KalmanFilter
rhs.statePre.copyTo(cv::KalmanFilter::statePre);
rhs.statePost.copyTo(cv::KalmanFilter::statePost);
rhs.errorCovPre.copyTo(cv::KalmanFilter::errorCovPre);
rhs.errorCovPost.copyTo(cv::KalmanFilter::errorCovPost);
return *this;
} }
inline Trajectory &Trajectory::operator=(const Trajectory &rhs) inline int Trajectory::next_id() {
{ ++count;
this->state = rhs.state; return count;
this->ltrb = rhs.ltrb;
rhs.smooth_embedding.copyTo(this->smooth_embedding);
this->id = rhs.id;
this->is_activated = rhs.is_activated;
this->timestamp = rhs.timestamp;
this->starttime = rhs.starttime;
this->xyah = rhs.xyah;
this->score = rhs.score;
rhs.current_embedding.copyTo(this->current_embedding);
this->eta = rhs.eta;
this->length = rhs.length;
// copy state in KalmanFilter
rhs.statePre.copyTo(cv::KalmanFilter::statePre);
rhs.statePost.copyTo(cv::KalmanFilter::statePost);
rhs.errorCovPre.copyTo(cv::KalmanFilter::errorCovPre);
rhs.errorCovPost.copyTo(cv::KalmanFilter::errorCovPost);
return *this;
} }
inline int Trajectory::next_id() inline void Trajectory::mark_lost(void) { state = Lost; }
{
++count;
return count;
}
inline void Trajectory::mark_lost(void) inline void Trajectory::mark_removed(void) { state = Removed; }
{
state = Lost;
}
inline void Trajectory::mark_removed(void)
{
state = Removed;
}
} // namespace PaddleDetection } // namespace PaddleDetection
...@@ -14,31 +14,29 @@ ...@@ -14,31 +14,29 @@
#pragma once #pragma once
#include <string> #include <algorithm>
#include <vector>
#include <utility>
#include <ctime> #include <ctime>
#include <numeric> #include <numeric>
#include <algorithm> #include <string>
#include <utility>
#include <vector>
#include "include/tracker.h" #include "include/tracker.h"
namespace PaddleDetection { namespace PaddleDetection {
struct Rect struct Rect {
{ float left;
float left; float top;
float top; float right;
float right; float bottom;
float bottom;
}; };
struct MOTTrack struct MOTTrack {
{ int ids;
int ids; float score;
float score; Rect rects;
Rect rects; int class_id = -1;
int class_id = -1;
}; };
typedef std::vector<MOTTrack> MOTResult; typedef std::vector<MOTTrack> MOTResult;
......
...@@ -13,18 +13,17 @@ ...@@ -13,18 +13,17 @@
// limitations under the License. // limitations under the License.
#include <sstream> #include <sstream>
// for setprecision // for setprecision
#include <iomanip>
#include <chrono> #include <chrono>
#include <iomanip>
#include "include/jde_predictor.h" #include "include/jde_predictor.h"
using namespace paddle_infer; // NOLINT
using namespace paddle_infer;
namespace PaddleDetection { namespace PaddleDetection {
// Load Model and create model predictor // Load Model and create model predictor
void JDEPredictor::LoadModel(const std::string& model_dir, void JDEPredictor::LoadModel(const std::string& model_dir,
const std::string& run_mode) { const std::string& run_mode) {
paddle_infer::Config config; paddle_infer::Config config;
std::string prog_file = model_dir + OS_PATH_SEP + "model.pdmodel"; std::string prog_file = model_dir + OS_PATH_SEP + "model.pdmodel";
std::string params_file = model_dir + OS_PATH_SEP + "model.pdiparams"; std::string params_file = model_dir + OS_PATH_SEP + "model.pdiparams";
...@@ -37,26 +36,24 @@ void JDEPredictor::LoadModel(const std::string& model_dir, ...@@ -37,26 +36,24 @@ void JDEPredictor::LoadModel(const std::string& model_dir,
auto precision = paddle_infer::Config::Precision::kFloat32; auto precision = paddle_infer::Config::Precision::kFloat32;
if (run_mode == "trt_fp32") { if (run_mode == "trt_fp32") {
precision = paddle_infer::Config::Precision::kFloat32; precision = paddle_infer::Config::Precision::kFloat32;
} } else if (run_mode == "trt_fp16") {
else if (run_mode == "trt_fp16") {
precision = paddle_infer::Config::Precision::kHalf; precision = paddle_infer::Config::Precision::kHalf;
} } else if (run_mode == "trt_int8") {
else if (run_mode == "trt_int8") {
precision = paddle_infer::Config::Precision::kInt8; precision = paddle_infer::Config::Precision::kInt8;
} else { } else {
printf("run_mode should be 'fluid', 'trt_fp32', 'trt_fp16' or 'trt_int8'"); printf(
"run_mode should be 'fluid', 'trt_fp32', 'trt_fp16' or 'trt_int8'");
} }
// set tensorrt // set tensorrt
config.EnableTensorRtEngine( config.EnableTensorRtEngine(1 << 30,
1 << 30, 1,
1, this->min_subgraph_size_,
this->min_subgraph_size_, precision,
precision, false,
false, this->trt_calib_mode_);
this->trt_calib_mode_);
} }
} else if (this->device_ == "XPU"){ } else if (this->device_ == "XPU") {
config.EnableXpu(10*1024*1024); config.EnableXpu(10 * 1024 * 1024);
} else { } else {
config.DisableGpu(); config.DisableGpu();
if (this->use_mkldnn_) { if (this->use_mkldnn_) {
...@@ -74,7 +71,9 @@ void JDEPredictor::LoadModel(const std::string& model_dir, ...@@ -74,7 +71,9 @@ void JDEPredictor::LoadModel(const std::string& model_dir,
predictor_ = std::move(CreatePredictor(config)); predictor_ = std::move(CreatePredictor(config));
} }
void FilterDets(const float conf_thresh, const cv::Mat dets, std::vector<int>* index) { void FilterDets(const float conf_thresh,
const cv::Mat dets,
std::vector<int>* index) {
for (int i = 0; i < dets.rows; ++i) { for (int i = 0; i < dets.rows; ++i) {
float score = *dets.ptr<float>(i, 4); float score = *dets.ptr<float>(i, 4);
if (score > conf_thresh) { if (score > conf_thresh) {
...@@ -89,9 +88,9 @@ void JDEPredictor::Preprocess(const cv::Mat& ori_im) { ...@@ -89,9 +88,9 @@ void JDEPredictor::Preprocess(const cv::Mat& ori_im) {
preprocessor_.Run(&im, &inputs_); preprocessor_.Run(&im, &inputs_);
} }
void JDEPredictor::Postprocess( void JDEPredictor::Postprocess(const cv::Mat dets,
const cv::Mat dets, const cv::Mat emb, const cv::Mat emb,
MOTResult* result) { MOTResult* result) {
result->clear(); result->clear();
std::vector<Track> tracks; std::vector<Track> tracks;
std::vector<int> valid; std::vector<int> valid;
...@@ -101,13 +100,13 @@ void JDEPredictor::Postprocess( ...@@ -101,13 +100,13 @@ void JDEPredictor::Postprocess(
new_dets.push_back(dets.row(valid[i])); new_dets.push_back(dets.row(valid[i]));
new_emb.push_back(emb.row(valid[i])); new_emb.push_back(emb.row(valid[i]));
} }
JDETracker::instance()->update(new_dets, new_emb, tracks); JDETracker::instance()->update(new_dets, new_emb, &tracks);
if (tracks.size() == 0) { if (tracks.size() == 0) {
MOTTrack mot_track; MOTTrack mot_track;
Rect ret = {*dets.ptr<float>(0, 0), Rect ret = {*dets.ptr<float>(0, 0),
*dets.ptr<float>(0, 1), *dets.ptr<float>(0, 1),
*dets.ptr<float>(0, 2), *dets.ptr<float>(0, 2),
*dets.ptr<float>(0, 3)}; *dets.ptr<float>(0, 3)};
mot_track.ids = 1; mot_track.ids = 1;
mot_track.score = *dets.ptr<float>(0, 4); mot_track.score = *dets.ptr<float>(0, 4);
mot_track.rects = ret; mot_track.rects = ret;
...@@ -124,24 +123,22 @@ void JDEPredictor::Postprocess( ...@@ -124,24 +123,22 @@ void JDEPredictor::Postprocess(
float area = w * h; float area = w * h;
if (area > min_box_area_ && !vertical) { if (area > min_box_area_ && !vertical) {
MOTTrack mot_track; MOTTrack mot_track;
Rect ret = {titer->ltrb[0], Rect ret = {
titer->ltrb[1], titer->ltrb[0], titer->ltrb[1], titer->ltrb[2], titer->ltrb[3]};
titer->ltrb[2],
titer->ltrb[3]};
mot_track.rects = ret; mot_track.rects = ret;
mot_track.score = titer->score; mot_track.score = titer->score;
mot_track.ids = titer->id; mot_track.ids = titer->id;
result->push_back(mot_track); result->push_back(mot_track);
} }
} }
} }
} }
} }
void JDEPredictor::Predict(const std::vector<cv::Mat> imgs, void JDEPredictor::Predict(const std::vector<cv::Mat> imgs,
const double threshold, const double threshold,
MOTResult* result, MOTResult* result,
std::vector<double>* times) { std::vector<double>* times) {
auto preprocess_start = std::chrono::steady_clock::now(); auto preprocess_start = std::chrono::steady_clock::now();
int batch_size = imgs.size(); int batch_size = imgs.size();
...@@ -149,7 +146,7 @@ void JDEPredictor::Predict(const std::vector<cv::Mat> imgs, ...@@ -149,7 +146,7 @@ void JDEPredictor::Predict(const std::vector<cv::Mat> imgs,
std::vector<float> in_data_all; std::vector<float> in_data_all;
std::vector<float> im_shape_all(batch_size * 2); std::vector<float> im_shape_all(batch_size * 2);
std::vector<float> scale_factor_all(batch_size * 2); std::vector<float> scale_factor_all(batch_size * 2);
// Preprocess image // Preprocess image
for (int bs_idx = 0; bs_idx < batch_size; bs_idx++) { for (int bs_idx = 0; bs_idx < batch_size; bs_idx++) {
cv::Mat im = imgs.at(bs_idx); cv::Mat im = imgs.at(bs_idx);
...@@ -160,8 +157,8 @@ void JDEPredictor::Predict(const std::vector<cv::Mat> imgs, ...@@ -160,8 +157,8 @@ void JDEPredictor::Predict(const std::vector<cv::Mat> imgs,
scale_factor_all[bs_idx * 2] = inputs_.scale_factor_[0]; scale_factor_all[bs_idx * 2] = inputs_.scale_factor_[0];
scale_factor_all[bs_idx * 2 + 1] = inputs_.scale_factor_[1]; scale_factor_all[bs_idx * 2 + 1] = inputs_.scale_factor_[1];
// TODO: reduce cost time in_data_all.insert(
in_data_all.insert(in_data_all.end(), inputs_.im_data_.begin(), inputs_.im_data_.end()); in_data_all.end(), inputs_.im_data_.begin(), inputs_.im_data_.end());
} }
// Prepare input tensor // Prepare input tensor
...@@ -181,7 +178,7 @@ void JDEPredictor::Predict(const std::vector<cv::Mat> imgs, ...@@ -181,7 +178,7 @@ void JDEPredictor::Predict(const std::vector<cv::Mat> imgs,
in_tensor->CopyFromCpu(scale_factor_all.data()); in_tensor->CopyFromCpu(scale_factor_all.data());
} }
} }
auto preprocess_end = std::chrono::steady_clock::now(); auto preprocess_end = std::chrono::steady_clock::now();
std::vector<int> bbox_shape; std::vector<int> bbox_shape;
std::vector<int> emb_shape; std::vector<int> emb_shape;
...@@ -207,7 +204,7 @@ void JDEPredictor::Predict(const std::vector<cv::Mat> imgs, ...@@ -207,7 +204,7 @@ void JDEPredictor::Predict(const std::vector<cv::Mat> imgs,
} }
bbox_data_.resize(bbox_size); bbox_data_.resize(bbox_size);
bbox_tensor->CopyToCpu(bbox_data_.data()); bbox_tensor->CopyToCpu(bbox_data_.data());
emb_data_.resize(emb_size); emb_data_.resize(emb_size);
emb_tensor->CopyToCpu(emb_data_.data()); emb_tensor->CopyToCpu(emb_data_.data());
...@@ -224,12 +221,14 @@ void JDEPredictor::Predict(const std::vector<cv::Mat> imgs, ...@@ -224,12 +221,14 @@ void JDEPredictor::Predict(const std::vector<cv::Mat> imgs,
auto postprocess_end = std::chrono::steady_clock::now(); auto postprocess_end = std::chrono::steady_clock::now();
std::chrono::duration<float> preprocess_diff = preprocess_end - preprocess_start; std::chrono::duration<float> preprocess_diff =
(*times)[0] += double(preprocess_diff.count() * 1000); preprocess_end - preprocess_start;
(*times)[0] += static_cast<double>(preprocess_diff.count() * 1000);
std::chrono::duration<float> inference_diff = inference_end - inference_start; std::chrono::duration<float> inference_diff = inference_end - inference_start;
(*times)[1] += double(inference_diff.count() * 1000); (*times)[1] += static_cast<double>(inference_diff.count() * 1000);
std::chrono::duration<float> postprocess_diff = postprocess_end - postprocess_start; std::chrono::duration<float> postprocess_diff =
(*times)[2] += double(postprocess_diff.count() * 1000); postprocess_end - postprocess_start;
(*times)[2] += static_cast<double>(postprocess_diff.count() * 1000);
} }
} // namespace PaddleDetection } // namespace PaddleDetection
...@@ -27,379 +27,383 @@ namespace PaddleDetection { ...@@ -27,379 +27,383 @@ namespace PaddleDetection {
/** Column-reduction and reduction transfer for a dense cost matrix. /** Column-reduction and reduction transfer for a dense cost matrix.
*/ */
int _ccrrt_dense(const int n, float *cost[], int _ccrrt_dense(
int *free_rows, int *x, int *y, float *v) const int n, float *cost[], int *free_rows, int *x, int *y, float *v) {
{ int n_free_rows;
int n_free_rows; bool *unique;
bool *unique;
for (int i = 0; i < n; i++) {
for (int i = 0; i < n; i++) { x[i] = -1;
x[i] = -1; v[i] = LARGE;
v[i] = LARGE; y[i] = 0;
y[i] = 0; }
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
const float c = cost[i][j];
if (c < v[j]) {
v[j] = c;
y[j] = i;
}
} }
for (int i = 0; i < n; i++) { }
for (int j = 0; j < n; j++) { NEW(unique, bool, n);
const float c = cost[i][j]; memset(unique, TRUE, n);
if (c < v[j]) { {
v[j] = c; int j = n;
y[j] = i; do {
} j--;
const int i = y[j];
if (x[i] < 0) {
x[i] = j;
} else {
unique[i] = FALSE;
y[j] = -1;
}
} while (j > 0);
}
n_free_rows = 0;
for (int i = 0; i < n; i++) {
if (x[i] < 0) {
free_rows[n_free_rows++] = i;
} else if (unique[i]) {
const int j = x[i];
float min = LARGE;
for (int j2 = 0; j2 < n; j2++) {
if (j2 == static_cast<int>(j)) {
continue;
} }
} const float c = cost[i][j2] - v[j2];
NEW(unique, bool, n); if (c < min) {
memset(unique, TRUE, n); min = c;
{
int j = n;
do {
j--;
const int i = y[j];
if (x[i] < 0) {
x[i] = j;
} else {
unique[i] = FALSE;
y[j] = -1;
}
} while (j > 0);
}
n_free_rows = 0;
for (int i = 0; i < n; i++) {
if (x[i] < 0) {
free_rows[n_free_rows++] = i;
} else if (unique[i]) {
const int j = x[i];
float min = LARGE;
for (int j2 = 0; j2 < n; j2++) {
if (j2 == (int)j) {
continue;
}
const float c = cost[i][j2] - v[j2];
if (c < min) {
min = c;
}
}
v[j] -= min;
} }
}
v[j] -= min;
} }
FREE(unique); }
return n_free_rows; FREE(unique);
return n_free_rows;
} }
/** Augmenting row reduction for a dense cost matrix. /** Augmenting row reduction for a dense cost matrix.
*/ */
int _carr_dense( int _carr_dense(const int n,
const int n, float *cost[], float *cost[],
const int n_free_rows, const int n_free_rows,
int *free_rows, int *x, int *y, float *v) int *free_rows,
{ int *x,
int current = 0; int *y,
int new_free_rows = 0; float *v) {
int rr_cnt = 0; int current = 0;
while (current < n_free_rows) { int new_free_rows = 0;
int i0; int rr_cnt = 0;
int j1, j2; while (current < n_free_rows) {
float v1, v2, v1_new; int i0;
bool v1_lowers; int j1, j2;
float v1, v2, v1_new;
rr_cnt++; bool v1_lowers;
const int free_i = free_rows[current++];
j1 = 0; rr_cnt++;
v1 = cost[free_i][0] - v[0]; const int free_i = free_rows[current++];
j2 = -1; j1 = 0;
v2 = LARGE; v1 = cost[free_i][0] - v[0];
for (int j = 1; j < n; j++) { j2 = -1;
const float c = cost[free_i][j] - v[j]; v2 = LARGE;
if (c < v2) { for (int j = 1; j < n; j++) {
if (c >= v1) { const float c = cost[free_i][j] - v[j];
v2 = c; if (c < v2) {
j2 = j; if (c >= v1) {
} else { v2 = c;
v2 = v1; j2 = j;
v1 = c; } else {
j2 = j1; v2 = v1;
j1 = j; v1 = c;
} j2 = j1;
} j1 = j;
} }
i0 = y[j1]; }
v1_new = v[j1] - (v2 - v1); }
v1_lowers = v1_new < v[j1]; i0 = y[j1];
if (rr_cnt < current * n) { v1_new = v[j1] - (v2 - v1);
if (v1_lowers) { v1_lowers = v1_new < v[j1];
v[j1] = v1_new; if (rr_cnt < current * n) {
} else if (i0 >= 0 && j2 >= 0) { if (v1_lowers) {
j1 = j2; v[j1] = v1_new;
i0 = y[j2]; } else if (i0 >= 0 && j2 >= 0) {
} j1 = j2;
if (i0 >= 0) { i0 = y[j2];
if (v1_lowers) { }
free_rows[--current] = i0; if (i0 >= 0) {
} else { if (v1_lowers) {
free_rows[new_free_rows++] = i0; free_rows[--current] = i0;
}
}
} else { } else {
if (i0 >= 0) { free_rows[new_free_rows++] = i0;
free_rows[new_free_rows++] = i0;
}
} }
x[free_i] = j1; }
y[j1] = free_i; } else {
if (i0 >= 0) {
free_rows[new_free_rows++] = i0;
}
} }
return new_free_rows; x[free_i] = j1;
y[j1] = free_i;
}
return new_free_rows;
} }
/** Find columns with minimum d[j] and put them on the SCAN list. /** Find columns with minimum d[j] and put them on the SCAN list.
*/ */
int _find_dense(const int n, int lo, float *d, int *cols, int *y) int _find_dense(const int n, int lo, float *d, int *cols, int *y) {
{ int hi = lo + 1;
int hi = lo + 1; float mind = d[cols[lo]];
float mind = d[cols[lo]]; for (int k = hi; k < n; k++) {
for (int k = hi; k < n; k++) { int j = cols[k];
int j = cols[k]; if (d[j] <= mind) {
if (d[j] <= mind) { if (d[j] < mind) {
if (d[j] < mind) { hi = lo;
hi = lo; mind = d[j];
mind = d[j]; }
} cols[k] = cols[hi];
cols[k] = cols[hi]; cols[hi++] = j;
cols[hi++] = j;
}
} }
return hi; }
return hi;
} }
// Scan all columns in TODO starting from arbitrary column in SCAN // Scan all columns in TODO starting from arbitrary column in SCAN
// and try to decrease d of the TODO columns using the SCAN column. // and try to decrease d of the TODO columns using the SCAN column.
int _scan_dense(const int n, float *cost[], int _scan_dense(const int n,
int *plo, int*phi, float *cost[],
float *d, int *cols, int *pred, int *plo,
int *y, float *v) int *phi,
{ float *d,
int lo = *plo; int *cols,
int hi = *phi; int *pred,
float h, cred_ij; int *y,
float *v) {
while (lo != hi) { int lo = *plo;
int j = cols[lo++]; int hi = *phi;
const int i = y[j]; float h, cred_ij;
const float mind = d[j];
h = cost[i][j] - v[j] - mind; while (lo != hi) {
// For all columns in TODO int j = cols[lo++];
for (int k = hi; k < n; k++) { const int i = y[j];
j = cols[k]; const float mind = d[j];
cred_ij = cost[i][j] - v[j] - h; h = cost[i][j] - v[j] - mind;
if (cred_ij < d[j]) { // For all columns in TODO
d[j] = cred_ij; for (int k = hi; k < n; k++) {
pred[j] = i; j = cols[k];
if (cred_ij == mind) { cred_ij = cost[i][j] - v[j] - h;
if (y[j] < 0) { if (cred_ij < d[j]) {
return j; d[j] = cred_ij;
} pred[j] = i;
cols[k] = cols[hi]; if (cred_ij == mind) {
cols[hi++] = j; if (y[j] < 0) {
} return j;
} }
cols[k] = cols[hi];
cols[hi++] = j;
} }
}
} }
*plo = lo; }
*phi = hi; *plo = lo;
return -1; *phi = hi;
return -1;
} }
/** Single iteration of modified Dijkstra shortest path algorithm as explained
/** Single iteration of modified Dijkstra shortest path algorithm as explained in the JV paper. * in the JV paper.
* *
* This is a dense matrix version. * This is a dense matrix version.
* *
* \return The closest free column index. * \return The closest free column index.
*/ */
int find_path_dense( int find_path_dense(const int n,
const int n, float *cost[], float *cost[],
const int start_i, const int start_i,
int *y, float *v, int *y,
int *pred) float *v,
{ int *pred) {
int lo = 0, hi = 0; int lo = 0, hi = 0;
int final_j = -1; int final_j = -1;
int n_ready = 0; int n_ready = 0;
int *cols; int *cols;
float *d; float *d;
NEW(cols, int, n); NEW(cols, int, n);
NEW(d, float, n); NEW(d, float, n);
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
cols[i] = i; cols[i] = i;
pred[i] = start_i; pred[i] = start_i;
d[i] = cost[start_i][i] - v[i]; d[i] = cost[start_i][i] - v[i];
} }
while (final_j == -1) { while (final_j == -1) {
// No columns left on the SCAN list. // No columns left on the SCAN list.
if (lo == hi) { if (lo == hi) {
n_ready = lo; n_ready = lo;
hi = _find_dense(n, lo, d, cols, y); hi = _find_dense(n, lo, d, cols, y);
for (int k = lo; k < hi; k++) { for (int k = lo; k < hi; k++) {
const int j = cols[k]; const int j = cols[k];
if (y[j] < 0) { if (y[j] < 0) {
final_j = j; final_j = j;
}
}
}
if (final_j == -1) {
final_j = _scan_dense(
n, cost, &lo, &hi, d, cols, pred, y, v);
} }
}
} }
if (final_j == -1) {
final_j = _scan_dense(n, cost, &lo, &hi, d, cols, pred, y, v);
}
}
{ {
const float mind = d[cols[lo]]; const float mind = d[cols[lo]];
for (int k = 0; k < n_ready; k++) { for (int k = 0; k < n_ready; k++) {
const int j = cols[k]; const int j = cols[k];
v[j] += d[j] - mind; v[j] += d[j] - mind;
}
} }
}
FREE(cols); FREE(cols);
FREE(d); FREE(d);
return final_j; return final_j;
} }
/** Augment for a dense cost matrix. /** Augment for a dense cost matrix.
*/ */
int _ca_dense( int _ca_dense(const int n,
const int n, float *cost[], float *cost[],
const int n_free_rows, const int n_free_rows,
int *free_rows, int *x, int *y, float *v) int *free_rows,
{ int *x,
int *pred; int *y,
float *v) {
NEW(pred, int, n); int *pred;
for (int *pfree_i = free_rows; pfree_i < free_rows + n_free_rows; pfree_i++) { NEW(pred, int, n);
int i = -1, j;
int k = 0; for (int *pfree_i = free_rows; pfree_i < free_rows + n_free_rows; pfree_i++) {
int i = -1, j;
j = find_path_dense(n, cost, *pfree_i, y, v, pred); int k = 0;
while (i != *pfree_i) {
i = pred[j]; j = find_path_dense(n, cost, *pfree_i, y, v, pred);
y[j] = i; while (i != *pfree_i) {
SWAP_INDICES(j, x[i]); i = pred[j];
k++; y[j] = i;
} SWAP_INDICES(j, x[i]);
k++;
} }
FREE(pred); }
return 0; FREE(pred);
return 0;
} }
/** Solve dense sparse LAP. /** Solve dense sparse LAP.
*/ */
int lapjv_internal( int lapjv_internal(const cv::Mat &cost,
const cv::Mat &cost, const bool extend_cost, const float cost_limit, const bool extend_cost,
int *x, int *y ) { const float cost_limit,
int n_rows = cost.rows; int *x,
int n_cols = cost.cols; int *y) {
int n; int n_rows = cost.rows;
if (n_rows == n_cols) { int n_cols = cost.cols;
n = n_rows; int n;
} else if (!extend_cost) { if (n_rows == n_cols) {
throw std::invalid_argument("Square cost array expected. If cost is intentionally non-square, pass extend_cost=True."); n = n_rows;
} else if (!extend_cost) {
throw std::invalid_argument(
"Square cost array expected. If cost is intentionally non-square, pass "
"extend_cost=True.");
}
// Get extend cost
if (extend_cost || cost_limit < LARGE) {
n = n_rows + n_cols;
}
cv::Mat cost_expand(n, n, CV_32F);
float expand_value;
if (cost_limit < LARGE) {
expand_value = cost_limit / 2;
} else {
double max_v;
minMaxLoc(cost, nullptr, &max_v);
expand_value = static_cast<float>(max_v) + 1.;
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
cost_expand.at<float>(i, j) = expand_value;
if (i >= n_rows && j >= n_cols) {
cost_expand.at<float>(i, j) = 0;
} else if (i < n_rows && j < n_cols) {
cost_expand.at<float>(i, j) = cost.at<float>(i, j);
}
} }
}
// Get extend cost
if (extend_cost || cost_limit < LARGE) { // Convert Mat to pointer array
n = n_rows + n_cols; float **cost_ptr;
NEW(cost_ptr, float *, n);
for (int i = 0; i < n; ++i) {
NEW(cost_ptr[i], float, n);
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
cost_ptr[i][j] = cost_expand.at<float>(i, j);
} }
cv::Mat cost_expand(n, n, CV_32F); }
float expand_value;
if (cost_limit < LARGE) { int ret;
expand_value = cost_limit / 2; int *free_rows;
} else { float *v;
double max_v; int *x_c;
minMaxLoc(cost, nullptr, &max_v); int *y_c;
expand_value = (float)max_v + 1;
NEW(free_rows, int, n);
NEW(v, float, n);
NEW(x_c, int, n);
NEW(y_c, int, n);
ret = _ccrrt_dense(n, cost_ptr, free_rows, x_c, y_c, v);
int i = 0;
while (ret > 0 && i < 2) {
ret = _carr_dense(n, cost_ptr, ret, free_rows, x_c, y_c, v);
i++;
}
if (ret > 0) {
ret = _ca_dense(n, cost_ptr, ret, free_rows, x_c, y_c, v);
}
FREE(v);
FREE(free_rows);
for (int i = 0; i < n; ++i) {
FREE(cost_ptr[i]);
}
FREE(cost_ptr);
if (ret != 0) {
if (ret == -1) {
throw "Out of memory.";
} }
throw "Unknown error (lapjv_internal)";
for (int i = 0; i < n; ++i) { }
for (int j = 0; j < n; ++j) { // Get output of x, y, opt
cost_expand.at<float>(i, j) = expand_value; for (int i = 0; i < n; ++i) {
if (i >= n_rows && j >= n_cols) { if (i < n_rows) {
cost_expand.at<float>(i, j) = 0; x[i] = x_c[i];
} else if (i < n_rows && j < n_cols) { if (x[i] >= n_cols) {
cost_expand.at<float>(i, j) = cost.at<float>(i, j); x[i] = -1;
}
} }
}
// Convert Mat to pointer array
float **cost_ptr;
NEW(cost_ptr, float *, n);
for (int i = 0; i < n; ++i) {
NEW(cost_ptr[i], float, n);
} }
for (int i = 0; i < n; ++i) { if (i < n_cols) {
for (int j = 0; j < n; ++j) { y[i] = y_c[i];
cost_ptr[i][j] = cost_expand.at<float>(i, j); if (y[i] >= n_rows) {
y[i] = -1;
} }
} }
}
int ret; FREE(x_c);
int *free_rows; FREE(y_c);
float *v; return ret;
int *x_c;
int *y_c;
NEW(free_rows, int, n);
NEW(v, float, n);
NEW(x_c, int, n);
NEW(y_c, int, n);
ret = _ccrrt_dense(n, cost_ptr, free_rows, x_c, y_c, v);
int i = 0;
while (ret > 0 && i < 2) {
ret = _carr_dense(n, cost_ptr, ret, free_rows, x_c, y_c, v);
i++;
}
if (ret > 0) {
ret = _ca_dense(n, cost_ptr, ret, free_rows, x_c, y_c, v);
}
FREE(v);
FREE(free_rows);
for (int i = 0; i < n; ++i) {
FREE(cost_ptr[i]);
}
FREE(cost_ptr);
if (ret != 0) {
if (ret == -1){
throw "Out of memory.";
}
throw "Unknown error (lapjv_internal)";
}
// Get output of x, y, opt
for (int i = 0; i < n; ++i) {
if (i < n_rows) {
x[i] = x_c[i];
if (x[i] >= n_cols) {
x[i] = -1;
}
}
if (i < n_cols) {
y[i] = y_c[i];
if (y[i] >= n_rows) {
y[i] = -1;
}
}
}
FREE(x_c);
FREE(y_c);
return ret;
} }
} // namespace PaddleDetection } // namespace PaddleDetection
...@@ -14,44 +14,55 @@ ...@@ -14,44 +14,55 @@
#include <glog/logging.h> #include <glog/logging.h>
#include <math.h>
#include <sys/types.h>
#include <algorithm>
#include <iostream> #include <iostream>
#include <numeric>
#include <string> #include <string>
#include <vector> #include <vector>
#include <numeric>
#include <sys/types.h>
#include <sys/stat.h>
#include <math.h>
#include <algorithm>
#ifdef _WIN32 #ifdef _WIN32
#include <direct.h> #include <direct.h>
#include <io.h> #include <io.h>
#elif LINUX #else
#include <stdarg.h> #include <stdarg.h>
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
#include "include/pipeline.h"
#include <gflags/gflags.h> #include <gflags/gflags.h>
#include "include/pipeline.h"
DEFINE_string(video_file, "", "Path of input video."); DEFINE_string(video_file, "", "Path of input video.");
DEFINE_string(video_other_file, "", "Path of other input video used for MTMCT."); DEFINE_string(video_other_file,
DEFINE_string(device, "CPU", "Choose the device you want to run, it can be: CPU/GPU/XPU, default is CPU."); "",
"Path of other input video used for MTMCT.");
DEFINE_string(device,
"CPU",
"Choose the device you want to run, it can be: CPU/GPU/XPU, "
"default is CPU.");
DEFINE_double(threshold, 0.5, "Threshold of score."); DEFINE_double(threshold, 0.5, "Threshold of score.");
DEFINE_string(output_dir, "output", "Directory of output visualization files."); DEFINE_string(output_dir, "output", "Directory of output visualization files.");
DEFINE_string(run_mode, "fluid", "Mode of running(fluid/trt_fp32/trt_fp16/trt_int8)"); DEFINE_string(run_mode,
"fluid",
"Mode of running(fluid/trt_fp32/trt_fp16/trt_int8)");
DEFINE_int32(gpu_id, 0, "Device id of GPU to execute"); DEFINE_int32(gpu_id, 0, "Device id of GPU to execute");
DEFINE_bool(use_mkldnn, false, "Whether use mkldnn with CPU"); DEFINE_bool(use_mkldnn, false, "Whether use mkldnn with CPU");
DEFINE_int32(cpu_threads, 1, "Num of threads with CPU"); DEFINE_int32(cpu_threads, 1, "Num of threads with CPU");
DEFINE_bool(trt_calib_mode, false, "If the model is produced by TRT offline quantitative calibration, trt_calib_mode need to set True"); DEFINE_bool(trt_calib_mode,
false,
"If the model is produced by TRT offline quantitative calibration, "
"trt_calib_mode need to set True");
DEFINE_bool(tiny_obj, false, "Whether tracking tiny object"); DEFINE_bool(tiny_obj, false, "Whether tracking tiny object");
DEFINE_bool(count, false, "Whether counting after tracking"); DEFINE_bool(count, false, "Whether counting after tracking");
DEFINE_bool(save_result, false, "Whether saving result after tracking"); DEFINE_bool(save_result, false, "Whether saving result after tracking");
DEFINE_string(scene, "", "scene of tracking system, it can be : pedestrian/vehicle/multiclass"); DEFINE_string(
scene,
"",
"scene of tracking system, it can be : pedestrian/vehicle/multiclass");
DEFINE_bool(is_mtmct, false, "Whether use multi-target multi-camera tracking"); DEFINE_bool(is_mtmct, false, "Whether use multi-target multi-camera tracking");
static std::string DirName(const std::string &filepath) { static std::string DirName(const std::string& filepath) {
auto pos = filepath.rfind(OS_PATH_SEP); auto pos = filepath.rfind(OS_PATH_SEP);
if (pos == std::string::npos) { if (pos == std::string::npos) {
return ""; return "";
...@@ -59,7 +70,7 @@ static std::string DirName(const std::string &filepath) { ...@@ -59,7 +70,7 @@ static std::string DirName(const std::string &filepath) {
return filepath.substr(0, pos); return filepath.substr(0, pos);
} }
static bool PathExists(const std::string& path){ static bool PathExists(const std::string& path) {
#ifdef _WIN32 #ifdef _WIN32
struct _stat buffer; struct _stat buffer;
return (_stat(path.c_str(), &buffer) == 0); return (_stat(path.c_str(), &buffer) == 0);
...@@ -101,13 +112,18 @@ int main(int argc, char** argv) { ...@@ -101,13 +112,18 @@ int main(int argc, char** argv) {
<< "-scene=pedestrian/vehicle/multiclass" << std::endl; << "-scene=pedestrian/vehicle/multiclass" << std::endl;
return -1; return -1;
} }
if (!(FLAGS_run_mode == "fluid" || FLAGS_run_mode == "trt_fp32" if (!(FLAGS_run_mode == "fluid" || FLAGS_run_mode == "trt_fp32" ||
|| FLAGS_run_mode == "trt_fp16" || FLAGS_run_mode == "trt_int8")) { FLAGS_run_mode == "trt_fp16" || FLAGS_run_mode == "trt_int8")) {
std::cout << "run_mode should be 'fluid', 'trt_fp32', 'trt_fp16' or 'trt_int8'."; std::cout
<< "run_mode should be 'fluid', 'trt_fp32', 'trt_fp16' or 'trt_int8'.";
return -1; return -1;
} }
transform(FLAGS_device.begin(),FLAGS_device.end(),FLAGS_device.begin(),::toupper); transform(FLAGS_device.begin(),
if (!(FLAGS_device == "CPU" || FLAGS_device == "GPU" || FLAGS_device == "XPU")) { FLAGS_device.end(),
FLAGS_device.begin(),
::toupper);
if (!(FLAGS_device == "CPU" || FLAGS_device == "GPU" ||
FLAGS_device == "XPU")) {
std::cout << "device should be 'CPU', 'GPU' or 'XPU'."; std::cout << "device should be 'CPU', 'GPU' or 'XPU'.";
return -1; return -1;
} }
...@@ -116,12 +132,19 @@ int main(int argc, char** argv) { ...@@ -116,12 +132,19 @@ int main(int argc, char** argv) {
MkDirs(FLAGS_output_dir); MkDirs(FLAGS_output_dir);
} }
PaddleDetection::Pipeline pipeline( PaddleDetection::Pipeline pipeline(FLAGS_device,
FLAGS_device, FLAGS_threshold, FLAGS_threshold,
FLAGS_output_dir, FLAGS_run_mode, FLAGS_gpu_id, FLAGS_output_dir,
FLAGS_use_mkldnn, FLAGS_cpu_threads, FLAGS_trt_calib_mode, FLAGS_run_mode,
FLAGS_count, FLAGS_save_result, FLAGS_scene, FLAGS_tiny_obj, FLAGS_gpu_id,
FLAGS_is_mtmct); FLAGS_use_mkldnn,
FLAGS_cpu_threads,
FLAGS_trt_calib_mode,
FLAGS_count,
FLAGS_save_result,
FLAGS_scene,
FLAGS_tiny_obj,
FLAGS_is_mtmct);
pipeline.SetInput(FLAGS_video_file); pipeline.SetInput(FLAGS_video_file);
if (!FLAGS_video_other_file.empty()) { if (!FLAGS_video_other_file.empty()) {
......
...@@ -14,18 +14,17 @@ ...@@ -14,18 +14,17 @@
#include <sstream> #include <sstream>
// for setprecision // for setprecision
#include <chrono>
#include <iomanip>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <iomanip>
#include <chrono>
#include "include/pipeline.h" #include "include/pipeline.h"
#include "include/postprocess.h" #include "include/postprocess.h"
#include "include/predictor.h" #include "include/predictor.h"
namespace PaddleDetection { namespace PaddleDetection {
void Pipeline::SetInput(const std::string& input_video) {
void Pipeline::SetInput(std::string& input_video) {
input_.push_back(input_video); input_.push_back(input_video);
} }
...@@ -66,8 +65,8 @@ void Pipeline::SelectModel(const std::string& scene, ...@@ -66,8 +65,8 @@ void Pipeline::SelectModel(const std::string& scene,
det_model_dir_ = "../vehicle_det"; det_model_dir_ = "../vehicle_det";
reid_model_dir_ = "../vehicle_reid"; reid_model_dir_ = "../vehicle_reid";
} else if (is_mtmct && scene == "multiclass") { } else if (is_mtmct && scene == "multiclass") {
throw "Multi-camera tracking is not supported in multiclass scene now."; throw "Multi-camera tracking is not supported in multiclass scene now.";
} }
} }
void Pipeline::InitPredictor() { void Pipeline::InitPredictor() {
...@@ -76,16 +75,29 @@ void Pipeline::InitPredictor() { ...@@ -76,16 +75,29 @@ void Pipeline::InitPredictor() {
} }
if (!track_model_dir_.empty()) { if (!track_model_dir_.empty()) {
jde_sct_ = std::make_shared<PaddleDetection::JDEPredictor>(device_, track_model_dir_, threshold_, run_mode_, gpu_id_, use_mkldnn_, cpu_threads_, trt_calib_mode_); jde_sct_ = std::make_shared<PaddleDetection::JDEPredictor>(device_,
track_model_dir_,
threshold_,
run_mode_,
gpu_id_,
use_mkldnn_,
cpu_threads_,
trt_calib_mode_);
} }
if (!det_model_dir_.empty()) { if (!det_model_dir_.empty()) {
sde_sct_ = std::make_shared<PaddleDetection::SDEPredictor>(device_, det_model_dir_, reid_model_dir_, threshold_, run_mode_, gpu_id_, use_mkldnn_, cpu_threads_, trt_calib_mode_); sde_sct_ = std::make_shared<PaddleDetection::SDEPredictor>(device_,
det_model_dir_,
reid_model_dir_,
threshold_,
run_mode_,
gpu_id_,
use_mkldnn_,
cpu_threads_,
trt_calib_mode_);
} }
} }
void Pipeline::Run() { void Pipeline::Run() {
if (track_model_dir_.empty() && det_model_dir_.empty()) { if (track_model_dir_.empty() && det_model_dir_.empty()) {
std::cout << "Pipeline must use SelectModel before Run"; std::cout << "Pipeline must use SelectModel before Run";
return; return;
...@@ -98,21 +110,21 @@ void Pipeline::Run() { ...@@ -98,21 +110,21 @@ void Pipeline::Run() {
if (!track_model_dir_.empty()) { if (!track_model_dir_.empty()) {
// single camera // single camera
if (input_.size() > 1) { if (input_.size() > 1) {
throw "Single camera tracking except single video, but received %d", input_.size(); throw "Single camera tracking except single video, but received %d",
input_.size();
} }
PredictMOT(input_[0]); PredictMOT(input_[0]);
} else { } else {
// multi cameras // multi cameras
if (input_.size() != 2) { if (input_.size() != 2) {
throw "Multi camera tracking except two videos, but received %d", input_.size(); throw "Multi camera tracking except two videos, but received %d",
input_.size();
} }
PredictMTMCT(input_); PredictMTMCT(input_);
} }
} }
void Pipeline::PredictMOT(const std::string& video_path) { void Pipeline::PredictMOT(const std::string& video_path) {
// Open video // Open video
cv::VideoCapture capture; cv::VideoCapture capture;
capture.open(video_path.c_str()); capture.open(video_path.c_str());
...@@ -134,9 +146,9 @@ void Pipeline::PredictMOT(const std::string& video_path) { ...@@ -134,9 +146,9 @@ void Pipeline::PredictMOT(const std::string& video_path) {
// Create VideoWriter for output // Create VideoWriter for output
cv::VideoWriter video_out; cv::VideoWriter video_out;
std::string video_out_path = output_dir_ + OS_PATH_SEP + "mot_output.mp4"; std::string video_out_path = output_dir_ + OS_PATH_SEP + "mot_output.mp4";
int fcc = cv::VideoWriter::fourcc('m','p','4','v'); int fcc = cv::VideoWriter::fourcc('m', 'p', '4', 'v');
video_out.open(video_out_path.c_str(), video_out.open(video_out_path.c_str(),
fcc, //0x00000021, fcc, // 0x00000021,
video_fps, video_fps,
cv::Size(video_width, video_height), cv::Size(video_width, video_height),
true); true);
...@@ -155,7 +167,7 @@ void Pipeline::PredictMOT(const std::string& video_path) { ...@@ -155,7 +167,7 @@ void Pipeline::PredictMOT(const std::string& video_path) {
// Capture all frames and do inference // Capture all frames and do inference
cv::Mat frame; cv::Mat frame;
int frame_id = 0; int frame_id = 0;
std::vector<std::string> records; std::vector<std::string> records;
records.push_back("result format: frame_id, track_id, x1, y1, w, h\n"); records.push_back("result format: frame_id, track_id, x1, y1, w, h\n");
...@@ -170,20 +182,21 @@ void Pipeline::PredictMOT(const std::string& video_path) { ...@@ -170,20 +182,21 @@ void Pipeline::PredictMOT(const std::string& video_path) {
frame_id += 1; frame_id += 1;
total_time = std::accumulate(det_times.begin(), det_times.end(), 0.); total_time = std::accumulate(det_times.begin(), det_times.end(), 0.);
times = total_time / frame_id; times = total_time / frame_id;
LOG(INFO) << "frame_id: " << frame_id LOG(INFO) << "frame_id: " << frame_id
<< " predict time(s): "<< total_time / 1000; << " predict time(s): " << total_time / 1000;
cv::Mat out_img = PaddleDetection::VisualizeTrackResult( cv::Mat out_img = PaddleDetection::VisualizeTrackResult(
frame, result, 1000./times, frame_id); frame, result, 1000. / times, frame_id);
if (count_) { if (count_) {
// Count total number // Count total number
// Count in & out number // Count in & out number
PaddleDetection::FlowStatistic(result, frame_id, &count_list, &in_count_list, &out_count_list); PaddleDetection::FlowStatistic(
result, frame_id, &count_list, &in_count_list, &out_count_list);
} }
if (save_result_) { if (save_result_) {
PaddleDetection::SaveMOTResult(result, frame_id, records); PaddleDetection::SaveMOTResult(result, frame_id, &records);
} }
video_out.write(out_img); video_out.write(out_img);
} }
...@@ -194,10 +207,11 @@ void Pipeline::PredictMOT(const std::string& video_path) { ...@@ -194,10 +207,11 @@ void Pipeline::PredictMOT(const std::string& video_path) {
LOG(INFO) << "Total frame: " << frame_id; LOG(INFO) << "Total frame: " << frame_id;
LOG(INFO) << "Visualized output saved as " << video_out_path.c_str(); LOG(INFO) << "Visualized output saved as " << video_out_path.c_str();
if (save_result_) { if (save_result_) {
FILE * fp; FILE* fp;
std::string result_output_path = output_dir_ + OS_PATH_SEP + "mot_output.txt"; std::string result_output_path =
if((fp = fopen(result_output_path.c_str(), "w+")) == NULL) { output_dir_ + OS_PATH_SEP + "mot_output.txt";
if ((fp = fopen(result_output_path.c_str(), "w+")) == NULL) {
printf("Open %s error.\n", result_output_path.c_str()); printf("Open %s error.\n", result_output_path.c_str());
return; return;
} }
...@@ -214,7 +228,13 @@ void Pipeline::PredictMTMCT(const std::vector<std::string> video_path) { ...@@ -214,7 +228,13 @@ void Pipeline::PredictMTMCT(const std::vector<std::string> video_path) {
throw "Not Implement!"; throw "Not Implement!";
} }
void Pipeline::RunMOTStream(const cv::Mat img, const int frame_id, cv::Mat& out_img, std::vector<std::string>& records, std::vector<int>& count_list, std::vector<int>& in_count_list, std::vector<int>& out_count_list) { void Pipeline::RunMOTStream(const cv::Mat img,
const int frame_id,
cv::Mat out_img,
std::vector<std::string>* records,
std::vector<int>* count_list,
std::vector<int>* in_count_list,
std::vector<int>* out_count_list) {
PaddleDetection::MOTResult result; PaddleDetection::MOTResult result;
std::vector<double> det_times(3); std::vector<double> det_times(3);
double times; double times;
...@@ -228,15 +248,16 @@ void Pipeline::RunMOTStream(const cv::Mat img, const int frame_id, cv::Mat& out_ ...@@ -228,15 +248,16 @@ void Pipeline::RunMOTStream(const cv::Mat img, const int frame_id, cv::Mat& out_
times = total_time / frame_id; times = total_time / frame_id;
LOG(INFO) << "frame_id: " << frame_id LOG(INFO) << "frame_id: " << frame_id
<< " predict time(s): "<< total_time / 1000; << " predict time(s): " << total_time / 1000;
out_img = PaddleDetection::VisualizeTrackResult( out_img = PaddleDetection::VisualizeTrackResult(
img, result, 1000./times, frame_id); img, result, 1000. / times, frame_id);
if (count_) { if (count_) {
// Count total number // Count total number
// Count in & out number // Count in & out number
PaddleDetection::FlowStatistic(result, frame_id, &count_list, &in_count_list, &out_count_list); PaddleDetection::FlowStatistic(
result, frame_id, count_list, in_count_list, out_count_list);
} }
PrintBenchmarkLog(det_times, frame_id); PrintBenchmarkLog(det_times, frame_id);
...@@ -245,23 +266,30 @@ void Pipeline::RunMOTStream(const cv::Mat img, const int frame_id, cv::Mat& out_ ...@@ -245,23 +266,30 @@ void Pipeline::RunMOTStream(const cv::Mat img, const int frame_id, cv::Mat& out_
} }
} }
void Pipeline::RunMTMCTStream(const std::vector<cv::Mat> imgs, std::vector<std::string>& records) { void Pipeline::RunMTMCTStream(const std::vector<cv::Mat> imgs,
std::vector<std::string>* records) {
throw "Not Implement!"; throw "Not Implement!";
} }
void Pipeline::PrintBenchmarkLog(std::vector<double> det_time, int img_num){ void Pipeline::PrintBenchmarkLog(const std::vector<double> det_time,
const int img_num) {
LOG(INFO) << "----------------------- Config info -----------------------"; LOG(INFO) << "----------------------- Config info -----------------------";
LOG(INFO) << "runtime_device: " << device_; LOG(INFO) << "runtime_device: " << device_;
LOG(INFO) << "ir_optim: " << "True"; LOG(INFO) << "ir_optim: "
LOG(INFO) << "enable_memory_optim: " << "True"; << "True";
LOG(INFO) << "enable_memory_optim: "
<< "True";
int has_trt = run_mode_.find("trt"); int has_trt = run_mode_.find("trt");
if (has_trt >= 0) { if (has_trt >= 0) {
LOG(INFO) << "enable_tensorrt: " << "True"; LOG(INFO) << "enable_tensorrt: "
<< "True";
std::string precision = run_mode_.substr(4, 8); std::string precision = run_mode_.substr(4, 8);
LOG(INFO) << "precision: " << precision; LOG(INFO) << "precision: " << precision;
} else { } else {
LOG(INFO) << "enable_tensorrt: " << "False"; LOG(INFO) << "enable_tensorrt: "
LOG(INFO) << "precision: " << "fp32"; << "False";
LOG(INFO) << "precision: "
<< "fp32";
} }
LOG(INFO) << "enable_mkldnn: " << (use_mkldnn_ ? "True" : "False"); LOG(INFO) << "enable_mkldnn: " << (use_mkldnn_ ? "True" : "False");
LOG(INFO) << "cpu_math_library_num_threads: " << cpu_threads_; LOG(INFO) << "cpu_math_library_num_threads: " << cpu_threads_;
...@@ -269,12 +297,10 @@ void Pipeline::PrintBenchmarkLog(std::vector<double> det_time, int img_num){ ...@@ -269,12 +297,10 @@ void Pipeline::PrintBenchmarkLog(std::vector<double> det_time, int img_num){
LOG(INFO) << "Total number of predicted data: " << img_num LOG(INFO) << "Total number of predicted data: " << img_num
<< " and total time spent(s): " << " and total time spent(s): "
<< std::accumulate(det_time.begin(), det_time.end(), 0.) / 1000; << std::accumulate(det_time.begin(), det_time.end(), 0.) / 1000;
img_num = std::max(1, img_num); int num = std::max(1, img_num);
LOG(INFO) << "preproce_time(ms): " << det_time[0] / img_num LOG(INFO) << "preproce_time(ms): " << det_time[0] / num
<< ", inference_time(ms): " << det_time[1] / img_num << ", inference_time(ms): " << det_time[1] / num
<< ", postprocess_time(ms): " << det_time[2] / img_num; << ", postprocess_time(ms): " << det_time[2] / num;
} }
} // namespace PaddleDetection
} // namespace PaddleDetection
...@@ -14,57 +14,60 @@ ...@@ -14,57 +14,60 @@
#include <sstream> #include <sstream>
// for setprecision // for setprecision
#include <iomanip>
#include <chrono> #include <chrono>
#include <iomanip>
#include "include/postprocess.h" #include "include/postprocess.h"
namespace PaddleDetection { namespace PaddleDetection {
cv::Scalar GetColor(int idx) { cv::Scalar GetColor(int idx) {
idx = idx * 3; idx = idx * 3;
cv::Scalar color = cv::Scalar((37 * idx) % 255, cv::Scalar color =
(17 * idx) % 255, cv::Scalar((37 * idx) % 255, (17 * idx) % 255, (29 * idx) % 255);
(29 * idx) % 255);
return color; return color;
} }
cv::Mat VisualizeTrackResult(const cv::Mat& img, cv::Mat VisualizeTrackResult(const cv::Mat& img,
const MOTResult& results, const MOTResult& results,
const float fps, const int frame_id) { const float fps,
const int frame_id) {
cv::Mat vis_img = img.clone(); cv::Mat vis_img = img.clone();
int im_h = img.rows; int im_h = img.rows;
int im_w = img.cols; int im_w = img.cols;
float text_scale = std::max(1, int(im_w / 1600.)); float text_scale = std::max(1, static_cast<int>(im_w / 1600.));
float text_thickness = 2.; float text_thickness = 2.;
float line_thickness = std::max(1, int(im_w / 500.)); float line_thickness = std::max(1, static_cast<int>(im_w / 500.));
std::ostringstream oss; std::ostringstream oss;
oss << std::setiosflags(std::ios::fixed) << std::setprecision(4); oss << std::setiosflags(std::ios::fixed) << std::setprecision(4);
oss << "frame: " << frame_id<<" "; oss << "frame: " << frame_id << " ";
oss << "fps: " << fps<<" "; oss << "fps: " << fps << " ";
oss << "num: " << results.size(); oss << "num: " << results.size();
std::string text = oss.str(); std::string text = oss.str();
cv::Point origin; cv::Point origin;
origin.x = 0; origin.x = 0;
origin.y = int(15 * text_scale); origin.y = static_cast<int>(15 * text_scale);
cv::putText( cv::putText(vis_img,
vis_img, text,
text, origin,
origin, cv::FONT_HERSHEY_PLAIN,
cv::FONT_HERSHEY_PLAIN, text_scale,
text_scale, (0, 0, 255), 2); (0, 0, 255),
2);
for (int i = 0; i < results.size(); ++i) { for (int i = 0; i < results.size(); ++i) {
const int obj_id = results[i].ids; const int obj_id = results[i].ids;
const float score = results[i].score; const float score = results[i].score;
cv::Scalar color = GetColor(obj_id); cv::Scalar color = GetColor(obj_id);
cv::Point pt1 = cv::Point(results[i].rects.left, results[i].rects.top); cv::Point pt1 = cv::Point(results[i].rects.left, results[i].rects.top);
cv::Point pt2 = cv::Point(results[i].rects.right, results[i].rects.bottom); cv::Point pt2 = cv::Point(results[i].rects.right, results[i].rects.bottom);
cv::Point id_pt = cv::Point(results[i].rects.left, results[i].rects.top + 10); cv::Point id_pt =
cv::Point score_pt = cv::Point(results[i].rects.left, results[i].rects.top - 10); cv::Point(results[i].rects.left, results[i].rects.top + 10);
cv::Point score_pt =
cv::Point(results[i].rects.left, results[i].rects.top - 10);
cv::rectangle(vis_img, pt1, pt2, color, line_thickness); cv::rectangle(vis_img, pt1, pt2, color, line_thickness);
std::ostringstream idoss; std::ostringstream idoss;
...@@ -92,19 +95,21 @@ cv::Mat VisualizeTrackResult(const cv::Mat& img, ...@@ -92,19 +95,21 @@ cv::Mat VisualizeTrackResult(const cv::Mat& img,
text_scale, text_scale,
cv::Scalar(0, 255, 255), cv::Scalar(0, 255, 255),
text_thickness); text_thickness);
} }
return vis_img; return vis_img;
} }
void FlowStatistic(const MOTResult& results, const int frame_id, void FlowStatistic(const MOTResult& results,
std::vector<int>* count_list, const int frame_id,
std::vector<int>* in_count_list, std::vector<int>* count_list,
std::vector<int>* in_count_list,
std::vector<int>* out_count_list) { std::vector<int>* out_count_list) {
throw "Not Implement"; throw "Not Implement";
} }
void SaveMOTResult(const MOTResult& results, const int frame_id, std::vector<std::string>& records) { void SaveMOTResult(const MOTResult& results,
const int frame_id,
std::vector<std::string>* records) {
// result format: frame_id, track_id, x1, y1, w, h // result format: frame_id, track_id, x1, y1, w, h
std::string record; std::string record;
for (int i = 0; i < results.size(); ++i) { for (int i = 0; i < results.size(); ++i) {
...@@ -122,12 +127,11 @@ void SaveMOTResult(const MOTResult& results, const int frame_id, std::vector<std ...@@ -122,12 +127,11 @@ void SaveMOTResult(const MOTResult& results, const int frame_id, std::vector<std
continue; continue;
} }
std::ostringstream os; std::ostringstream os;
os << frame_id << " " << ids << "" os << frame_id << " " << ids << "" << x1 << " " << y1 << " " << w << " "
<< x1 << " " << y1 << " " << h << "\n";
<< w << " " << h <<"\n";
record = os.str(); record = os.str();
records.push_back(record); records->push_back(record);
} }
} }
} // namespace PaddleDetection } // namespace PaddleDetection
...@@ -12,24 +12,20 @@ ...@@ -12,24 +12,20 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <vector>
#include <string> #include <string>
#include <thread> #include <thread>
#include <vector>
#include "include/preprocess_op.h" #include "include/preprocess_op.h"
namespace PaddleDetection { namespace PaddleDetection {
void InitInfo::Run(cv::Mat* im, ImageBlob* data) { void InitInfo::Run(cv::Mat* im, ImageBlob* data) {
data->im_shape_ = { data->im_shape_ = {static_cast<float>(im->rows),
static_cast<float>(im->rows), static_cast<float>(im->cols)};
static_cast<float>(im->cols)
};
data->scale_factor_ = {1., 1.}; data->scale_factor_ = {1., 1.};
data->in_net_shape_ = { data->in_net_shape_ = {static_cast<float>(im->rows),
static_cast<float>(im->rows), static_cast<float>(im->cols)};
static_cast<float>(im->cols)
};
} }
void NormalizeImage::Run(cv::Mat* im, ImageBlob* data) { void NormalizeImage::Run(cv::Mat* im, ImageBlob* data) {
...@@ -41,11 +37,11 @@ void NormalizeImage::Run(cv::Mat* im, ImageBlob* data) { ...@@ -41,11 +37,11 @@ void NormalizeImage::Run(cv::Mat* im, ImageBlob* data) {
for (int h = 0; h < im->rows; h++) { for (int h = 0; h < im->rows; h++) {
for (int w = 0; w < im->cols; w++) { for (int w = 0; w < im->cols; w++) {
im->at<cv::Vec3f>(h, w)[0] = im->at<cv::Vec3f>(h, w)[0] =
(im->at<cv::Vec3f>(h, w)[0] - mean_[0] ) / scale_[0]; (im->at<cv::Vec3f>(h, w)[0] - mean_[0]) / scale_[0];
im->at<cv::Vec3f>(h, w)[1] = im->at<cv::Vec3f>(h, w)[1] =
(im->at<cv::Vec3f>(h, w)[1] - mean_[1] ) / scale_[1]; (im->at<cv::Vec3f>(h, w)[1] - mean_[1]) / scale_[1];
im->at<cv::Vec3f>(h, w)[2] = im->at<cv::Vec3f>(h, w)[2] =
(im->at<cv::Vec3f>(h, w)[2] - mean_[2] ) / scale_[2]; (im->at<cv::Vec3f>(h, w)[2] - mean_[2]) / scale_[2];
} }
} }
} }
...@@ -64,27 +60,20 @@ void Permute::Run(cv::Mat* im, ImageBlob* data) { ...@@ -64,27 +60,20 @@ void Permute::Run(cv::Mat* im, ImageBlob* data) {
void Resize::Run(cv::Mat* im, ImageBlob* data) { void Resize::Run(cv::Mat* im, ImageBlob* data) {
auto resize_scale = GenerateScale(*im); auto resize_scale = GenerateScale(*im);
data->im_shape_ = { data->im_shape_ = {static_cast<float>(im->cols * resize_scale.first),
static_cast<float>(im->cols * resize_scale.first), static_cast<float>(im->rows * resize_scale.second)};
static_cast<float>(im->rows * resize_scale.second) data->in_net_shape_ = {static_cast<float>(im->cols * resize_scale.first),
}; static_cast<float>(im->rows * resize_scale.second)};
data->in_net_shape_ = {
static_cast<float>(im->cols * resize_scale.first),
static_cast<float>(im->rows * resize_scale.second)
};
cv::resize( cv::resize(
*im, *im, cv::Size(), resize_scale.first, resize_scale.second, interp_); *im, *im, cv::Size(), resize_scale.first, resize_scale.second, interp_);
data->im_shape_ = { data->im_shape_ = {
static_cast<float>(im->rows), static_cast<float>(im->rows), static_cast<float>(im->cols),
static_cast<float>(im->cols),
}; };
data->scale_factor_ = { data->scale_factor_ = {
resize_scale.second, resize_scale.second, resize_scale.first,
resize_scale.first,
}; };
} }
std::pair<float, float> Resize::GenerateScale(const cv::Mat& im) { std::pair<float, float> Resize::GenerateScale(const cv::Mat& im) {
std::pair<float, float> resize_scale; std::pair<float, float> resize_scale;
int origin_w = im.cols; int origin_w = im.cols;
...@@ -93,8 +82,10 @@ std::pair<float, float> Resize::GenerateScale(const cv::Mat& im) { ...@@ -93,8 +82,10 @@ std::pair<float, float> Resize::GenerateScale(const cv::Mat& im) {
if (keep_ratio_) { if (keep_ratio_) {
int im_size_max = std::max(origin_w, origin_h); int im_size_max = std::max(origin_w, origin_h);
int im_size_min = std::min(origin_w, origin_h); int im_size_min = std::min(origin_w, origin_h);
int target_size_max = *std::max_element(target_size_.begin(), target_size_.end()); int target_size_max =
int target_size_min = *std::min_element(target_size_.begin(), target_size_.end()); *std::max_element(target_size_.begin(), target_size_.end());
int target_size_min =
*std::min_element(target_size_.begin(), target_size_.end());
float scale_min = float scale_min =
static_cast<float>(target_size_min) / static_cast<float>(im_size_min); static_cast<float>(target_size_min) / static_cast<float>(im_size_min);
float scale_max = float scale_max =
...@@ -114,46 +105,38 @@ void LetterBoxResize::Run(cv::Mat* im, ImageBlob* data) { ...@@ -114,46 +105,38 @@ void LetterBoxResize::Run(cv::Mat* im, ImageBlob* data) {
float resize_scale = GenerateScale(*im); float resize_scale = GenerateScale(*im);
int new_shape_w = std::round(im->cols * resize_scale); int new_shape_w = std::round(im->cols * resize_scale);
int new_shape_h = std::round(im->rows * resize_scale); int new_shape_h = std::round(im->rows * resize_scale);
data->im_shape_ = { data->im_shape_ = {static_cast<float>(new_shape_h),
static_cast<float>(new_shape_h), static_cast<float>(new_shape_w)};
static_cast<float>(new_shape_w)
};
float padw = (target_size_[1] - new_shape_w) / 2.; float padw = (target_size_[1] - new_shape_w) / 2.;
float padh = (target_size_[0] - new_shape_h) / 2.; float padh = (target_size_[0] - new_shape_h) / 2.;
int top = std::round(padh - 0.1); int top = std::round(padh - 0.1);
int bottom = std::round(padh + 0.1); int bottom = std::round(padh + 0.1);
int left = std::round(padw - 0.1); int left = std::round(padw - 0.1);
int right = std::round(padw + 0.1); int right = std::round(padw + 0.1);
cv::resize( cv::resize(
*im, *im, cv::Size(new_shape_w, new_shape_h), 0, 0, cv::INTER_AREA); *im, *im, cv::Size(new_shape_w, new_shape_h), 0, 0, cv::INTER_AREA);
data->in_net_shape_ = { data->in_net_shape_ = {
static_cast<float>(im->rows), static_cast<float>(im->rows), static_cast<float>(im->cols),
static_cast<float>(im->cols),
}; };
cv::copyMakeBorder( cv::copyMakeBorder(*im,
*im, *im,
*im, top,
top, bottom,
bottom, left,
left, right,
right, cv::BORDER_CONSTANT,
cv::BORDER_CONSTANT, cv::Scalar(127.5));
cv::Scalar(127.5));
data->in_net_shape_ = { data->in_net_shape_ = {
static_cast<float>(im->rows), static_cast<float>(im->rows), static_cast<float>(im->cols),
static_cast<float>(im->cols),
}; };
data->scale_factor_ = { data->scale_factor_ = {
resize_scale, resize_scale, resize_scale,
resize_scale,
}; };
} }
float LetterBoxResize::GenerateScale(const cv::Mat& im) { float LetterBoxResize::GenerateScale(const cv::Mat& im) {
...@@ -165,7 +148,7 @@ float LetterBoxResize::GenerateScale(const cv::Mat& im) { ...@@ -165,7 +148,7 @@ float LetterBoxResize::GenerateScale(const cv::Mat& im) {
float ratio_h = static_cast<float>(target_h) / static_cast<float>(origin_h); float ratio_h = static_cast<float>(target_h) / static_cast<float>(origin_h);
float ratio_w = static_cast<float>(target_w) / static_cast<float>(origin_w); float ratio_w = static_cast<float>(target_w) / static_cast<float>(origin_w);
float resize_scale = std::min(ratio_h, ratio_w); float resize_scale = std::min(ratio_h, ratio_w);
return resize_scale; return resize_scale;
} }
...@@ -179,24 +162,19 @@ void PadStride::Run(cv::Mat* im, ImageBlob* data) { ...@@ -179,24 +162,19 @@ void PadStride::Run(cv::Mat* im, ImageBlob* data) {
int nh = (rh / stride_) * stride_ + (rh % stride_ != 0) * stride_; int nh = (rh / stride_) * stride_ + (rh % stride_ != 0) * stride_;
int nw = (rw / stride_) * stride_ + (rw % stride_ != 0) * stride_; int nw = (rw / stride_) * stride_ + (rw % stride_ != 0) * stride_;
cv::copyMakeBorder( cv::copyMakeBorder(
*im, *im, *im, 0, nh - rh, 0, nw - rw, cv::BORDER_CONSTANT, cv::Scalar(0));
*im,
0,
nh - rh,
0,
nw - rw,
cv::BORDER_CONSTANT,
cv::Scalar(0));
data->in_net_shape_ = { data->in_net_shape_ = {
static_cast<float>(im->rows), static_cast<float>(im->rows), static_cast<float>(im->cols),
static_cast<float>(im->cols),
}; };
} }
// Preprocessor op running order // Preprocessor op running order
const std::vector<std::string> Preprocessor::RUN_ORDER = { const std::vector<std::string> Preprocessor::RUN_ORDER = {"InitInfo",
"InitInfo", "Resize", "LetterBoxResize", "NormalizeImage", "PadStride", "Permute" "Resize",
}; "LetterBoxResize",
"NormalizeImage",
"PadStride",
"Permute"};
void Preprocessor::Run(cv::Mat* im, ImageBlob* data) { void Preprocessor::Run(cv::Mat* im, ImageBlob* data) {
for (const auto& name : RUN_ORDER) { for (const auto& name : RUN_ORDER) {
......
...@@ -13,12 +13,11 @@ ...@@ -13,12 +13,11 @@
// limitations under the License. // limitations under the License.
#include <sstream> #include <sstream>
// for setprecision // for setprecision
#include <iomanip>
#include <chrono> #include <chrono>
#include <iomanip>
#include "include/sde_predictor.h" #include "include/sde_predictor.h"
using namespace paddle_infer; // NOLINT
using namespace paddle_infer;
namespace PaddleDetection { namespace PaddleDetection {
...@@ -29,21 +28,18 @@ void SDEPredictor::LoadModel(const std::string& det_model_dir, ...@@ -29,21 +28,18 @@ void SDEPredictor::LoadModel(const std::string& det_model_dir,
throw "Not Implement"; throw "Not Implement";
} }
void SDEPredictor::Preprocess(const cv::Mat& ori_im) { throw "Not Implement"; }
void SDEPredictor::Preprocess(const cv::Mat& ori_im) { void SDEPredictor::Postprocess(const cv::Mat dets,
throw "Not Implement"; const cv::Mat emb,
} MOTResult* result) {
void SDEPredictor::Postprocess(
const cv::Mat dets, const cv::Mat emb,
MOTResult* result) {
throw "Not Implement"; throw "Not Implement";
} }
void SDEPredictor::Predict(const std::vector<cv::Mat> imgs, void SDEPredictor::Predict(const std::vector<cv::Mat> imgs,
const double threshold, const double threshold,
MOTResult* result, MOTResult* result,
std::vector<double>* times) { std::vector<double>* times) {
throw "Not Implement"; throw "Not Implement";
} }
......
...@@ -15,319 +15,290 @@ ...@@ -15,319 +15,290 @@
// The code is based on: // The code is based on:
// https://github.com/CnybTseng/JDE/blob/master/platforms/common/jdetracker.cpp // https://github.com/CnybTseng/JDE/blob/master/platforms/common/jdetracker.cpp
// Ths copyright of CnybTseng/JDE is as follows: // Ths copyright of CnybTseng/JDE is as follows:
// MIT License // MIT License
#include <map>
#include <stdio.h>
#include <limits.h> #include <limits.h>
#include <stdio.h>
#include <algorithm> #include <algorithm>
#include <map>
#include "include/lapjv.h" #include "include/lapjv.h"
#include "include/tracker.h" #include "include/tracker.h"
#define mat2vec4f(m) cv::Vec4f(*m.ptr<float>(0,0), *m.ptr<float>(0,1), *m.ptr<float>(0,2), *m.ptr<float>(0,3)) #define mat2vec4f(m) \
cv::Vec4f(*m.ptr<float>(0, 0), \
*m.ptr<float>(0, 1), \
*m.ptr<float>(0, 2), \
*m.ptr<float>(0, 3))
namespace PaddleDetection { namespace PaddleDetection {
static std::map<int, float> chi2inv95 = { static std::map<int, float> chi2inv95 = {{1, 3.841459f},
{1, 3.841459f}, {2, 5.991465f},
{2, 5.991465f}, {3, 7.814728f},
{3, 7.814728f}, {4, 9.487729f},
{4, 9.487729f}, {5, 11.070498f},
{5, 11.070498f}, {6, 12.591587f},
{6, 12.591587f}, {7, 14.067140f},
{7, 14.067140f}, {8, 15.507313f},
{8, 15.507313f}, {9, 16.918978f}};
{9, 16.918978f}
};
JDETracker *JDETracker::me = new JDETracker; JDETracker *JDETracker::me = new JDETracker;
JDETracker *JDETracker::instance(void) JDETracker *JDETracker::instance(void) { return me; }
{
return me;
}
JDETracker::JDETracker(void) : timestamp(0), max_lost_time(30), lambda(0.98f), det_thresh(0.3f) JDETracker::JDETracker(void)
{ : timestamp(0), max_lost_time(30), lambda(0.98f), det_thresh(0.3f) {}
}
bool JDETracker::update(const cv::Mat &dets, const cv::Mat &emb, std::vector<Track> &tracks) bool JDETracker::update(const cv::Mat &dets,
{ const cv::Mat &emb,
++timestamp; std::vector<Track> *tracks) {
TrajectoryPool candidates(dets.rows); ++timestamp;
for (int i = 0; i < dets.rows; ++i) TrajectoryPool candidates(dets.rows);
{ for (int i = 0; i < dets.rows; ++i) {
float score = *dets.ptr<float>(i, 4); float score = *dets.ptr<float>(i, 4);
const cv::Mat &ltrb_ = dets(cv::Rect(0, i, 4, 1)); const cv::Mat &ltrb_ = dets(cv::Rect(0, i, 4, 1));
cv::Vec4f ltrb = mat2vec4f(ltrb_); cv::Vec4f ltrb = mat2vec4f(ltrb_);
const cv::Mat &embedding = emb(cv::Rect(0, i, emb.cols, 1)); const cv::Mat &embedding = emb(cv::Rect(0, i, emb.cols, 1));
candidates[i] = Trajectory(ltrb, score, embedding); candidates[i] = Trajectory(ltrb, score, embedding);
} }
TrajectoryPtrPool tracked_trajectories;
TrajectoryPtrPool tracked_trajectories; TrajectoryPtrPool unconfirmed_trajectories;
TrajectoryPtrPool unconfirmed_trajectories; for (size_t i = 0; i < this->tracked_trajectories.size(); ++i) {
for (size_t i = 0; i < this->tracked_trajectories.size(); ++i) if (this->tracked_trajectories[i].is_activated)
{ tracked_trajectories.push_back(&this->tracked_trajectories[i]);
if (this->tracked_trajectories[i].is_activated) else
tracked_trajectories.push_back(&this->tracked_trajectories[i]); unconfirmed_trajectories.push_back(&this->tracked_trajectories[i]);
else }
unconfirmed_trajectories.push_back(&this->tracked_trajectories[i]);
}
TrajectoryPtrPool trajectory_pool = tracked_trajectories + this->lost_trajectories;
for (size_t i = 0; i < trajectory_pool.size(); ++i)
trajectory_pool[i]->predict();
Match matches;
std::vector<int> mismatch_row;
std::vector<int> mismatch_col;
cv::Mat cost = motion_distance(trajectory_pool, candidates);
linear_assignment(cost, 0.7f, matches, mismatch_row, mismatch_col);
MatchIterator miter;
TrajectoryPtrPool activated_trajectories;
TrajectoryPtrPool retrieved_trajectories;
for (miter = matches.begin(); miter != matches.end(); miter++)
{
Trajectory *pt = trajectory_pool[miter->first];
Trajectory &ct = candidates[miter->second];
if (pt->state == Tracked)
{
pt->update(ct, timestamp);
activated_trajectories.push_back(pt);
}
else
{
pt->reactivate(ct, timestamp);
retrieved_trajectories.push_back(pt);
}
}
TrajectoryPtrPool next_candidates(mismatch_col.size());
for (size_t i = 0; i < mismatch_col.size(); ++i)
next_candidates[i] = &candidates[mismatch_col[i]];
TrajectoryPtrPool next_trajectory_pool;
for (size_t i = 0; i < mismatch_row.size(); ++i)
{
int j = mismatch_row[i];
if (trajectory_pool[j]->state == Tracked)
next_trajectory_pool.push_back(trajectory_pool[j]);
}
cost = iou_distance(next_trajectory_pool, next_candidates);
linear_assignment(cost, 0.5f, matches, mismatch_row, mismatch_col);
for (miter = matches.begin(); miter != matches.end(); miter++)
{
Trajectory *pt = next_trajectory_pool[miter->first];
Trajectory *ct = next_candidates[miter->second];
if (pt->state == Tracked)
{
pt->update(*ct, timestamp);
activated_trajectories.push_back(pt);
}
else
{
pt->reactivate(*ct, timestamp);
retrieved_trajectories.push_back(pt);
}
}
TrajectoryPtrPool lost_trajectories;
for (size_t i = 0; i < mismatch_row.size(); ++i)
{
Trajectory *pt = next_trajectory_pool[mismatch_row[i]];
if (pt->state != Lost)
{
pt->mark_lost();
lost_trajectories.push_back(pt);
}
}
TrajectoryPtrPool nnext_candidates(mismatch_col.size());
for (size_t i = 0; i < mismatch_col.size(); ++i)
nnext_candidates[i] = next_candidates[mismatch_col[i]];
cost = iou_distance(unconfirmed_trajectories, nnext_candidates);
linear_assignment(cost, 0.7f, matches, mismatch_row, mismatch_col);
for (miter = matches.begin(); miter != matches.end(); miter++)
{
unconfirmed_trajectories[miter->first]->update(*nnext_candidates[miter->second], timestamp);
activated_trajectories.push_back(unconfirmed_trajectories[miter->first]);
}
TrajectoryPtrPool removed_trajectories;
for (size_t i = 0; i < mismatch_row.size(); ++i) TrajectoryPtrPool trajectory_pool =
{ tracked_trajectories + &(this->lost_trajectories);
unconfirmed_trajectories[mismatch_row[i]]->mark_removed();
removed_trajectories.push_back(unconfirmed_trajectories[mismatch_row[i]]); for (size_t i = 0; i < trajectory_pool.size(); ++i)
trajectory_pool[i]->predict();
Match matches;
std::vector<int> mismatch_row;
std::vector<int> mismatch_col;
cv::Mat cost = motion_distance(trajectory_pool, candidates);
linear_assignment(cost, 0.7f, &matches, &mismatch_row, &mismatch_col);
MatchIterator miter;
TrajectoryPtrPool activated_trajectories;
TrajectoryPtrPool retrieved_trajectories;
for (miter = matches.begin(); miter != matches.end(); miter++) {
Trajectory *pt = trajectory_pool[miter->first];
Trajectory &ct = candidates[miter->second];
if (pt->state == Tracked) {
pt->update(&ct, timestamp);
activated_trajectories.push_back(pt);
} else {
pt->reactivate(&ct, timestamp);
retrieved_trajectories.push_back(pt);
} }
}
for (size_t i = 0; i < mismatch_col.size(); ++i)
{ TrajectoryPtrPool next_candidates(mismatch_col.size());
if (nnext_candidates[mismatch_col[i]]->score < det_thresh) continue; for (size_t i = 0; i < mismatch_col.size(); ++i)
nnext_candidates[mismatch_col[i]]->activate(timestamp); next_candidates[i] = &candidates[mismatch_col[i]];
activated_trajectories.push_back(nnext_candidates[mismatch_col[i]]);
TrajectoryPtrPool next_trajectory_pool;
for (size_t i = 0; i < mismatch_row.size(); ++i) {
int j = mismatch_row[i];
if (trajectory_pool[j]->state == Tracked)
next_trajectory_pool.push_back(trajectory_pool[j]);
}
cost = iou_distance(next_trajectory_pool, next_candidates);
linear_assignment(cost, 0.5f, &matches, &mismatch_row, &mismatch_col);
for (miter = matches.begin(); miter != matches.end(); miter++) {
Trajectory *pt = next_trajectory_pool[miter->first];
Trajectory *ct = next_candidates[miter->second];
if (pt->state == Tracked) {
pt->update(ct, timestamp);
activated_trajectories.push_back(pt);
} else {
pt->reactivate(ct, timestamp);
retrieved_trajectories.push_back(pt);
} }
}
for (size_t i = 0; i < this->lost_trajectories.size(); ++i)
{ TrajectoryPtrPool lost_trajectories;
Trajectory &lt = this->lost_trajectories[i]; for (size_t i = 0; i < mismatch_row.size(); ++i) {
if (timestamp - lt.timestamp > max_lost_time) Trajectory *pt = next_trajectory_pool[mismatch_row[i]];
{ if (pt->state != Lost) {
lt.mark_removed(); pt->mark_lost();
removed_trajectories.push_back(&lt); lost_trajectories.push_back(pt);
}
} }
}
TrajectoryPoolIterator piter;
for (piter = this->tracked_trajectories.begin(); piter != this->tracked_trajectories.end(); ) TrajectoryPtrPool nnext_candidates(mismatch_col.size());
{ for (size_t i = 0; i < mismatch_col.size(); ++i)
if (piter->state != Tracked) nnext_candidates[i] = next_candidates[mismatch_col[i]];
piter = this->tracked_trajectories.erase(piter); cost = iou_distance(unconfirmed_trajectories, nnext_candidates);
else linear_assignment(cost, 0.7f, &matches, &mismatch_row, &mismatch_col);
++piter;
for (miter = matches.begin(); miter != matches.end(); miter++) {
unconfirmed_trajectories[miter->first]->update(
nnext_candidates[miter->second], timestamp);
activated_trajectories.push_back(unconfirmed_trajectories[miter->first]);
}
TrajectoryPtrPool removed_trajectories;
for (size_t i = 0; i < mismatch_row.size(); ++i) {
unconfirmed_trajectories[mismatch_row[i]]->mark_removed();
removed_trajectories.push_back(unconfirmed_trajectories[mismatch_row[i]]);
}
for (size_t i = 0; i < mismatch_col.size(); ++i) {
if (nnext_candidates[mismatch_col[i]]->score < det_thresh) continue;
nnext_candidates[mismatch_col[i]]->activate(timestamp);
activated_trajectories.push_back(nnext_candidates[mismatch_col[i]]);
}
for (size_t i = 0; i < this->lost_trajectories.size(); ++i) {
Trajectory &lt = this->lost_trajectories[i];
if (timestamp - lt.timestamp > max_lost_time) {
lt.mark_removed();
removed_trajectories.push_back(&lt);
} }
}
this->tracked_trajectories += activated_trajectories;
this->tracked_trajectories += retrieved_trajectories; TrajectoryPoolIterator piter;
for (piter = this->tracked_trajectories.begin();
this->lost_trajectories -= this->tracked_trajectories; piter != this->tracked_trajectories.end();) {
this->lost_trajectories += lost_trajectories; if (piter->state != Tracked)
this->lost_trajectories -= this->removed_trajectories; piter = this->tracked_trajectories.erase(piter);
this->removed_trajectories += removed_trajectories; else
remove_duplicate_trajectory(this->tracked_trajectories, this->lost_trajectories); ++piter;
}
tracks.clear();
for (size_t i = 0; i < this->tracked_trajectories.size(); ++i) this->tracked_trajectories += activated_trajectories;
{ this->tracked_trajectories += retrieved_trajectories;
if (this->tracked_trajectories[i].is_activated)
{ this->lost_trajectories -= this->tracked_trajectories;
Track track = { this->lost_trajectories += lost_trajectories;
.id = this->tracked_trajectories[i].id, this->lost_trajectories -= this->removed_trajectories;
.score = this->tracked_trajectories[i].score, this->removed_trajectories += removed_trajectories;
.ltrb = this->tracked_trajectories[i].ltrb}; remove_duplicate_trajectory(&this->tracked_trajectories,
tracks.push_back(track); &this->lost_trajectories);
}
tracks->clear();
for (size_t i = 0; i < this->tracked_trajectories.size(); ++i) {
if (this->tracked_trajectories[i].is_activated) {
Track track = {.id = this->tracked_trajectories[i].id,
.score = this->tracked_trajectories[i].score,
.ltrb = this->tracked_trajectories[i].ltrb};
tracks->push_back(track);
} }
return 0; }
return 0;
} }
cv::Mat JDETracker::motion_distance(const TrajectoryPtrPool &a,
const TrajectoryPool &b) {
if (0 == a.size() || 0 == b.size())
return cv::Mat(a.size(), b.size(), CV_32F);
cv::Mat edists = embedding_distance(a, b);
cv::Mat mdists = mahalanobis_distance(a, b);
cv::Mat fdists = lambda * edists + (1 - lambda) * mdists;
cv::Mat JDETracker::motion_distance(const TrajectoryPtrPool &a, const TrajectoryPool &b) const float gate_thresh = chi2inv95[4];
{ for (int i = 0; i < fdists.rows; ++i) {
if (0 == a.size() || 0 == b.size()) for (int j = 0; j < fdists.cols; ++j) {
return cv::Mat(a.size(), b.size(), CV_32F); if (*mdists.ptr<float>(i, j) > gate_thresh)
*fdists.ptr<float>(i, j) = FLT_MAX;
cv::Mat edists = embedding_distance(a, b);
cv::Mat mdists = mahalanobis_distance(a, b);
cv::Mat fdists = lambda * edists + (1 - lambda) * mdists;
const float gate_thresh = chi2inv95[4];
for (int i = 0; i < fdists.rows; ++i)
{
for (int j = 0; j < fdists.cols; ++j)
{
if (*mdists.ptr<float>(i, j) > gate_thresh)
*fdists.ptr<float>(i, j) = FLT_MAX;
}
} }
}
return fdists;
return fdists;
} }
void JDETracker::linear_assignment(const cv::Mat &cost, float cost_limit, Match &matches, void JDETracker::linear_assignment(const cv::Mat &cost,
std::vector<int> &mismatch_row, std::vector<int> &mismatch_col) float cost_limit,
{ Match *matches,
matches.clear(); std::vector<int> *mismatch_row,
mismatch_row.clear(); std::vector<int> *mismatch_col) {
mismatch_col.clear(); matches->clear();
if (cost.empty()) mismatch_row->clear();
{ mismatch_col->clear();
for (int i = 0; i < cost.rows; ++i) if (cost.empty()) {
mismatch_row.push_back(i); for (int i = 0; i < cost.rows; ++i) mismatch_row->push_back(i);
for (int i = 0; i < cost.cols; ++i) for (int i = 0; i < cost.cols; ++i) mismatch_col->push_back(i);
mismatch_col.push_back(i);
return;
}
float opt = 0;
cv::Mat x(cost.rows, 1, CV_32S);
cv::Mat y(cost.cols, 1, CV_32S);
lapjv_internal(cost, true, cost_limit,
(int *)x.data, (int *)y.data);
for (int i = 0; i < x.rows; ++i)
{
int j = *x.ptr<int>(i);
if (j >= 0)
matches.insert({i, j});
else
mismatch_row.push_back(i);
}
for (int i = 0; i < y.rows; ++i)
{
int j = *y.ptr<int>(i);
if (j < 0)
mismatch_col.push_back(i);
}
return; return;
}
float opt = 0;
cv::Mat x(cost.rows, 1, CV_32S);
cv::Mat y(cost.cols, 1, CV_32S);
lapjv_internal(cost,
true,
cost_limit,
reinterpret_cast<int *>(x.data),
reinterpret_cast<int *>(y.data));
for (int i = 0; i < x.rows; ++i) {
int j = *x.ptr<int>(i);
if (j >= 0)
matches->insert({i, j});
else
mismatch_row->push_back(i);
}
for (int i = 0; i < y.rows; ++i) {
int j = *y.ptr<int>(i);
if (j < 0) mismatch_col->push_back(i);
}
return;
} }
void JDETracker::remove_duplicate_trajectory(TrajectoryPool &a, TrajectoryPool &b, float iou_thresh) void JDETracker::remove_duplicate_trajectory(TrajectoryPool *a,
{ TrajectoryPool *b,
if (0 == a.size() || 0 == b.size()) float iou_thresh) {
return; if (a->size() == 0 || b->size() == 0) return;
cv::Mat dist = iou_distance(a, b); cv::Mat dist = iou_distance(*a, *b);
cv::Mat mask = dist < iou_thresh; cv::Mat mask = dist < iou_thresh;
std::vector<cv::Point> idx; std::vector<cv::Point> idx;
cv::findNonZero(mask, idx); cv::findNonZero(mask, idx);
std::vector<int> da; std::vector<int> da;
std::vector<int> db; std::vector<int> db;
for (size_t i = 0; i < idx.size(); ++i) for (size_t i = 0; i < idx.size(); ++i) {
{ int ta = (*a)[idx[i].y].timestamp - (*a)[idx[i].y].starttime;
int ta = a[idx[i].y].timestamp - a[idx[i].y].starttime; int tb = (*b)[idx[i].x].timestamp - (*b)[idx[i].x].starttime;
int tb = b[idx[i].x].timestamp - b[idx[i].x].starttime; if (ta > tb)
if (ta > tb) db.push_back(idx[i].x);
db.push_back(idx[i].x); else
else da.push_back(idx[i].y);
da.push_back(idx[i].y); }
}
int id = 0;
int id = 0; TrajectoryPoolIterator piter;
TrajectoryPoolIterator piter; for (piter = a->begin(); piter != a->end();) {
for (piter = a.begin(); piter != a.end(); ) std::vector<int>::iterator iter = find(da.begin(), da.end(), id++);
{ if (iter != da.end())
std::vector<int>::iterator iter = find(da.begin(), da.end(), id++); piter = a->erase(piter);
if (iter != da.end()) else
piter = a.erase(piter); ++piter;
else }
++piter;
} id = 0;
for (piter = b->begin(); piter != b->end();) {
id = 0; std::vector<int>::iterator iter = find(db.begin(), db.end(), id++);
for (piter = b.begin(); piter != b.end(); ) if (iter != db.end())
{ piter = b->erase(piter);
std::vector<int>::iterator iter = find(db.begin(), db.end(), id++); else
if (iter != db.end()) ++piter;
piter = b.erase(piter); }
else
++piter;
}
} }
} // namespace PaddleDetection } // namespace PaddleDetection
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册