上一篇文章已经带着大家安装DeepStream的Python开发环境,并且执行最简单的deepstream-test1.py,让大家体验一下这个范例的效果。本文则进一步以这个Python代码讲解DeepStream插件工作流,并且扩充USB摄像头作为输入,以及将输出透过RTSP转发到其他电脑上观看。
如果还未安装Python环境或下载Python范例的,请至前一篇文章中找安装与下载的步骤,这里不再重复。
前面文章中已经简单提过DeepStream所用到的插件内容,但那只是整个框架中非常基础的一小部分,本文要用代码开始解说范例的时候,还是得将Gstreamer一些重要构成元素之间的关系说明清楚,这样才能让大家在代码过程得以一目了然。
现在先把这个test1范例的执行流程先讲解清楚,这样在阅读后面的代码就会更加容易掌握上下之间的交互关系。这里的流程对C/C++版本与Python版本是完全一样的,只不过代码不过用Python来说明:
建立DeepStream应用程式的步骤与Gstreamer几乎一样,都是有固定的步骤,只要熟悉之后就会发现其实并没有什么难度,接下去就开始我们的执行步骤。
|
# 从“def main(args):”开始 GObject.threads_init() # 标准GStreamer初始化 Gst.init(None) # 创建Gst物件与初始化 pipeline = Gst.Pipeline() # 创建与其他元素相连接的管道元素 |
|
# 阶段1-处理输入源的插件: # 建立“源”元素负责从文件读入数据 source = Gst.ElementFactory.make("filesrc", "file-source") # 解析文件是否为要求的h264格式 h264parser = Gst.ElementFactory.make("h264parse", "h264-parser") # 调用NVIDIA的nvdec_h264硬件解码器 decoder = Gst.ElementFactory.make("nvv4l2decoder", "nvv4l2-decoder") # 创建nvstreammux实例,将单个或多个源数据,复用成一个“批(batch)” streammux = Gst.ElementFactory.make("nvstreammux", "Stream-muxer")
# 阶段2-执行推理的插件: # 使用NVINFERE对解码器的输出执行推理,推理行为是通过配置文件设置 pgie = Gst.ElementFactory.make("nvinfer", "primary-inference")
# 阶段3-处理输出的插件: # 根据nvosd的要求,使用转换器将NV12转换为RGBA nvvidconv = Gst.ElementFactory.make("nvvideoconvert", "convertor") # 创建OSD以在转换的RGBA缓冲区上绘制 nvosd = Gst.ElementFactory.make("nvdsosd", "onscreendisplay") # 最后将osd的绘制,进行渲染后在屏幕上显示结果 transform=Gst.ElementFactory.make("nvegltransform", "egltransform") sink = Gst.ElementFactory.make("nveglglessink", "nvvideo-renderer") |
|
# 以args[1]给定的文件名为输入源视频文件 source.set_property('location', args[1]) # 设定流复用器的尺寸、数量 streammux.set_property('width', 1920) streammux.set_property('height', 1080) streammux.set_property('batch-size', 1) streammux.set_property('batched-push-timeout', 4000000) # 设定pgie的配置文件 pgie.set_property('config-file-path', "dstest1_pgie_config.txt") |
|
pipeline.add(source) pipeline.add(h264parser) pipeline.add(decoder) pipeline.add(streammux) pipeline.add(pgie) pipeline.add(nvvidconv) pipeline.add(nvosd) pipeline.add(sink) if is_aarch64(): pipeline.add(transform) |
|
source.link(h264parser) # file-source -> h264-parser h264parser.link(decoder) # h264-parser -> nvh264-decoder # 下面粗线的三行,是streammux的特殊处理方式 sinkpad = streammux.get_request_pad("sink_0") srcpad = decoder.get_static_pad("src") srcpad.link(sinkpad) streammux.link(pgie) # streammux -> nvinfer pgie.link(nvvidconv) # nvinfer -> nvvidconv nvvidconv.link(nvosd) # nvvidconv -> nvosd nvosd.link(transform) # nvosd -> transform transform.link(sink) # transform -> video-renderer |
前面5个步骤都是比较静态的固定步骤,只要将想开发的应用所需要的插件元件进行“创建”、“给值”、“连接”就可以。
接下去的部分是整个应用中非常关键的灵魂,就是我们得为整个应用去建构“信息(message)传递系统”,这样才能让这个应用与插件元件之间形成互动,进而正确执行我们想要得到的结果。其相互关系图如下,这里并不花时间去讲解调用细节,想了解的请自行参考Gstreamer框架的详细使用。

