GstBuffer是GStreamer Pipeline中流动的最基本的数据单元,每个GstBuffer都有与之关联的metadata,DeepStreamer实现了一套拓展的标准metadata数据结构,NvDsBatchMeta是其中最基础的一个。
NvDsBatchMeta内含了一系例metadata数据,包括帧,物体,分类和标签结果,DeepStream通过访问NvDsBatchMeta来访问这些metadata。gst_buffer_get_nvds_batch_meta()
可以从GstBuffer中提取出NvDsBatchMeta。
typedef struct NvDsDisplayMeta { NvDsBaseMeta base_meta; guint num_rects; guint num_labels; guint num_lines; guint num_arrows; guint num_circles; NvOSD_RectParams rect_params[MAX_ELEMENTS_IN_DISPLAY_META]; NvOSD_TextParams text_params[MAX_ELEMENTS_IN_DISPLAY_META]; NvOSD_LineParams line_params[MAX_ELEMENTS_IN_DISPLAY_META]; NvOSD_ArrowParams arrow_params[MAX_ELEMENTS_IN_DISPLAY_META]; NvOSD_CircleParams circle_params[MAX_ELEMENTS_IN_DISPLAY_META]; gint64 misc_osd_data[MAX_USER_FIELDS]; gint64 reserved[MAX_RESERVED_FIELDS]; } NvDsDisplayMeta;
在DeepStream 5.0之后增加了绘制arrow和circle两种形状的支持,因此相对于4.0增加了对应的两个数据结构。从上述声明中可以看出,一帧图像支持绘制的object的个数是有上限的,查看头文件可以知道MAX_ELEMENTS_IN_DISPLAY_META=16
。
/*
* file-source -> h264parser -> nvv4l2decoder ->nvstreammux
* nvinfer -> nvvideoconvert -> nvdsosd -> nveglglessink
*/
以这样一条pipeline为例,nvinfer将完成推理任务,在nvvideoconvert阶段将获得所有需要OSD的objectmetadata信息,这时候将你所想要额外fontparams添加到NvDisplayMeta中即可。
// Build pipeline时为nvvideoconvert添加GstPadProbe
{
nvvidconv_sink_pad = gst_element_get_static_pad (nvvidconv, "sink");
if (!nvvidconv_sink_pad)
g_print ("Unable to get sink pad\n");
else
gst_pad_add_probe (nvvidconv_sink_pad, GST_PAD_PROBE_TYPE_BUFFER,
nvvidconv_sink_pad_buffer_probe, NULL, NULL);
}
//
static GstPadProbeReturn
nvvidconv_sink_pad_buffer_probe (GstPad * pad, GstPadProbeInfo * info,
gpointer u_data)
{
GstBuffer *buf = (GstBuffer *) info->data;
NvDsObjectMeta *obj_meta = NULL;
guint vehicle_count = 0;
guint person_count = 0;
guint face_count = 0;
guint lp_count = 0;
NvDsMetaList * l_frame = NULL;
NvDsMetaList * l_obj = NULL;
NvDsDisplayMeta *display_meta = NULL;
// 遍历GstBuffer取出NvDsBatchMeta
NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta (buf);
// 遍历batch中的所有帧
// 假如只有一路流(nvstreammux的batch-size=1),那么frame_meta_list长度为1
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;
// 遍历object_list,对于常规第三方算法手段可以省略,直接设置NvDsDisplayMeta即可
for (l_obj = frame_meta->obj_meta_list; l_obj != NULL;
l_obj = l_obj->next) {
obj_meta = (NvDsObjectMeta *) (l_obj->data);
/* Check that the object has been detected by the primary detector
* and that the class id is that of vehicles/persons. */
if (obj_meta->unique_component_id == PRIMARY_DETECTOR_UID) {
if (obj_meta->class_id == PGIE_CLASS_ID_VEHICLE)
vehicle_count++;
if (obj_meta->class_id == PGIE_CLASS_ID_PERSON)
person_count++;
}
if (obj_meta->unique_component_id == SECONDARY_DETECTOR_UID) {
if (obj_meta->class_id == SGIE_CLASS_ID_FACE) {
face_count++;
/* Print this info only when operating in secondary model. */
if (SECOND_DETECTOR_IS_SECONDARY)
g_print ("Face found for parent object %p (type=%s)\n",
obj_meta->parent, pgie_classes_str[obj_meta->parent->class_id]);
}
if (obj_meta->class_id == SGIE_CLASS_ID_LP) {
lp_count++;
/* Print this info only when operating in secondary model. */
if (SECOND_DETECTOR_IS_SECONDARY)
g_print ("License plate found for parent object %p (type=%s)\n",
obj_meta->parent, pgie_classes_str[obj_meta->parent->class_id]);
}
}
}
// 添加自定义的OSD信息,具体有哪些设置参数可以参考官方API文档
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 = g_malloc0 (MAX_DISPLAY_LEN);
offset = snprintf(txt_params->display_text, MAX_DISPLAY_LEN, "Person = %d ", person_count);
offset += snprintf(txt_params->display_text + offset , MAX_DISPLAY_LEN, "Vehicle = %d ", vehicle_count);
offset += snprintf(txt_params->display_text + offset , MAX_DISPLAY_LEN, "Face = %d ", face_count);
offset += snprintf(txt_params->display_text + offset , MAX_DISPLAY_LEN, "License Plate = %d ", lp_count);
/* 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 = "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 ("Frame Number = %d Vehicle Count = %d Person Count = %d"
" Face Count = %d License Plate Count = %d\n",
frame_number, vehicle_count, person_count,
face_count, lp_count);
frame_number++;
return GST_PAD_PROBE_OK;
}