diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f594b2..642faea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,6 +85,7 @@ set_source_files_properties( src/nv_infer_server_manager.cpp src/main.cpp src/pipeline_manager.cpp + src/nv_tracker_manager.cpp PROPERTIES COMPILE_FLAGS "-Wno-missing-field-initializers" ) diff --git a/data/configuration.json b/data/configuration.json index 2248e84..d31b398 100644 --- a/data/configuration.json +++ b/data/configuration.json @@ -17,6 +17,7 @@ "host": "0.0.0.0" }, "pgie_batch_size": 16, + "threshold_body_detection": 0.05, "inferserver_pgie_config_file": "../data/inferserver/primary_detector_config.txt", "PGIE_NET_WIDTH": 640, "PGIE_NET_HEIGHT": 640, diff --git a/src/nv_infer_server_manager.cpp b/src/nv_infer_server_manager.cpp index df4de91..bc5dd49 100644 --- a/src/nv_infer_server_manager.cpp +++ b/src/nv_infer_server_manager.cpp @@ -10,6 +10,7 @@ unsigned int NvInferServerManager::PGIE_NET_HEIGHT = 1; unsigned int NvInferServerManager::MUXER_OUTPUT_WIDTH = 1; unsigned int NvInferServerManager::MUXER_OUTPUT_HEIGHT = 1; guint NvInferServerManager::use_device_mem = 0; +float NvInferServerManager::threshold_body_detection = 0; const gchar pgie_class_str[PGIE_DETECTED_CLASS_NUM][32] = {"Person"}; @@ -28,6 +29,7 @@ NvInferServerManager::NvInferServerManager() { PGIE_NET_HEIGHT = config["PGIE_NET_HEIGHT"]; MUXER_OUTPUT_WIDTH = config["MUXER_OUTPUT_WIDTH"]; MUXER_OUTPUT_HEIGHT = config["MUXER_OUTPUT_HEIGHT"]; + threshold_body_detection = config["threshold_body_detection"]; } bool NvInferServerManager::create_nv_infer_server(int num_sources) { @@ -104,7 +106,7 @@ GstPadProbeReturn NvInferServerManager::osd_sink_pad_buffer_probe( void NvInferServerManager::attach_probe_to_element(GstElement *nvosd) { GstPad *sink_pad = gst_element_get_static_pad(nvosd, "sink"); if (!sink_pad) { - std::cerr << "Unable to get sink pad\n"; + std::cerr << "Unable to get nvosd sink pad\n"; return; } @@ -141,11 +143,14 @@ GstPadProbeReturn NvInferServerManager::osd_sink_pad_buffer_probe_new( if (obj_meta->class_id == PGIE_CLASS_ID_PERSON) { person_count++; num_rects++; - std::cout << "x = " << obj_meta->rect_params.left + std::cout << "In OSD sink " + << "x = " << obj_meta->rect_params.left << " y = " << obj_meta->rect_params.top << " w = " << obj_meta->rect_params.width << " h = " << obj_meta->rect_params.height - << " score = " << obj_meta->confidence << std::endl; + << " score = " << obj_meta->confidence + << " Object ID: " << obj_meta->object_id + << std::endl; } } display_meta = nvds_acquire_display_meta_from_pool(batch_meta); @@ -178,6 +183,7 @@ GstPadProbeReturn NvInferServerManager::osd_sink_pad_buffer_probe_new( nvds_add_display_meta_to_frame(frame_meta, display_meta); } g_print( + "In OSD sink " "Frame Number = %d " "Person Count = %d\n", frame_number, person_count); @@ -290,17 +296,19 @@ GstPadProbeReturn NvInferServerManager::pgie_pad_buffer_probe( uint detected_persons = 0; float *data = static_cast(layer.buffer); for (unsigned int jkl = 0; jkl < 100; ++jkl) { - if (data[jkl * 57 + 4] > 0.05) { + if (data[jkl * 57 + 4] > threshold_body_detection) { detected_persons++; - std::cout << "x = " << data[jkl * 57 + 0] - << " y = " << data[jkl * 57 + 1] - << " w = " << data[jkl * 57 + 2] - << " h = " << data[jkl * 57 + 3] - << " score = " << data[jkl * 57 + 4] << std::endl; + // std::cout << "x = " << data[jkl * 57 + 0] + // << " y = " << data[jkl * 57 + 1] + // << " w = " << data[jkl * 57 + 2] + // << " h = " << data[jkl * 57 + 3] + // << " score = " << data[jkl * 57 + 4] << + // std::endl; for (unsigned int mno = 0; mno < 5; ++mno) { float value = data[jkl * 57 + mno]; - std::cout << "data[" << jkl << "][" << mno - << "] = " << value << std::endl; + (void)value; + // std::cout << "data[" << jkl << "][" << mno + // << "] = " << value << std::endl; } } } diff --git a/src/nv_infer_server_manager.hpp b/src/nv_infer_server_manager.hpp index 0426302..26abbdc 100644 --- a/src/nv_infer_server_manager.hpp +++ b/src/nv_infer_server_manager.hpp @@ -22,6 +22,7 @@ class NvInferServerManager { static gint frame_number; static guint use_device_mem; std::string inferserver_pgie_config_file; + static float threshold_body_detection; NvInferServerManager(); bool create_nv_infer_server(int); ~NvInferServerManager(); diff --git a/src/nv_tracker_manager.cpp b/src/nv_tracker_manager.cpp index 5db24a6..a2e2488 100644 --- a/src/nv_tracker_manager.cpp +++ b/src/nv_tracker_manager.cpp @@ -3,6 +3,11 @@ #define SET_GPU_ID(object, gpu_id) \ g_object_set(G_OBJECT(object), "gpu-id", gpu_id, NULL); #define GPU_ID 0 +#define MAX_DISPLAY_LEN 64 +#define PGIE_CLASS_ID_PERSON 0 +#define PGIE_DETECTED_CLASS_NUM 1 + +gint NvTrackerManager::frame_number = 0; NvTrackerManager::NvTrackerManager() { const auto &config = ConfigManager::get_instance().get_config(); @@ -20,8 +25,98 @@ bool NvTrackerManager::create_nv_tracker() { // g_object_set (G_OBJECT (tracker), "enable_batch_process", 1, NULL); if (!tracker) { - g_printerr("\033[1;31m Unable to create Tracker. Exiting. \033[0m\n"); + g_printerr("Unable to create Tracker.\n"); return false; } return true; -} \ No newline at end of file +} + +// Attach probe to a pad in the pipeline +void NvTrackerManager::attach_probe_to_element(GstElement *nvosd) { + GstPad *sink_pad = gst_element_get_static_pad(nvosd, "src"); + if (!sink_pad) { + std::cerr << "Unable to get nvosd sink pad\n"; + return; + } + + gst_pad_add_probe(sink_pad, GST_PAD_PROBE_TYPE_BUFFER, + tracker_sink_pad_buffer_probe, NULL, NULL); + gst_object_unref(sink_pad); +} + +/* This is the buffer probe function that we have registered on the sink pad + * of the OSD element. All the infer elements in the pipeline shall attach + * their metadata to the GstBuffer, here we will iterate & process the metadata + * forex: class ids to strings, counting of class_id objects etc. */ +GstPadProbeReturn NvTrackerManager::tracker_sink_pad_buffer_probe( + GstPad *pad, GstPadProbeInfo *info, gpointer u_data) { + (void)pad; + (void)u_data; + GstBuffer *buf = (GstBuffer *)info->data; + guint num_rects = 0; + guint person_count = 0; + NvDsObjectMeta *obj_meta = NULL; + NvDsMetaList *l_frame = NULL; + NvDsMetaList *l_obj = NULL; + NvDsDisplayMeta *display_meta = NULL; + + NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta(buf); + + for (l_frame = batch_meta->frame_meta_list; l_frame != NULL; + l_frame = l_frame->next) { + NvDsFrameMeta *frame_meta = (NvDsFrameMeta *)(l_frame->data); + int offset = 0; + for (l_obj = frame_meta->obj_meta_list; l_obj != NULL; + l_obj = l_obj->next) { + obj_meta = (NvDsObjectMeta *)(l_obj->data); + if (obj_meta->class_id == PGIE_CLASS_ID_PERSON) { + person_count++; + num_rects++; + std::cout << "In Tracker sink " + << "x = " << obj_meta->rect_params.left + << " y = " << obj_meta->rect_params.top + << " w = " << obj_meta->rect_params.width + << " h = " << obj_meta->rect_params.height + << " score = " << obj_meta->confidence + << " object_id = " << obj_meta->object_id + << std::endl; + } + } + display_meta = nvds_acquire_display_meta_from_pool(batch_meta); + NvOSD_TextParams *txt_params = &display_meta->text_params[0]; + display_meta->num_labels = 1; + txt_params->display_text = (gchar *)g_malloc0(MAX_DISPLAY_LEN); + offset = snprintf(txt_params->display_text, MAX_DISPLAY_LEN, + "Person = %d ", person_count); + (void)offset; + + /* Now set the offsets where the string should appear */ + txt_params->x_offset = 10; + txt_params->y_offset = 12; + + /* Font , font-color and font-size */ + txt_params->font_params.font_name = (gchar *)"Serif"; + txt_params->font_params.font_size = 10; + txt_params->font_params.font_color.red = 1.0; + txt_params->font_params.font_color.green = 1.0; + txt_params->font_params.font_color.blue = 1.0; + txt_params->font_params.font_color.alpha = 1.0; + + /* Text background color */ + txt_params->set_bg_clr = 1; + txt_params->text_bg_clr.red = 0.0; + txt_params->text_bg_clr.green = 0.0; + txt_params->text_bg_clr.blue = 0.0; + txt_params->text_bg_clr.alpha = 1.0; + + nvds_add_display_meta_to_frame(frame_meta, display_meta); + } + g_print( + "In Tracker sink " + "Frame Number = %d " + "Person Count = %d\n", + frame_number, person_count); + + frame_number++; + return GST_PAD_PROBE_OK; +} diff --git a/src/nv_tracker_manager.hpp b/src/nv_tracker_manager.hpp index 698bf89..2ce9878 100644 --- a/src/nv_tracker_manager.hpp +++ b/src/nv_tracker_manager.hpp @@ -4,14 +4,20 @@ #include #include "config_manager.hpp" +#include "gstnvdsmeta.h" class NvTrackerManager { private: public: GstElement *tracker = NULL; + static gint frame_number; std::string ll_config_file; std::string ll_lib_file; NvTrackerManager(); ~NvTrackerManager(); bool create_nv_tracker(); + void attach_probe_to_element(GstElement *); + static GstPadProbeReturn tracker_sink_pad_buffer_probe(GstPad *, + GstPadProbeInfo *, + gpointer); }; \ No newline at end of file diff --git a/src/pipeline_manager.cpp b/src/pipeline_manager.cpp index e2e8cfb..3573922 100644 --- a/src/pipeline_manager.cpp +++ b/src/pipeline_manager.cpp @@ -246,8 +246,7 @@ bool PipelineManager::setup_pipeline() { gstds_example_manager->custom_plugin, tiler_manager->tiler, nv_osd_manager->nvosd, sink_manager->sink, NULL)) { - g_printerr( - "\033[1;31m Elements could not be linked. Exiting.\033[0m\n"); + g_printerr("Elements could not be linked.\n"); return false; } } else { @@ -273,8 +272,7 @@ bool PipelineManager::setup_pipeline() { nv_osd_manager->nvosd, sink_manager->nvvidconv_postosd, sink_manager->caps, sink_manager->encoder, sink_manager->rtppay, sink_manager->sink, NULL)) { - g_printerr( - "\033[1;31m Elements could not be linked. Exiting.\033[0m\n"); + g_printerr("Elements could not be linked.\n"); return false; } } @@ -358,6 +356,8 @@ bool PipelineManager::create_pipeline_elements(int num_sources, // gst_object_unref(nvinfer); nv_tracker_manager->create_nv_tracker(); + nv_tracker_manager->attach_probe_to_element( + nv_tracker_manager->tracker); // nvinfer Or use "nvtracker" if after message_handling->create_message_handler(pipeline, g_run_forever, loop); setup_pipeline();