#include "nv_tracker_manager.hpp" #define NVDS_USER_OBJECT_META_LANDMARKS_AND_SOURCE_ID \ (nvds_get_user_meta_type(const_cast("NVIDIA.NVINFER.USER_META"))) #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 FACE_COMPONENT_ID 2 #define FACE_CLASS_ID 42 #define THRESHOLD_LANDMARKS 0.1 unsigned int NvTrackerManager::PGIE_NET_WIDTH = 1; unsigned int NvTrackerManager::PGIE_NET_HEIGHT = 1; unsigned int NvTrackerManager::MUXER_OUTPUT_WIDTH = 1; unsigned int NvTrackerManager::MUXER_OUTPUT_HEIGHT = 1; std::vector NvTrackerManager::body_face_list; FaceCandidTrace *NvTrackerManager::face_candidate_trace = new FaceCandidTrace(); // nullptr; // Definition gint NvTrackerManager::frame_number = 0; NvTrackerManager::NvTrackerManager() { const auto &config = ConfigManager::get_instance().get_config(); ll_config_file = config["ll-config-file"].get(); ll_lib_file = config["ll-lib-file"].get(); PGIE_NET_WIDTH = config["PGIE_NET_WIDTH"]; PGIE_NET_HEIGHT = config["PGIE_NET_HEIGHT"]; MUXER_OUTPUT_WIDTH = config["MUXER_OUTPUT_WIDTH"]; MUXER_OUTPUT_HEIGHT = config["MUXER_OUTPUT_HEIGHT"]; } bool NvTrackerManager::create_nv_tracker() { tracker = gst_element_factory_make("nvtracker", "tracker_plugin"); g_object_set(G_OBJECT(tracker), "ll-config-file", ll_config_file.c_str(), NULL); g_object_set(G_OBJECT(tracker), "ll-lib-file", ll_lib_file.c_str(), NULL); g_object_set(G_OBJECT(tracker), "display-tracking-id", 1, NULL); g_object_set(G_OBJECT(tracker), "gpu_id", GPU_ID, NULL); // g_object_set (G_OBJECT (tracker), "enable_batch_process", 1, NULL); if (!tracker) { g_printerr("Unable to create Tracker.\n"); return false; } return true; } void NvTrackerManager::get_face_score(float *user_meta_data) { face_score = (user_meta_data[8] + user_meta_data[11] + user_meta_data[14]) / 3; } bool NvTrackerManager::check_existence(int object_id, int source_id, float area, bool *is_area_updated) { for (std::vector::iterator iter = body_face_list.begin(); iter != body_face_list.end(); iter++) { if (((*iter).object_id == object_id) && ((*iter).source_id == source_id)) { if (area > (*iter).largest_area) { (*iter).largest_area = area; *is_area_updated = true; } (*iter).num_frames++; std::cout << "source_id = " << source_id << " object_id = " << object_id << " face num_frames = " << (*iter).num_frames << std::endl; return true; } } return false; } // Attach probe to a pad in the pipeline void NvTrackerManager::attach_probe_to_element() { GstPad *src_pad = gst_element_get_static_pad(tracker, "src"); if (!src_pad) { std::cerr << "Unable to get nvosd src pad\n"; return; } gst_pad_add_probe(src_pad, GST_PAD_PROBE_TYPE_BUFFER, tracker_src_pad_buffer_probe, this, NULL); gst_object_unref(src_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_src_pad_buffer_probe( GstPad *pad, GstPadProbeInfo *info, gpointer u_data) { (void)pad; // (void)u_data; // Cast user_data back to NvTrackerManager* NvTrackerManager *manager = static_cast(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 " // << " source_id " << frame_meta->source_id // << " 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; } // else{ // std::cout << "obj_meta->class_id = " // << obj_meta->class_id << std::endl; // std::quick_exit(0); // } NvDsUserMeta *user_meta = NULL; NvDsMetaList *l_user_meta = NULL; float *user_meta_data = NULL; uint index = 0; for (l_user_meta = obj_meta->obj_user_meta_list; l_user_meta != NULL; l_user_meta = l_user_meta->next) { user_meta = (NvDsUserMeta *)(l_user_meta->data); user_meta_data = (float *)user_meta->user_meta_data; // std::cout << " source_id " << frame_meta->source_id // << " object_id = " << obj_meta->object_id // << std::endl; // user_meta->base_meta.meta_type == 7 means it is user-defined // metadata (NVDS_USER_META). // This is typically used when you attach custom metadata // (like your float* user_meta_data) to an object // (NvDsObjectMeta) using DeepStream APIs. if (user_meta->base_meta.meta_type == NVDS_USER_OBJECT_META_LANDMARKS_AND_SOURCE_ID) { // std::cout << "In Tracker sink "<object_id == 0) { continue; } // ??????????????????????????????????????????????????????????????????? // NvDsObjectMeta *obj_meta = // nvds_acquire_obj_meta_from_pool(batch_meta); // obj_meta->unique_component_id = meta->unique_id; // obj_meta->confidence = user_meta_data[index * 57 + 4]; // obj_meta->object_id = UNTRACKED_OBJECT_ID; // obj_meta->class_id = 0; if (!(user_meta_data[index * 57 + 8] > THRESHOLD_LANDMARKS && user_meta_data[index * 57 + 11] > THRESHOLD_LANDMARKS && user_meta_data[index * 57 + 14] > THRESHOLD_LANDMARKS && user_meta_data[index * 57 + 17] > THRESHOLD_LANDMARKS && user_meta_data[index * 57 + 20] > THRESHOLD_LANDMARKS && user_meta_data[index * 57 + 23] > THRESHOLD_LANDMARKS && user_meta_data[index * 57 + 26] > THRESHOLD_LANDMARKS)) { continue; } // NvOSD_RectParams &face_rect_params; // NvOSD_RectParams *face_rect_params = nullptr; // Fill // face_rect_params.top, .left, .width, .height NvOSD_RectParams *face_rect_params = new NvOSD_RectParams(); face_rect_params->left = user_meta_data[index * 57 + 0]; face_rect_params->top = user_meta_data[index * 57 + 1]; /* Assign bounding box coordinates. */ // Right Shoulder - Left Shoulder if (user_meta_data[index * 57 + 24] > user_meta_data[index * 57 + 21]) { face_rect_params->width = abs((user_meta_data[index * 57 + 24] - user_meta_data[index * 57 + 0]) * MUXER_OUTPUT_WIDTH / PGIE_NET_WIDTH); } else { face_rect_params->width = abs((user_meta_data[index * 57 + 21] - user_meta_data[index * 57 + 0]) * MUXER_OUTPUT_WIDTH / PGIE_NET_WIDTH); } if (user_meta_data[index * 57 + 25] > user_meta_data[index * 57 + 22]) { face_rect_params->height = abs((user_meta_data[index * 57 + 25] - user_meta_data[index * 57 + 1]) * MUXER_OUTPUT_WIDTH / PGIE_NET_WIDTH); } else { face_rect_params->height = abs((user_meta_data[index * 57 + 22] - user_meta_data[index * 57 + 1]) * MUXER_OUTPUT_WIDTH / PGIE_NET_WIDTH); } NvDsObjectMeta *face_obj = nvds_acquire_obj_meta_from_pool(batch_meta); face_obj->unique_component_id = FACE_COMPONENT_ID; // Use a new component ID face_obj->confidence = 1.0; face_obj->rect_params = *face_rect_params; face_obj->rect_params.has_bg_color = 0; face_obj->rect_params.border_width = 2; face_obj->rect_params.border_color = NvOSD_ColorParams{1.0, 0.0, 0.0, 1.0}; // Red box manager->get_face_score(user_meta_data); // FaceCandidate *face_candidate = new FaceCandidate(); FaceCandidTrace::FaceCandidate *face_candidate = new FaceCandidTrace::FaceCandidate(); // NvTrackerManager::FaceCandidate* face_candidate = new // NvTrackerManager::FaceCandidate(); // manager->face_candidate face_candidate->frame_number = frame_meta->frame_num; face_candidate->h = face_rect_params->height; face_candidate->w = face_rect_params->width; face_candidate->face_score = manager->face_score; face_candidate->object_id = obj_meta->object_id; face_candidate->source_id = frame_meta->source_id; bool add_status = face_candidate_trace->add(face_candidate); if (add_status) { face_obj->class_id = FACE_CLASS_ID; } else { face_obj->class_id = 41; } // std::cout << "In Tracker sink " // << " source_id = " << frame_meta->source_id // << " object_id = " << obj_meta->object_id // << " 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; // bool is_area_updated = false; // FaceBody current_face; // current_face.largest_area = face_obj->rect_params.height // * // face_obj->rect_params.width; // current_face.object_id = obj_meta->object_id; // current_face.source_id = frame_meta->source_id; // if (!check_existence( // obj_meta->object_id, current_face.source_id, // current_face.largest_area, &is_area_updated)) { // current_face.num_frames = 1; // body_face_list.push_back(current_face); // std::cout << "source_id = " << current_face.source_id // << " frame_num = " << frame_meta->frame_num // << " object_id = " << obj_meta->object_id // << " size body_face_list = " // << body_face_list.size() << std::endl; // face_obj->class_id = FACE_CLASS_ID; // } // if (is_area_updated) { // face_obj->class_id = FACE_CLASS_ID; // std::cout << "source_id = " << current_face.source_id // << " frame_num = " << frame_meta->frame_num // << " object_id = " << obj_meta->object_id // << " area is updated" << std::endl; // } else { // face_obj->class_id = 41; // // std::cout<<"not is_area_updated "<< std::endl; // } // NvOSD_RectParams &rect_params = obj_meta->rect_params; // NvOSD_TextParams &text_params = obj_meta->text_params; /* Assign bounding box coordinates. */ // rect_params.left = int(data[index * 57 + 0] * // MUXER_OUTPUT_WIDTH / // PGIE_NET_WIDTH); // rect_params.top = int(data[index * 57 + 1] * // MUXER_OUTPUT_HEIGHT / // PGIE_NET_HEIGHT); // rect_params.width = // int((data[index * 57 + 2] - data[index * 57 + 0]) * // MUXER_OUTPUT_WIDTH / PGIE_NET_WIDTH); // rect_params.height = // int((data[index * 57 + 3] - data[index * 57 + 1]) * // MUXER_OUTPUT_HEIGHT / PGIE_NET_HEIGHT); // std::cout << "nvinferserver second for x = " << // rect_params.left // << " y = " << rect_params.top // << " w = " << rect_params.width // << " h = " << rect_params.height // << " score = " << obj_meta->confidence << // std::endl; // /* Border of width 3. */ // rect_params.border_width = 3; // rect_params.has_bg_color = 0; // rect_params.border_color = NvOSD_ColorParams{1, 0, 0, 1}; // /* display_text requires heap allocated memory. */ // text_params.display_text = g_strdup(pgie_class_str[0]); // /* Display text above the left top corner of the object. // */ text_params.x_offset = rect_params.left; // text_params.y_offset = rect_params.top - 10; // /* Set black background for the text. */ // text_params.set_bg_clr = 1; // text_params.text_bg_clr = NvOSD_ColorParams{0, 0, 0, 1}; // /* Font face, size and color. */ // text_params.font_params.font_name = (gchar *)"Serif"; // text_params.font_params.font_size = 11; // text_params.font_params.font_color = // NvOSD_ColorParams{1, 1, 1, 1}; // adding landmarks to obj_meta as user_meta // nvds_add_child_object(obj_meta, face_obj); // nvds_attach_obj_meta(obj_meta, face_obj, NULL); // NvDsUserMeta *um1 = // nvds_acquire_user_meta_from_pool(batch_meta); // um1->user_meta_data = // set_metadata_ptr(&(data[index * 57 + 6]), // source_id); // Add landmarks // here // um1->base_meta.meta_type = // NVDS_USER_OBJECT_META_LANDMARKS_AND_SOURCE_ID; // um1->base_meta.copy_func = // (NvDsMetaCopyFunc)copy_user_meta; // um1->base_meta.release_func = // (NvDsMetaReleaseFunc)release_user_meta; // nvds_add_user_meta_to_obj(obj_meta, um1); // nvds_add_obj_meta_to_frame(frame_meta, obj_meta, NULL); nvds_add_obj_meta_to_frame(frame_meta, face_obj, obj_meta); } // index++; } } 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; }