未验证 提交 8902c4f8 编写于 作者: F FlyingQianMM 提交者: GitHub

[MOT] add c++ implementation for flow_statistics (#4510)

* add implementment for FlowStatics

* rename count to entrance_count; rename count_set to id_set

* add a todo for entrance line setting

* rename count to do_entrance_counting

* convert print_save_file to the origin line
上级 a86bf8b9
...@@ -48,11 +48,12 @@ class Pipeline { ...@@ -48,11 +48,12 @@ class Pipeline {
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 do_entrance_counting = 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,
const int secs_interval = 10) {
std::vector<std::string> input; std::vector<std::string> input;
this->input_ = input; this->input_ = input;
this->device_ = device; this->device_ = device;
...@@ -63,7 +64,8 @@ class Pipeline { ...@@ -63,7 +64,8 @@ class Pipeline {
this->use_mkldnn_ = use_mkldnn; this->use_mkldnn_ = use_mkldnn;
this->cpu_threads_ = cpu_threads; this->cpu_threads_ = cpu_threads;
this->trt_calib_mode_ = trt_calib_mode; this->trt_calib_mode_ = trt_calib_mode;
this->count_ = count; this->do_entrance_counting_ = do_entrance_counting;
this->secs_interval_ = secs_interval_;
this->save_result_ = save_result; this->save_result_ = save_result;
SelectModel(scene, tiny_obj, is_mtmct); SelectModel(scene, tiny_obj, is_mtmct);
InitPredictor(); InitPredictor();
...@@ -81,11 +83,16 @@ class Pipeline { ...@@ -81,11 +83,16 @@ class Pipeline {
// Run pipeline in stream // Run pipeline in stream
void RunMOTStream(const cv::Mat img, void RunMOTStream(const cv::Mat img,
const int frame_id, const int frame_id,
const int video_fps,
const Rect entrance,
cv::Mat out_img, cv::Mat out_img,
std::vector<std::string>* records, std::vector<std::string>* records,
std::vector<int>* count_list, std::set<int>* count_set,
std::set<int>* interval_count_set,
std::vector<int>* in_count_list, std::vector<int>* in_count_list,
std::vector<int>* out_count_list); std::vector<int>* out_count_list,
std::map<int, std::vector<float>>* prev_center,
std::vector<std::string>* flow_records);
void RunMTMCTStream(const std::vector<cv::Mat> imgs, void RunMTMCTStream(const std::vector<cv::Mat> imgs,
std::vector<std::string>* records); std::vector<std::string>* records);
...@@ -114,8 +121,9 @@ class Pipeline { ...@@ -114,8 +121,9 @@ class Pipeline {
bool use_mkldnn_ = false; bool use_mkldnn_ = false;
int cpu_threads_ = 1; int cpu_threads_ = 1;
bool trt_calib_mode_ = false; bool trt_calib_mode_ = false;
bool count_ = false; bool do_entrance_counting_ = false;
bool save_result_ = false; bool save_result_ = false;
int secs_interval_ = 10;
}; };
} // namespace PaddleDetection } // namespace PaddleDetection
......
...@@ -14,11 +14,14 @@ ...@@ -14,11 +14,14 @@
#pragma once #pragma once
#include <glog/logging.h>
#include <ctime> #include <ctime>
#include <memory> #include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <set>
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp> #include <opencv2/highgui/highgui.hpp>
...@@ -40,9 +43,17 @@ cv::Mat VisualizeTrackResult(const cv::Mat& img, ...@@ -40,9 +43,17 @@ cv::Mat VisualizeTrackResult(const cv::Mat& img,
// Pedestrian/Vehicle Counting // Pedestrian/Vehicle Counting
void FlowStatistic(const MOTResult& results, void FlowStatistic(const MOTResult& results,
const int frame_id, const int frame_id,
std::vector<int>* count_list, const int secs_interval,
std::vector<int>* in_count_list, const bool do_entrance_counting,
std::vector<int>* out_count_list); const int video_fps,
const Rect entrance,
std::set<int>* id_set,
std::set<int>* interval_id_set,
std::vector<int>* in_id_list,
std::vector<int>* out_id_list,
std::map<int, std::vector<float>>* prev_center,
std::vector<std::string>* records);
// Save Tracking Results // Save Tracking Results
void SaveMOTResult(const MOTResult& results, void SaveMOTResult(const MOTResult& results,
......
...@@ -54,7 +54,10 @@ DEFINE_bool(trt_calib_mode, ...@@ -54,7 +54,10 @@ DEFINE_bool(trt_calib_mode,
"If the model is produced by TRT offline quantitative calibration, " "If the model is produced by TRT offline quantitative calibration, "
"trt_calib_mode need to set True"); "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(do_entrance_counting, false,
"Whether counting the numbers of identifiers entering "
"or getting out from the entrance.");
DEFINE_int32(secs_interval, 10, "The seconds interval to count after tracking");
DEFINE_bool(save_result, false, "Whether saving result after tracking"); DEFINE_bool(save_result, false, "Whether saving result after tracking");
DEFINE_string( DEFINE_string(
scene, scene,
...@@ -140,11 +143,12 @@ int main(int argc, char** argv) { ...@@ -140,11 +143,12 @@ int main(int argc, char** argv) {
FLAGS_use_mkldnn, FLAGS_use_mkldnn,
FLAGS_cpu_threads, FLAGS_cpu_threads,
FLAGS_trt_calib_mode, FLAGS_trt_calib_mode,
FLAGS_count, FLAGS_do_entrance_counting,
FLAGS_save_result, FLAGS_save_result,
FLAGS_scene, FLAGS_scene,
FLAGS_tiny_obj, FLAGS_tiny_obj,
FLAGS_is_mtmct); FLAGS_is_mtmct,
FLAGS_secs_interval);
pipeline.SetInput(FLAGS_video_file); pipeline.SetInput(FLAGS_video_file);
if (!FLAGS_video_other_file.empty()) { if (!FLAGS_video_other_file.empty()) {
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include "include/pipeline.h" #include "include/pipeline.h"
#include "include/postprocess.h" #include "include/postprocess.h"
#include "include/predictor.h" #include "include/predictor.h"
...@@ -159,9 +160,14 @@ void Pipeline::PredictMOT(const std::string& video_path) { ...@@ -159,9 +160,14 @@ void Pipeline::PredictMOT(const std::string& video_path) {
PaddleDetection::MOTResult result; PaddleDetection::MOTResult result;
std::vector<double> det_times(3); std::vector<double> det_times(3);
std::vector<int> count_list; std::set<int> id_set;
std::vector<int> in_count_list; std::set<int> interval_id_set;
std::vector<int> out_count_list; std::vector<int> in_id_list;
std::vector<int> out_id_list;
std::map<int, std::vector<float>> prev_center;
Rect entrance = {0, static_cast<float>(video_height) / 2,
static_cast<float>(video_width),
static_cast<float>(video_height) / 2};
double times; double times;
double total_time; double total_time;
// Capture all frames and do inference // Capture all frames and do inference
...@@ -169,6 +175,7 @@ void Pipeline::PredictMOT(const std::string& video_path) { ...@@ -169,6 +175,7 @@ void Pipeline::PredictMOT(const std::string& video_path) {
int frame_id = 0; int frame_id = 0;
std::vector<std::string> records; std::vector<std::string> records;
std::vector<std::string> flow_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");
LOG(INFO) << "------------------- Predict info ------------------------"; LOG(INFO) << "------------------- Predict info ------------------------";
...@@ -188,13 +195,13 @@ void Pipeline::PredictMOT(const std::string& video_path) { ...@@ -188,13 +195,13 @@ void Pipeline::PredictMOT(const std::string& video_path) {
cv::Mat out_img = PaddleDetection::VisualizeTrackResult( cv::Mat out_img = PaddleDetection::VisualizeTrackResult(
frame, result, 1000. / times, frame_id); frame, result, 1000. / times, frame_id);
// TODO: the entrance line can be set by users
PaddleDetection::FlowStatistic(
result, frame_id, secs_interval_, do_entrance_counting_, video_fps, entrance,
&id_set, &interval_id_set, &in_id_list, &out_id_list,
&prev_center, &flow_records);
if (count_) {
// Count total number
// Count in & out number
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);
} }
...@@ -221,6 +228,17 @@ void Pipeline::PredictMOT(const std::string& video_path) { ...@@ -221,6 +228,17 @@ void Pipeline::PredictMOT(const std::string& video_path) {
fclose(fp); fclose(fp);
LOG(INFO) << "txt result output saved as " << result_output_path.c_str(); LOG(INFO) << "txt result output saved as " << result_output_path.c_str();
result_output_path = output_dir_ + OS_PATH_SEP + "flow_statistic.txt";
if ((fp = fopen(result_output_path.c_str(), "w+")) == NULL) {
printf("Open %s error.\n", result_output_path);
return;
}
for (int l; l < flow_records.size(); ++l) {
fprintf(fp, flow_records[l].c_str());
}
fclose(fp);
LOG(INFO) << "txt flow statistic saved as " << result_output_path.c_str();
} }
} }
...@@ -230,11 +248,16 @@ void Pipeline::PredictMTMCT(const std::vector<std::string> video_path) { ...@@ -230,11 +248,16 @@ void Pipeline::PredictMTMCT(const std::vector<std::string> video_path) {
void Pipeline::RunMOTStream(const cv::Mat img, void Pipeline::RunMOTStream(const cv::Mat img,
const int frame_id, const int frame_id,
const int video_fps,
const Rect entrance,
cv::Mat out_img, cv::Mat out_img,
std::vector<std::string>* records, std::vector<std::string>* records,
std::vector<int>* count_list, std::set<int>* id_set,
std::vector<int>* in_count_list, std::set<int>* interval_id_set,
std::vector<int>* out_count_list) { std::vector<int>* in_id_list,
std::vector<int>* out_id_list,
std::map<int, std::vector<float>>* prev_center,
std::vector<std::string>* flow_records) {
PaddleDetection::MOTResult result; PaddleDetection::MOTResult result;
std::vector<double> det_times(3); std::vector<double> det_times(3);
double times; double times;
...@@ -250,15 +273,15 @@ void Pipeline::RunMOTStream(const cv::Mat img, ...@@ -250,15 +273,15 @@ void Pipeline::RunMOTStream(const cv::Mat img,
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,
img, result, 1000. / times, frame_id); frame_id);
if (count_) { // Count total number
// Count total number // Count in & out number
// Count in & out number PaddleDetection::FlowStatistic(result, frame_id, secs_interval_, do_entrance_counting_,
PaddleDetection::FlowStatistic( video_fps, entrance, id_set,
result, frame_id, count_list, in_count_list, out_count_list); interval_id_set, in_id_list,
} out_id_list, prev_center, flow_records);
PrintBenchmarkLog(det_times, frame_id); PrintBenchmarkLog(det_times, frame_id);
if (save_result_) { if (save_result_) {
...@@ -303,4 +326,4 @@ void Pipeline::PrintBenchmarkLog(const std::vector<double> det_time, ...@@ -303,4 +326,4 @@ void Pipeline::PrintBenchmarkLog(const std::vector<double> det_time,
<< ", postprocess_time(ms): " << det_time[2] / num; << ", postprocess_time(ms): " << det_time[2] / num;
} }
} // namespace PaddleDetection } // namespace PaddleDetection
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
// for setprecision // for setprecision
#include <chrono> #include <chrono>
#include <iomanip> #include <iomanip>
#include <iostream>
#include "include/postprocess.h" #include "include/postprocess.h"
namespace PaddleDetection { namespace PaddleDetection {
...@@ -101,10 +102,80 @@ cv::Mat VisualizeTrackResult(const cv::Mat& img, ...@@ -101,10 +102,80 @@ cv::Mat VisualizeTrackResult(const cv::Mat& img,
void FlowStatistic(const MOTResult& results, void FlowStatistic(const MOTResult& results,
const int frame_id, const int frame_id,
std::vector<int>* count_list, const int secs_interval,
std::vector<int>* in_count_list, const bool do_entrance_counting,
std::vector<int>* out_count_list) { const int video_fps,
throw "Not Implement"; const Rect entrance,
std::set<int>* id_set,
std::set<int>* interval_id_set,
std::vector<int>* in_id_list,
std::vector<int>* out_id_list,
std::map<int, std::vector<float>>* prev_center,
std::vector<std::string>* records) {
if (frame_id == 0)
interval_id_set->clear();
if (do_entrance_counting) {
// Count in and out number:
// Use horizontal center line as the entrance just for simplification.
// If a person located in the above the horizontal center line
// at the previous frame and is in the below the line at the current frame,
// the in number is increased by one.
// If a person was in the below the horizontal center line
// at the previous frame and locates in the below the line at the current frame,
// the out number is increased by one.
// TODO: if the entrance is not the horizontal center line,
// the counting method should be optimized.
float entrance_y = entrance.top;
for (const auto& result : results) {
float center_x = (result.rects.left + result.rects.right) / 2;
float center_y = (result.rects.top + result.rects.bottom) / 2;
int ids = result.ids;
std::map<int, std::vector<float>>::iterator iter;
iter = prev_center->find(ids);
if (iter != prev_center->end()) {
if (iter->second[1] <= entrance_y && center_y > entrance_y) {
in_id_list->push_back(ids);
}
if (iter->second[1] >= entrance_y && center_y < entrance_y) {
out_id_list->push_back(ids);
}
(*prev_center)[ids][0] = center_x;
(*prev_center)[ids][1] = center_y;
} else {
prev_center->insert(
std::pair<int, std::vector<float>>(ids, {center_x, center_y}));
}
}
}
// Count totol number, number at a manual-setting interval
for (const auto& result : results) {
id_set->insert(result.ids);
interval_id_set->insert(result.ids);
}
std::ostringstream os;
os << "Frame id: " << frame_id
<< ", Total count: " << id_set->size();
if (do_entrance_counting) {
os << ", In count: " << in_id_list->size()
<< ", Out count: " << out_id_list->size();
}
// Reset counting at the interval beginning
int curr_interval_count = -1;
if (frame_id % video_fps == 0 && frame_id / video_fps % secs_interval == 0) {
curr_interval_count = interval_id_set->size();
os << ", Count during " << secs_interval
<< " secs: " << curr_interval_count;
interval_id_set->clear();
}
os << "\n";
std::string record = os.str();
records->push_back(record);
LOG(INFO) << record;
} }
void SaveMOTResult(const MOTResult& results, void SaveMOTResult(const MOTResult& results,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册