未验证 提交 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 {
const bool use_mkldnn = false,
const int cpu_threads = 1,
const bool trt_calib_mode = false,
const bool count = false,
const bool do_entrance_counting = false,
const bool save_result = false,
const std::string& scene = "pedestrian",
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;
this->input_ = input;
this->device_ = device;
......@@ -63,7 +64,8 @@ class Pipeline {
this->use_mkldnn_ = use_mkldnn;
this->cpu_threads_ = cpu_threads;
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;
SelectModel(scene, tiny_obj, is_mtmct);
InitPredictor();
......@@ -81,11 +83,16 @@ class Pipeline {
// Run pipeline in stream
void RunMOTStream(const cv::Mat img,
const int frame_id,
const int video_fps,
const Rect entrance,
cv::Mat out_img,
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>* 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,
std::vector<std::string>* records);
......@@ -114,8 +121,9 @@ class Pipeline {
bool use_mkldnn_ = false;
int cpu_threads_ = 1;
bool trt_calib_mode_ = false;
bool count_ = false;
bool do_entrance_counting_ = false;
bool save_result_ = false;
int secs_interval_ = 10;
};
} // namespace PaddleDetection
......
......@@ -14,11 +14,14 @@
#pragma once
#include <glog/logging.h>
#include <ctime>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <set>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
......@@ -40,9 +43,17 @@ cv::Mat VisualizeTrackResult(const cv::Mat& img,
// Pedestrian/Vehicle Counting
void FlowStatistic(const MOTResult& results,
const int frame_id,
std::vector<int>* count_list,
std::vector<int>* in_count_list,
std::vector<int>* out_count_list);
const int secs_interval,
const bool do_entrance_counting,
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
void SaveMOTResult(const MOTResult& results,
......
......@@ -54,7 +54,10 @@ DEFINE_bool(trt_calib_mode,
"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(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_string(
scene,
......@@ -140,11 +143,12 @@ int main(int argc, char** argv) {
FLAGS_use_mkldnn,
FLAGS_cpu_threads,
FLAGS_trt_calib_mode,
FLAGS_count,
FLAGS_do_entrance_counting,
FLAGS_save_result,
FLAGS_scene,
FLAGS_tiny_obj,
FLAGS_is_mtmct);
FLAGS_is_mtmct,
FLAGS_secs_interval);
pipeline.SetInput(FLAGS_video_file);
if (!FLAGS_video_other_file.empty()) {
......
......@@ -18,6 +18,7 @@
#include <iomanip>
#include <iostream>
#include <string>
#include "include/pipeline.h"
#include "include/postprocess.h"
#include "include/predictor.h"
......@@ -159,9 +160,14 @@ void Pipeline::PredictMOT(const std::string& video_path) {
PaddleDetection::MOTResult result;
std::vector<double> det_times(3);
std::vector<int> count_list;
std::vector<int> in_count_list;
std::vector<int> out_count_list;
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;
Rect entrance = {0, static_cast<float>(video_height) / 2,
static_cast<float>(video_width),
static_cast<float>(video_height) / 2};
double times;
double total_time;
// Capture all frames and do inference
......@@ -169,6 +175,7 @@ void Pipeline::PredictMOT(const std::string& video_path) {
int frame_id = 0;
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");
LOG(INFO) << "------------------- Predict info ------------------------";
......@@ -188,13 +195,13 @@ void Pipeline::PredictMOT(const std::string& video_path) {
cv::Mat out_img = PaddleDetection::VisualizeTrackResult(
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_) {
PaddleDetection::SaveMOTResult(result, frame_id, &records);
}
......@@ -221,6 +228,17 @@ void Pipeline::PredictMOT(const std::string& video_path) {
fclose(fp);
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) {
void Pipeline::RunMOTStream(const cv::Mat img,
const int frame_id,
const int video_fps,
const Rect entrance,
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) {
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>* flow_records) {
PaddleDetection::MOTResult result;
std::vector<double> det_times(3);
double times;
......@@ -250,15 +273,15 @@ void Pipeline::RunMOTStream(const cv::Mat img,
LOG(INFO) << "frame_id: " << frame_id
<< " predict time(s): " << total_time / 1000;
out_img = PaddleDetection::VisualizeTrackResult(
img, result, 1000. / times, frame_id);
out_img = PaddleDetection::VisualizeTrackResult(img, result, 1000. / times,
frame_id);
if (count_) {
// Count total number
// Count in & out number
PaddleDetection::FlowStatistic(
result, frame_id, count_list, in_count_list, out_count_list);
}
// Count total number
// Count in & out number
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);
PrintBenchmarkLog(det_times, frame_id);
if (save_result_) {
......@@ -303,4 +326,4 @@ void Pipeline::PrintBenchmarkLog(const std::vector<double> det_time,
<< ", postprocess_time(ms): " << det_time[2] / num;
}
} // namespace PaddleDetection
} // namespace PaddleDetection
......@@ -16,6 +16,7 @@
// for setprecision
#include <chrono>
#include <iomanip>
#include <iostream>
#include "include/postprocess.h"
namespace PaddleDetection {
......@@ -101,10 +102,80 @@ cv::Mat VisualizeTrackResult(const cv::Mat& img,
void FlowStatistic(const MOTResult& results,
const int frame_id,
std::vector<int>* count_list,
std::vector<int>* in_count_list,
std::vector<int>* out_count_list) {
throw "Not Implement";
const int secs_interval,
const bool do_entrance_counting,
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) {
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,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册