deepstream-image-decode-test解析

0. application介绍

相对于deepstream中大多使用video的例子,该sample向我们展示了如何使用image的解码器来进行图像的推理。该sample支持多路输入,是在deepstream-test3的基础上改进得到的。该pipeline接收MJPEG和JPEG格式的数据作为输入。

该sample的代码位于deepstream下的sources/apps/sample_apps/deepstream-image-decode-test路径下面。

1. 编译和运行

根据该sample下的README,学习一下如何编译和运行该sample。README提供的命令行如下:

To compile:                # 编译

  $ Set CUDA_VER in the MakeFile as per platform.        # 设置CUDA的版本(应该根据自己当前平台安装的CUDA版本提供)
      For Jetson, CUDA_VER=10.2                # 对于Jetson硬件平台
      For x86, CUDA_VER=11.4                        # 对于x86硬件平台
  $ sudo make                                        # make 编译(加不加sudo随意)
To run:                                                # 运行推理
  $ ./deepstream-image-decode-app <file1> [file2] ... [fileN]                # fileN为文件的路径
e.g.
  $ ./deepstream-image-decode-app file1.mjpeg file2.mjpeg

通过运行上述的命令,(只要不移动该sample代码的位置)一般情况下能编译运行起来。但是,还是解释一下Makefile中一些语句的含义:

CUDA_VER 

与CUDA_VER相关的语句如下,含义只要正确的设置cuda的版本编译的时候才能找到向对应的头文件和动态链接库

CUDA_VER?=
ifeq ($(CUDA_VER),)
  $(error "CUDA_VER is not set")
endif
# cuda的头文件路径
-I /usr/local/cuda-$(CUDA_VER)/include 
# cuda的库文件路径
-L/usr/local/cuda-$(CUDA_VER)/lib64/

sources文件夹下的include路径

在Makefile文件中使用如下的语句链接sources路径下的include文件夹,采用的是相对路径,如果你移动了该sample代码的位置,建议使用绝对路径指定include的路径

-I../../../includes

