deepstream之Metadata Structures分析

 0. 背景介绍

本文主要对deepstream提供的Metadata结构进行分析,包括NvDsBatchMeta ,NvDsFrameMeta,NvDsObjectMeta和NvDsClassifierMeta等Metadata结构。

 通过对官方文档的阅读,可以得到上述的结构图,描述了每个metadata结构之间的联系以及属性。此外,本文对这些metadata结构的测试是通过在pipeline中element的pad上添加probe回调函数,获取得到nvinfer推理之后的数据信息

1. NvDsBatchMeta分析

NvDsBatchMeta的含义:

Holds information about a formed batch containing frames from different sources.

这个对象中包含来自不同源数据构建的batched buffers。

上图为NvDsBatchMeta结构中一些重要的属性,具体的含义如下:

Holds the number of frames now in the batch.当前batch buffer的batch size大小

Holds a pointer to a list of pointers of type NvDsFrameMeta or NvDsAudioFrameMeta (when the batch represent audio batch), representing frame metas used in the current batch。当前batch meta数据中包含的frame meta数据指针

Holds a pointer to a list of pointers of type NvDsUserMeta, representing user metas in the current batch. usermeta我暂时还没有学习和用到,但感觉挺重要的

2. NvDsFrameMeta 

NvDsFrameMeta的含义如下:

Holds metadata for a frame in a batch.

一个batch中的一帧数据

 上图为NvDsFrameMeta结构中一些重要的属性,具体的含义如下:

Holds the location of the frame in the batch.

在这个batch buffer中的第几帧数据

Holds the current frame number of the source.

当前frame meta数据为source id下的第frame_num帧数据

Holds the source IDof the frame in the batch,

batch buffer的数据是来自不同的源,因此对于不同的source会有一个独一无二的ID

Holds the number of object meta elements attached to current frame.

简单来说,就是这一帧数据中,算法检测出了几个物体

Holds a pointer to a list of pointers of type NvDsObjectMeta in use for the frame.

这一帧数据中,被检测出来物体的信息指针

 通过下面代码就能从batch meta中获取到frame meta数据

NvDsMetaList * l_frame = NULL;
for (l_frame = batch_meta->frame_meta_list; l_frame != NULL; l_frame = l_frame->next) 
{
    NvDsFrameMeta *frame_meta = (NvDsFrameMeta *) (l_frame->data);
    // analyze 
    guint  batch_id = frame_meta->batch_id;
    ...
}

3. NvDsObjectMeta

NvDsObjectMeta的含义如下:

Holds metadata for an object in the frame.

该metadata中包含的是一帧数据中单个object的信息 

  • class_id

Holds the index of the object class inferred by the primary detector/classifier.

该属性代表一级检测器或者分类器的预测类别index

  • object_id

Holds a unique ID for tracking the object

如果一级目标检测后续连接了tracker,表示该框的tracked ID

  • confidence

Holds a confidence value for the object, set by the inference component.

目标的分类置信度

  • rect_params

Holds a structure containing positional parameters of the object processed by the last component that updates it in the pipeline.

目标框的位置信息以及需要传递给OSD渲染的信息

  • obj_label 

Holds a string describing the class of the detected object.

目标框的类别字符串 

4. NvDsClassifierMeta分析

  • num_labels         

Holds the number of outputs/labels produced by the classifier.

分类网络的类别数

  • unique_component_id

Holds a unique component ID for the classifier metadata.

指的是该分类metadata对应的gie-unique-id

  • label_info_list