|
loop = GObject.MainLoop() bus = pipeline.get_bus() bus.add_signal_watch() bus.connect ("message", bus_call, loop) # 用osdsinkpad来确认nvosd插件是否获得输入 osdsinkpad = nvosd.get_static_pad("sink") # 添加探针(probe)以获得生成的元数据的通知,我们将probe添加到osd元素的接收器板中,因为到那时,缓冲区将具有已经得到了所有的元数据。 osdsinkpad.add_probe(Gst.PadProbeType.BUFFER, \ osd_sink_pad_buffer_probe, 0) |
注意粗体“osd_sink_pad_buffer_probe”部分,这是代码中另一个重点,需要自行撰写代码去执行的部分,就是代码中第41~126行的内容,这里面的处理以“帧”为单位(在“while l_frame is not None:”里面),将该帧所检测到的物件种类进行加总,并且将物件根据种类的颜色画出框框。
事实上在这80+行代码中,真正与数据处理相关的部分,只有20行左右的内容,注释的部分占用不小的篇幅,这是作者为大家提供非常重要的说明,只要耐心地去阅读,就能轻松地掌握里面的要领。
|
# 配置导管状态为PLAYING就可以 pipeline.set_state(Gst.State.PLAYING) try: loop.run() # 执行前面创建的事件循环 except: pass # 执行结束之后,需要清除导管,将状态为NULL就可以 pipeline.set_state(Gst.State.NULL) |
以上就是建立DeepStream应用的标准步骤,可以将“def main(args):”部分的代码当作是个模板去加以利用。
至于“osd_sink_pad_buffer_probe”函数的作用,就是从osd接收器提取接收的元数据,并更新绘图矩形、对象信息等的参数,里面的代码也都是标准内容,可以在别的应用在重复套用。更多参数优化的细节部分,须花时间详细阅读DeepStream开发手册。
接下来就实际执行一下Python版本的deepstream-test1代码,看看效果如何!
前面文章中已经将NVIDIA/AI-IOT/deepstream-python-apps项目下载到Jetson Nano 2GB上的<DeepStream根目录>/sources下面,现在就到这个目录下去执行
|
cd <DeepStream根目录>/sources/deepstream_python_apps/apps cd deepstream-test1 |
下面有执行文件deepstream_test_1.py、配置文件dstest1_pgie_config.txt与说明文件README,这个配置文件就是步骤3最后“pgie.set_property”里面指定的文件,在执行文件里看不到任何与推理模型相关的内容,原来都放在设定文件里面去指定了。
关于设定文件的参数设定部分,是相对容易了解的,这里不多花时间说明,接下去直接执行以下指令看看执行结果:
|
python3 deepstream_test_1.py ../../../../samples/streams/sample_720p.h264 |
就能跑出我们熟悉的结果,

如果觉得左上方显示的字体太小,请自行改动代码第110行的字体号数。下图是字体放大到20号时候的显示结果,现在就可以看到很清楚了。

到这里,相信您应该对DeepStream代码有更深层次的了解,在了解整个框架与工作流程之后,可以发现要开发一个基础应用,并不是一件太困难的事情,不过建议您多反复阅读代码内的每一行说明,并且自行适度修改些参数看看效果会有什么变化,一旦熟悉这些逻辑与交互关系之后,就会觉得DeepStream其实很简单。《完》
好文章,需要你的鼓励
阿里云CEO吴泳铭在财报电话会议上表示,AI需求增长如此迅猛,以至于服务器部署速度无法跟上客户需求。公司正在对GPU进行配给制,优先满足使用全套阿里云服务的客户需求。过去12个月,阿里巴巴在AI相关基础设施上投入1200亿元人民币,预计三年预算可能超过当前的3800亿元。阿里云智能集团季度营收达56亿美元,同比增长34%。
新加坡南洋理工大学团队开发的NEO模型颠覆了传统视觉语言AI的设计思路,从模块化拼接转向原生统一架构。仅用3.9亿图文配对数据就实现了与大型模块化系统相媲美的性能,证明了端到端训练的有效性,为AI系统设计开辟了新路径。
OpenAI为ChatGPT推出"购物研究"新功能,恰逢假期购物季。该功能面向免费和付费用户开放,支持移动端和网页版。用户询问购物问题时,ChatGPT会提供个性化购物助手服务,通过一系列问题帮助用户筛选价格、用途和功能偏好。该功能基于专为购物任务优化的GPT-5 mini版本,从优质网络资源获取产品信息。OpenAI计划推出即时结账功能,允许用户直接在ChatGPT内购买商品。
谷歌联合德克萨斯大学等机构开发出LATTICE框架,这是一种革命性的信息检索系统,能像智能图书管理员一样工作。它将文档组织成语义树结构,用AI推理能力进行智能导航搜索,在复杂查询任务上比传统方法准确率提高9%以上。该系统无需训练即可适应新领域,为未来智能搜索指明了方向。