这样我们基本上能正确的编译通过,此时在该sample的路径下会生成一个deepstream-image-decode-app的可执行文件,通过运行与如下类似的命令,便可以在显示器上看到检测结果(对于输入的图像数据,检测结果会一闪而过

# jpg 图像
./deepstream-image-decode-app /opt/nvidia/deepstream/deepstream-6.0/samples/streams/sample_720p.jpg
# mjpeg 视频数据
./deepstream-image-decode-app /opt/nvidia/deepstream/deepstream-6.0/samples/streams/sample_720p.mjpeg

2. pipeline分析

该sample的整体pipeline结果应该如下图所示。filesrc接收jpg或mjepg数据,jpegparser对数据进行解析,nvv4l2decoder对数据进行解码,streammux将多路数据组成batch,nvinfer对输入的batch数据进行推理,nvmultistreamtiler将batch数据平铺成2D数据,nvvideoconvert将数据格式从NV12转换成RGBA(nvosd要求的数据格式), nvdsosd将检测结果渲染到frame数据中,nvegltransform和nveglelessink用于将结果显示到屏幕上。

 同样,我们也可以使用gstreamer自带的功能导出pipeline。具体步骤如下:

1. 安装graphviz,该工具能将dot文件转换为pdf或者图像文件

sudo apt-get install graphviz

2. 设置GST_DEBUG_DUMP_DOT_DIR属性

设置GST_DEBUG_DUMP_DOT_DIR属性有两种方式,一种是暂时性修改(仅对当前终端有效),设置方法是在当前终端输入如下命令:

export GST_DEBUG_DUMP_DOT_DIR=./pipeline/

 另一种是永久修改,通过在~/.bashrc文件中添加上面类似的语句,具体过程如下:

sudo vi ~/.bashrc
# 进入文件添加该语句, 同时需要注意的是给定的路径一定要存在,即gstreamer不会自动创建文件名
export GST_DEBUG_DUMP_DOT_DIR=/home/nvidia/pipeline/
# 保存文件
source ~/.bashrc

 3. 生成pipeline的dot文件

对于gst-launch-1.0工具和deepstream-app,只要pipeline的状态改变就会生成一组新的pipeline的dot文件。正常情况下,生成的文件内容如下所示。

 对于自己搭建的应用程序,需要在cpp文件中加入如下的语句:

GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pipeline");

其中,GST_DEBUG_BIN_TO_DOT_FILE的定义如下:

#define GST_DEBUG_BIN_TO_DOT_FILE(bin, details, file_name) gst_debug_bin_to_dot_file (bin, details, file_name)

 各参数的含义如下:

 4. 将dot文件转换为pdf或图像文件

通过-?能查看dot支持的命令

dot -?

 将dot文件转换的命令一般如下:

dot -T{format} src_file>dst_file

 一般情况下,是将playing状态的dot文件转换,方式如下:

# pdf(效果比较好)
dot -Tpdf pipeline/0.00.06.619216356-ds-app-playing.dot > pipeline/pipeline-playing.pdf
# png
dot -Tpng pipeline/0.00.06.619216356-ds-app-playing.dot > pipeline/pipeline-playing.png

3. plugin使用分析

 3.1 source plugin

在该sample中,提供了两种source插件:filesrcmultifilesrc

  if (strstr(uri, "%d"))
  {
    source = gst_element_factory_make("multifilesrc", "source");
    multi_file_src = TRUE;
  }
  else
    source = gst_element_factory_make ("filesrc", "source");

 filesrc接收单个文件(包括图片和视频),具体的代码分析可以参考【Gstreamer之plugin教程二-filesrc】

multifilesrc支持接收一个序列的数据,其中的index序号使用"%d"格式化表示。对于该sample,如果你的图像数据的命名是如下格式:

image
├── test0000.jpg
├── test0001.jpg
├── test0002.jpg
├── test0003.jpg
├── test0004.jpg
├── test0005.jpg
├── test0006.jpg
├── test0007.jpg
...

可以通过如下命令,推理这个序列的data:

./deepstream-image-decode-app ./image/test%04d.jpg

 需要注意的是,输入的序列文件名中间不能中断或间隔多个,否则后续的数据没法检测

3.2 保存图像推理结果

在该sample中,对于图像推理后其结果会一闪而过,因此想的是将检测结果保存下来,同时也可以参考下面这个问题。

How to save output image when running deepstream-image-decode-test?

保存图像推理结果的具体做法是添加nvvideoconvert->jpegenc->filesink这个三个plugin。代码如下:

  /* --------------------------- 添加element用于输出JPEG ------------------ */
  GstElement *nvvideoconvert = NULL, *jpegenc  = NULL;
  nvvideoconvert = gst_element_factory_make("nvvideoconvert", "nvvideo-converter2");  // RGBA -> RGB
  jpegenc = gst_element_factory_make("jpegenc", "jpegenc");
  sink = gst_element_factory_make("multifilesink", "mjpeg-filesink");
  /* -------------------------------------------------------------------  */ 
  g_object_set (G_OBJECT (sink), "sync", 0, NULL);
  g_object_set (G_OBJECT (sink), "location", "test%d.jpg", NULL);

此时的pipeline应该如下:

filesrc->jpegparse->nvv4l2decoder->nvstreammux->nvinfer->nvmultistreamtiler->nvvideoconvert->nvdsosd->nvvideoconvert->jpegenc->filesink 

3.3 将filesink修改为fakesink

使用fakesink意味着什么都不输出,具体问题描述可以参考下面链接

In deepstream_image_decoder_c,how can I change nveglglessink to fakesink?

同样问题的解决方法也在这个链接中给出,通过在sink前面添加一个queue。

#ifdef PLATFORM_TEGRA
  transform = gst_element_factory_make ("queue", "nvegl-transform");
#endif
  sink = gst_element_factory_make ("fakesink", "nvvideo-renderer");

 上述只是对如何使用该sample进行了介绍,如果相对其进行更多的修改请阅读源代码!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值