指的是分类目标需要的信息

  • NvDsLabelInfo

  • result_label:预测目标的类别字符串
  • result_class_id:预测目标的index
  • result_prob:预测目标的分类置信度
  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 以下是使用DeepStream C版本进行推流的示例代码: ```c #include <gst/gst.h> #include <glib.h> #include <deepstream_common.h> #include <deepstream_config.h> #include <deepstream_sources.h> #include <deepstream_sink_bin.h> #include <deepstream_metadata.h> #define TILED_OUTPUT_WIDTH 1280 #define TILED_OUTPUT_HEIGHT 720 int main(int argc, char *argv[]) { GstElement *pipeline = NULL; GstBus *bus = NULL; GstMessage *msg = NULL; GError *error = NULL; gchar *pipeline_string = NULL; guint bus_watch_id; // 初始化 GStreamer gst_init(&argc, &argv); // 创建管道 pipeline_string = g_strdup_printf( "filesrc location=%s ! qtdemux ! h264parse ! nvv4l2decoder ! " "nvstreammux name=mux batch-size=1 width=%d height=%d ! " "nvinfer config-file-path=/path/to/config_file.txt ! " "nvvideoconvert ! nvdsosd ! nvegltransform ! nveglglessink sync=false", argv[1], TILED_OUTPUT_WIDTH, TILED_OUTPUT_HEIGHT); pipeline = gst_parse_launch(pipeline_string, &error); if (!pipeline) { g_printerr("Pipeline could not be created. Error: %s\n", error->message); g_clear_error(&error); return -1; } // 创建消息总线 bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); bus_watch_id = gst_bus_add_watch(bus, bus_call, NULL); // 启动管道 gst_element_set_state(pipeline, GST_STATE_PLAYING); // 进入事件循环 g_main_loop_run(loop); // 停止管道 gst_element_set_state(pipeline, GST_STATE_NULL); // 释放资源 gst_object_unref(GST_OBJECT(pipeline)); gst_object_unref(GST_OBJECT(bus)); g_source_remove(bus_watch_id); g_free(pipeline_string); return 0; } ``` 在此示例中,我们使用DeepStream C库创建了一个GStreamer管道,该管道从H264编码视频文件中读取数据,并进行解码,分类和渲染,最终将输出渲染到屏幕上。 注意:此示例代码是基于DeepStream 5.1版本的,您需要根据自己的DeepStream版本和配置文件来调整代码。同时,您需要确保已正确安装DeepStream SDK并正确设置环境变量。 ### 回答2: 要编写一个DeepStream C版本的推流代码,需要首先安装DeepStream SDK并配置好开发环境。 下面是一个简单的DeepStream C版本推流代码示例: ```c #include <deepstream_common.h> #include <gst/gst.h> // 定义推流功能的回调函数 gboolean push_to_rtmp(gpointer data) { GstElement *pipeline; GstBus *bus; GstMessage *msg; // 构建GStreamer pipeline pipeline = gst_parse_launch("videotestsrc ! x264enc ! flvmux ! rtmpsink location=rtmp://example.com/live/stream", NULL); // 启动pipeline gst_element_set_state(pipeline, GST_STATE_PLAYING); // 等待pipeline结束并打印错误信息 bus = gst_element_get_bus(pipeline); msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR); if (msg != NULL) { GError *err; gchar *debug_info; gst_message_parse_error(msg, &err, &debug_info); g_printerr("Error received from element %s: %s\n", GST_OBJECT_NAME(msg->src), err->message); g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none"); g_clear_error(&err); g_free(debug_info); } gst_message_unref(msg); gst_object_unref(bus); gst_element_set_state(pipeline, GST_STATE_NULL); gst_object_unref(pipeline); return G_SOURCE_REMOVE; } int main(int argc, char *argv[]) { GMainLoop *loop; // 初始化GStreamer库 gst_init(&argc, &argv); // 创建GMainLoop事件循环 loop = g_main_loop_new(NULL, FALSE); // 启动推流 g_timeout_add_seconds(10, push_to_rtmp, NULL); // 10秒后开始推流 // 运行事件循环 g_main_loop_run(loop); // 退出程序 g_main_loop_unref(loop); gst_deinit(); return 0; } ``` 这个示例代码使用GStreamer库,建立了一个简单的推流pipeline,将视频源输入经过编码和封装后推送到RTMP服务器上。在main函数中,我们使用GMainLoop来启动推流并运行事件循环,之后就可以将视频数据推送到RTMP服务器上。 注意,这只是一个简单的示例代码,实际使用中可能需要根据自己的需求和配置进行修改。 ### 回答3: deepstream是一个基于NVIDIA的深度学习推理平台,它提供了一个用于构建智能视频分析应用程序的框架。在deepstream中,可以使用C语言编写推流代码来将视频数据发送到外部服务器或流媒体平台。以下是一个示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include "nvds_msgapi.h" #define MAX_SUPPORTED_ENCODERS 64 int main(int argc, char *argv[]) { const char *inputPath = "input.mp4"; // 视频输入路径 const char *outputUri = "rtmp://example.com/stream"; // 视频输出地址 nvds_msgapi_handle_t conn = NULL; nvds_msgapi_connect_async_params_t connect_params = NVDS_MSGAPI_CONNECT_ASYNC_PARAMS_INIT; // 初始化消息传递API连接参数 connect_params.conn_func = (nvds_msgapi_connect_cb_t) &nvds_msgapi_connect_cb; connect_params.disconn_func = (nvds_msgapi_connect_cb_t) &nvds_msgapi_disconnect_cb; connect_params.connect_params.client_id = "deepstream_push"; connect_params.connect_params.proto = "producer"; connect_params.connect_params.server_uri = outputUri; // 连接到目标服务器 nvds_msgapi_connect_async(&connect_params, &conn); // 打开输入视频文件 FILE *inputFile = fopen(inputPath, "rb"); if (inputFile == NULL) { fprintf(stderr, "无法打开输入文件\n"); return -1; } // 按帧读取视频文件并发送到服务器 while (1) { uint8_t frameData[4096]; // 帧数据缓冲区大小 size_t bytesRead = fread(frameData, 1, sizeof(frameData), inputFile); if (bytesRead == 0) { break; } // 将帧数据发送到服务器 nvds_msgapi_send_async(conn, (const uint8_t *) frameData, bytesRead); } // 关闭输入文件和与服务器的连接 fclose(inputFile); nvds_msgapi_disconnect(conn); return 0; } ``` 上述代码使用了deepstream的消息传递API来发送帧数据到指定的服务器。它通过打开输入视频文件,按帧读取数据,并将数据发送到服务器的URI地址指定的位置。在实际使用中,需要替换`inputPath`和`outputUri`为相关的实际路径和地址,并且需要根据需要进行其他定制化开发。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值