diff --git a/deploy/pptracking/include/pipeline.h b/deploy/pptracking/include/pipeline.h index 20ef1d739be964377f0342b0f7cf07ff414634a2..185cd894100ed228d390b833afa1330087c938bc 100644 --- a/deploy/pptracking/include/pipeline.h +++ b/deploy/pptracking/include/pipeline.h @@ -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 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* records, - std::vector* count_list, + std::set* count_set, + std::set* interval_count_set, std::vector* in_count_list, - std::vector* out_count_list); + std::vector* out_count_list, + std::map>* prev_center, + std::vector* flow_records); void RunMTMCTStream(const std::vector imgs, std::vector* 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 diff --git a/deploy/pptracking/include/postprocess.h b/deploy/pptracking/include/postprocess.h index 27586abb5839fc03d76cbd6e3c7e227a34167af6..64d69a9d96392379d2182f85f0d300c0a701cfd5 100644 --- a/deploy/pptracking/include/postprocess.h +++ b/deploy/pptracking/include/postprocess.h @@ -14,11 +14,14 @@ #pragma once +#include + #include #include #include #include #include +#include #include #include @@ -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* count_list, - std::vector* in_count_list, - std::vector* out_count_list); + const int secs_interval, + const bool do_entrance_counting, + const int video_fps, + const Rect entrance, + std::set* id_set, + std::set* interval_id_set, + std::vector* in_id_list, + std::vector* out_id_list, + std::map>* prev_center, + std::vector* records); + // Save Tracking Results void SaveMOTResult(const MOTResult& results, diff --git a/deploy/pptracking/src/main.cc b/deploy/pptracking/src/main.cc index 33219fd80475eb7d3aead4a7c453dfdeb02c6107..1f54c87e1bc327bfcc626383b57a40665f343ce5 100644 --- a/deploy/pptracking/src/main.cc +++ b/deploy/pptracking/src/main.cc @@ -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()) { diff --git a/deploy/pptracking/src/pipeline.cc b/deploy/pptracking/src/pipeline.cc index 63144e8b0d3e7c28960fee3b6ce6290cd403aa80..d508650877b0cb54dab6faa67360adbc2e5730cb 100644 --- a/deploy/pptracking/src/pipeline.cc +++ b/deploy/pptracking/src/pipeline.cc @@ -18,6 +18,7 @@ #include #include #include + #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 det_times(3); - std::vector count_list; - std::vector in_count_list; - std::vector out_count_list; + std::set id_set; + std::set interval_id_set; + std::vector in_id_list; + std::vector out_id_list; + std::map> prev_center; + Rect entrance = {0, static_cast(video_height) / 2, + static_cast(video_width), + static_cast(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 records; + std::vector 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 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* records, - std::vector* count_list, - std::vector* in_count_list, - std::vector* out_count_list) { + std::set* id_set, + std::set* interval_id_set, + std::vector* in_id_list, + std::vector* out_id_list, + std::map>* prev_center, + std::vector* flow_records) { PaddleDetection::MOTResult result; std::vector 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 det_time, << ", postprocess_time(ms): " << det_time[2] / num; } -} // namespace PaddleDetection +} // namespace PaddleDetection diff --git a/deploy/pptracking/src/postprocess.cc b/deploy/pptracking/src/postprocess.cc index 9d9afc5246e6057e0d4e658f12b6f1b168d09b89..2c85b1a4fa81c538eca79bc52875932685b0a3b4 100644 --- a/deploy/pptracking/src/postprocess.cc +++ b/deploy/pptracking/src/postprocess.cc @@ -16,6 +16,7 @@ // for setprecision #include #include +#include #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* count_list, - std::vector* in_count_list, - std::vector* out_count_list) { - throw "Not Implement"; + const int secs_interval, + const bool do_entrance_counting, + const int video_fps, + const Rect entrance, + std::set* id_set, + std::set* interval_id_set, + std::vector* in_id_list, + std::vector* out_id_list, + std::map>* prev_center, + std::vector* 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>::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>(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,