AIoT人工智能物联网之deepstream
相关代码见文末
1.deepstream介绍安装
DeepStream 是一个功能齐全的平台套装,在多个关键领域发挥着重要作用:首先是多源数据采集能力;其次是智能的数据预处理能力;再次是行为轨迹分析能力;最后是高效的编码解决方案。

(1)deepstream docker 版本查询
网页查询
https://catalog.ngc.nvidia.com/containers
(2)下载 deepstream docker 对应 版本
访问该容器的详细文档以获取更多信息

寻找适用于json nano的版本

下载:docker pull nvcr.io/nvidia/deepstream-l4t:6.0.1-samples

进入docker:
docker run -it --rm --net=host --runtime nvidia -e
DISPLAY=$DISPLAY -w /opt/nvidia/deepstream/deepstream -v
/tmp/.X11-unix/:/tmp/.X11-unix nvcr.io/nvidia/deepstream
l4t:6.0.1-samples
上面的是c++版本
找到python版本,并拉取
https://hub.docker.com/r/ryagi997/deepstream-6.0-python


(3)进入docker
xhost +
执行以下Docker命令:以容器模式运行并删除旧容器、使用宿主机网络、采用NVIDIA运行时、指定视频设备为/V Dev 0、设置环境变量$DISPLAY的值、将工作目录设置为/applications/applications/applications和(applications)/applications/applications(applications)、将工作目录设置为(applications)/applications(applications)/applications(applications)、并将工作目录设为(applications)/applications(applications)/apps并将文件映射到(deepstream samples)/python apps中
(4)切换清华数据源
python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --upgrade pip
pip config set global.index-url
https://pypi.tuna.tsinghua.edu.cn/simple
(5)安装jupyter
pip3 install jupyter
jupyter notebook password
jupyter notebook --ip 0.0.0.0 --allow-root --port 8888
(6)保存docker
docker commit 5f2927d43e45 lijianyu110/deepstream-6.0-python:sample-jupyter-v1
docker push lijianyu110/deepstream-6.0-python:sample-jupyter-v1(保存到云端)


2.deepstream介绍
deepstream 基于 GStreamer 而言,在其架构中通过管道将每个元素依次连接到下一个环节,从而构建视频流
(1)source element
对于一个source元素来说,在此框架中我们常用src_pad字段来表示该元素能够生成的数据,并将其放置在其右侧的位置。源元素仅具有src_pad字段这一属性,在通过设备、存储介质或网络等方式获取数据后(如图所示),系统会将获取到的数据通过src_pad字段传递给pipeline模块进行处理以启动其计算流程。

(2)sink element
仅能接收而非生成数据的element被定义为sinks element(如alsasink等)。其中典型的例子包括alsasink等设备类元素,在这些元素中通常会连接一个从其左侧连接的sink pad来表示该类element具备接收处理数据的能力。
对于这类element而言(即sinks element),它们仅具备一个输出端口即所谓的sinks pad用于接收来自 upstream data流的数据,并将其传递给指定的目标设备或存储位置以完成整个processing pipeline的任务。
如图所示:

(3)filter-like element
一个既可以接收数据又可以生成数据的element被称为filter-like element。比如分离器、解码器和音量等元素都属于此类别
控制器类中也存在此类设备。对于具有类似滤波功能的element来说,在其左侧配置有sink_pad,在右侧则配置有src_pad。该element通过从sink_pad读取数据并进行处理后,在src_pad生成新的数据。如下图所示

(4)pipeline 连接element
当元素数量较多时,在数据传输路径上对这些元素进行串联是必要的操作。按照数据传输路径对这些元素进行串联后发现源端口仅能连接到目标端口从而实现预期的功能

(5)helloWorld示例
从videotestsrc为源,到autovideosink

gst-launch-1.0 videotestsrc ! autovideosink

设置宽和高:gst-launch-1.0 videotestsrc ! 'video/x-raw,width=1280' ! autovideosink

查看格式和属性:gst-inspect-1.0 videotestsrc

gst-launch-version videotestsrc directly connects to a video/x-raw source with width 1280, height 720, and I420 format through a direct connection to an autovideosink device sink.

(6)python使用
启动docker:

启动jupyter

将依赖加入环境:

创建管道

创建element

加入管道并链接


3.GStreamer RTP和RTSP
(1)RTP(传输层)
Real-Time Transport Protocol(简称RTP)被定义为其全称。
在IP网络上,
RTP通过提供端到端的服务实现了语音、图像以及传真等多媒体数据的实时传输需求。
该协议不仅在互联网上传输媒体文件时延一致,
并且能够保持各部分数据的有效同步。
然而,
在实际应用中并不能保证整体网络服务质量;
相关质量控制功能则由另一个协议——RTCP来进行监控。
GStreamer Windows安装
https://gstreamer.freedesktop.org/download/

避坑:安装目录不要有中文和空格,选择完整安装
避坑:一定要选择运行版安装,不要选开发版
然后,将路径加入环境变量
(2)RTP:Server UDP
jetson nano:作为服务器端,发送数据
IP:192.168.2.9
gst-launch-1.0 videotestsrc启动gstreamer流程;设置流状态为实时;随后依次执行jpegenc编码;将编码后的数据传输至rtpjpegpay转换;再经udpsink发送到远程服务器;参数设置中指定本地主机IP地址为192.168.2.7;指定本地主机TCP/IP端口为5004;其中host变量标识客户端设备地址
(3)RTP:Client UDP
Window10 录屏台式机:客户端(接收数据)
IP:192.168.2.7
启动Gstreamer组件并配置输入源为UDP端口5004!引入带有JPEG编码的RTP数据流!解码RTP JPEG数据!解压JPEG图像块!连接至自动视频输出设备

(4)RTP:Server TCP
Lauching the program gst-launch-1.0 with parameters: videotestsrc is-live=true, followed by a series of encoders and decoders connected in sequence via pipes
(5)RTP:Client TCP
启动GStreamer媒体流编址程序并配置本地地址为192.168.2.9、端口4953以及应用层RTP-流数据包(应用层RTP/JPEG编码格式)。随后依次解码RTP流数据包、应用层RTP-JPEG数据包以及进行JPEG解压缩,并将结果发送至自动视频输出设备。

RTP包封装

(6)matroskamux 混合器模式
Service:gst-launch-1.0 video test source is live streaming jpeg encoder matroska encoder tcp server sink host=192.168.2.9 port=4953
Client :(主动连服务器)
启动Gstreamer 1.0,并配置 TCP 客户端连接到主机 IP 地址 192.168.2.9 和指定端口4953;随后依次连接矩阵 Multiplexing 组件、JPEG 解码器以及自动视频 sink。
(7)H264编码(最常用)
CPU编码
服务器端
gst-launch-1.0 -v videotestsrc ! 'video/x-raw,width=(int)1280, height=(int)720, framerate=20/1' !
videoscale ! videoconvert ! x264enc tune=zerolatency
bitrate=2048 speed-preset=superfast ! rtph264pay
config-interval=1 pt=96 ! udpsink host=192.168.2.7
port=5004
客户端 (windows 平台下是 ” , Linux 下是 ’ )
gst-launch-1.0 -v udpsrc port=5004 caps =
RTSP 格式,视频媒体类型,...
payload=(int)96 " ! rtph264depay ! decodebin !
videoconvert ! autovideosink sync=false

硬件编码:
服务器端
运行gst-launch-1.0并启用-v选项以指定输入源'...'. 配置输入源文件为'video/x-raw,format=(string)NV12,width=(int)320,height=(int)180,f'.
ramerate=20/1' ! nvvidconv ! nvv4l2h264enc !
h264parse ! rtph264pay config-interval=1 pt=96 !
udpsink host=192.168.2.7 port=5004
客户端可以与上面的相同
4.实时流传输协议(Real Time Streaming Protocol,RTSP)
主要由服务器端生成图片或视频并发送至客户端。该系统不具备pause等交互控制功能。类似于优酷这样的在线视频平台提供实时流媒体服务。通过客户端的媒体播放器进行观看,并对内容进行基本的控制操作。
实时流传输协议(Real-Time Streaming Protocol, RTSP)作为TCP/IP协议体系中的一个应用层协议,在1998年由美国哥伦比亚大学、网景网络公司以及RealNetworks三家公司共同提出并作为IETF RFC标准进行规范。该协议通过规范了单播式的通信机制,在媒体服务器与客户端之间实现了高效的数据流传输
该应用如何高效地通过IP网络传送多媒体数据?RTSP建立在RTP和RTCP基础之上,并基于TCP或UDP协议负责传输多媒体数据。
(1)启动deepstream python的docker
Docker exec -it --remove-terminals --network=host --runtime=nvidia环境变量设置为DISPLAY映射文件夹:/tmp/argus_socket:/tmp/argus_socket并配置版本信息为715a93f1d755 -e DISPLAY=DISPLAY -v ~/GStreamer:/opt/nvidia/deepstream/deepstream-6.0/sources/deepstream_python_apps/apps/GStreamer 715a93f1d755 -v /tmp/argus_socket:/tmp/argus_socket --device=/dev/video0 apps/G斯特拉mer 715a93f1d755
RTSP 示例
import gi
gi.require_version('Gst','1.0')
gi.require_version('GstRtspServer','1.0')
from gi.repository import Gst, GObject, GstRtspServer
Gst.init(None)
mainloop = GObject.MainLoop() # 产生循环
server = GstRtspServer.RTSPServer() # 服务
factory = GstRtspServer.RTSPMediaFactory() # 工程产生管道
factory.set_launch(
' ( videotestsrc is-live=1 '
'! video/x-raw,format=(string)NV12,width=(int)320,height=(int)180,framerate=20/1 '
'! nvvidconv ! nvv4l2h264enc ! h264parse ! rtph264pay name=pay0 bitrate=40000 pt=96 ) '
)
# allow multiple connections
factory.set_shared(True) # 设置共享,可以多个连接
mounts = server.get_mount_points() # 产生挂载点
mounts.add_factory('/live', factory) # 工程挂载上去
print('rtsp://192.168.2.9:8554/live')
server.attach(None)
mainloop.run()
AI助手
服务器运行上述python代码,产生了地址

启动客户端 EasyPlayer-RTSP,下载地址:
https://github.com/tsingsee/EasyPlayer-RTSP
rtsp://192.168.2.9:8554/live

连接

import gi
gi.require_version('Gst','1.0')
gi.require_version('GstRtspServer','1.0')
from gi.repository import Gst, GObject, GstRtspServer
Gst.init(None)
mainloop = GObject.MainLoop()
server = GstRtspServer.RTSPServer()
factory = GstRtspServer.RTSPMediaFactory()
factory.set_launch(
' ( nvarguscamerasrc ' # 内存运到显存
'! video/x-raw(memory:NVMM),width=(int)1280,height=(int)720,format=(string)NV12,framerate=(fraction)30/1 '
'! nvv4l2h264enc ! h264parse ! rtph264pay name=pay0 bitrate=40000 pt=96 ) '
)
# allow multiple connections
factory.set_shared(True)
mounts = server.get_mount_points()
mounts.add_factory('/live', factory)
print('rtsp://192.168.2.9:8554/live')
server.attach(None)
mainloop.run()
AI助手
摄像头输出格式

摄像头的数据输出格式一般分为RAW RGB和非raw RGB格式。
Raw RGB是Sensor每个感光点感应到的RGB数值。
Raw RGB经过ISP的处理还原出三原色,输出YUV或者RGB格式。
其中,YUV 也是一种颜色编码方案:与 RGB 编码方案类似。具体而言,“Y”表示亮度值(Luminance),即为亮度值(Luma),U 和 V 则分别代表色度(Chrominance)信息中的两个分量。这些分量用于表示图像的颜色信息及其饱和程度,并根据这些参数来指定像素的颜色信息
YUV格式好处:
无需 UV 信息即可完整显示图像,从而实现了彩色电视与黑白电视的兼容性.
减少颜色通道采样率对于不会显著影响图像质量而言,减少了在视频信号传输中所需的带宽需求。
**YUV 数据格式有哪些:**YU12、I420、YV12、**NV12 、**NV21、YUV420P、YUV420SP、
YUV422P 、 YUV444P
nvarguscamerasrc 插件:

nvv4l2h264enc插件:

(memory:NVMM)表示GPU运算
nvvidconv 插件:主要做内存交换、格式转换,输入可以是内存,可以是显存


5.python实现RTP和RTSP
当遇到无法生成XXX插件的情况以及gstreamer无法创建Element元素时,请及时删除缓存文件
rm -rf ~/.cache/gstreamer-1.0/ (在home/.cache目录下)
首先,回顾之前的脚本:
摄像头RTP客户端Windows:
gst-launch-1.0 udpsrc port=5004 name=pay0 buffer-size=524288
caps="application/x-rtp, media=video, clock-rate=90000,
encoding-name=(string)H264, payload=96 " ! rtph264depay !
h264parse ! nvh264dec ! videoconvert ! autovideosink -e
AI助手
摄像头 RTP 服务端 Jetson nano Linux:
gst-launch-1.0 -v nvarguscamerasrc bufapi-version=1 ! 'video/xraw(memory:NVMM),width=(int)1280,height=(int)720,format=(stri
ng)NV12,framerate=(fraction)30/1' ! nvv4l2h264enc presetlevel=1 insert-sps-pps=1 bufapi-version=1 ! h264parse !
rtph264pay pt=96 ! udpsink host=192.168.2.7 port=5004
async=False sync=1
AI助手
启动docker:
在宿主机上执行,避免无法获取到图形界面的一些问题,
715a93f1d755是ImageId 改为你自己的,注意GStreamer目录映
射
docker run -it --rm --net=host --runtime nvidia -e
DISPLAY=$DISPLAY -v /tmp/argus_socket:/tmp/argus_socket -- device /dev/video0 -v
~/GStreamer:/opt/nvidia/deepstream/deepstream- 6.0/sources/deepstream_python_apps/apps/GStreamer
715a93f1d755
AI助手

运行python代码,使用客户端连接即可连接摄像头

python代码
import sys
sys.path.append('../')
import gi
gi.require_version('Gst', '1.0')
from gi.repository import GObject, Gst
from common.bus_call import bus_call
# 本程序等价于 下面的脚本, 自动使用时注意把192.168.2.7改为自己的客户端IP
# gst-launch-1.0 -v nvarguscamerasrc
# ! 'video/x-raw(memory:NVMM),width=(int)1280,height=(int)720,format=(string)NV12,framerate=(fraction)30/1'
# ! nvv4l2h264enc ! h264parse ! rtph264pay pt=96
# ! udpsink host=192.168.2.7 port=5004
Gst.init(None)
pipeline = Gst.Pipeline()
camerasrc = Gst.ElementFactory.make("nvarguscamerasrc", "nv-arguscamerasrc") # 创建element
caps = Gst.ElementFactory.make("capsfilter", "filter") # 格式
caps.set_property("caps", Gst.Caps.from_string("video/x-raw(memory:NVMM),width=(int)1280,height=(int)720,format=(string)NV12,framerate=(fraction)30/1"))
encoder = Gst.ElementFactory.make("nvv4l2h264enc", "encoder") # 创建编码器
h264parse = Gst.ElementFactory.make("h264parse", "h264parse")
rtppay = Gst.ElementFactory.make("rtph264pay", "rtppay")
sink = Gst.ElementFactory.make("udpsink", "udpsink")
camerasrc.set_property('bufapi-version', 1)
encoder.set_property('preset-level', 1)
encoder.set_property('insert-sps-pps', 1)
encoder.set_property('bufapi-version', 1)
rtppay.set_property("pt", 96)
sink.set_property('host', '192.168.2.7')
sink.set_property('port', 5004)
sink.set_property('async', False)
sink.set_property('sync', 1)
pipeline.add(camerasrc ) # 加入到管道中
pipeline.add(caps)
pipeline.add(encoder)
pipeline.add(h264parse)
pipeline.add(rtppay)
pipeline.add(sink)
camerasrc.link(caps) # 连接起来
caps.link(encoder)
encoder.link(h264parse)
h264parse.link(rtppay)
rtppay.link(sink)
loop = GObject.MainLoop() # 循环
bus = pipeline.get_bus() # 总线
bus.add_signal_watch() # 信号连接器
bus.connect("message", bus_call, loop)
pipeline.set_state(Gst.State.PLAYING)
try:
loop.run()
except:
pass
pipeline.set_state(Gst.State.NULL)
# 摄像头RTP客户端Windows
# gst-launch-1.0 udpsrc port=5004 name=pay0 buffer-size=524288 caps="application/x-rtp, media=video, clock-rate=90000, encoding-name=(string)H264, payload=96 " ! rtph264depay ! h264parse ! nvh264dec ! videoconvert ! autovideosink -e
AI助手
python 实现rtsp
import sys
sys.path.append('../')
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstRtspServer', '1.0') # 注册一个rtsp server
from gi.repository import GObject, Gst, GstRtspServer
from common.bus_call import bus_call
GObject.threads_init()
Gst.init(None)
pipeline = Gst.Pipeline()
camerasrc = Gst.ElementFactory.make("nvarguscamerasrc", "nv-arguscamerasrc")
caps = Gst.ElementFactory.make("capsfilter", "filter")
caps.set_property("caps", Gst.Caps.from_string("video/x-raw(memory:NVMM),width=(int)1280,height=(int)720,format=(string)NV12,framerate=(fraction)30/1"))
encoder = Gst.ElementFactory.make("nvv4l2h264enc", "encoder")
h264parse = Gst.ElementFactory.make("h264parse", "h264parse")
rtppay = Gst.ElementFactory.make("rtph264pay", "rtppay")
sink = Gst.ElementFactory.make("udpsink", "udpsink")
camerasrc.set_property('bufapi-version', 1)
encoder.set_property('preset-level', 1)
encoder.set_property('insert-sps-pps', 1)
encoder.set_property('bufapi-version', 1)
rtppay.set_property("pt", 96)
sink.set_property('host', '192.168.2.9') # 本机IP
sink.set_property('port', 5004)
sink.set_property('async', False)
sink.set_property('sync', 1)
pipeline.add(camerasrc )
pipeline.add(caps)
pipeline.add(encoder)
pipeline.add(h264parse)
pipeline.add(rtppay)
pipeline.add(sink)
camerasrc .link(caps)
caps.link(encoder)
encoder.link(h264parse)
h264parse.link(rtppay)
rtppay.link(sink)
server = GstRtspServer.RTSPServer.new() # 产生一个设置实例
server.props.service = "%d" % 8554 # 整型,设置端口号
server.attach(None)
factory = GstRtspServer.RTSPMediaFactory.new() # 产生工厂,提供多媒体数据
factory.set_launch(
"( udpsrc name=pay0 port=%d buffer-size=524288 caps=\"application/x-rtp, media=video, clock-rate=90000, encoding-name=(string)H264, payload=96 \" )" % (
5004))
factory.set_shared(True) # 共享
server.get_mount_points().add_factory("/live", factory) # 挂载
loop = GObject.MainLoop()
bus = pipeline.get_bus()
bus.add_signal_watch()
bus.connect("message", bus_call, loop)
pipeline.set_state(Gst.State.PLAYING)
print("rtsp://192.168.2.9:8554/live")
try:
loop.run()
except:
pass
pipeline.set_state(Gst.State.NULL)
AI助手
6.deepstream推理
数据流组件图:
nvarguscamerasrc->capsfilter-> nvstreammux->nvinfer->
nvvideoconvert ->nvdsosd--> nvvideoconvert -> capsfilter-
nvv4l2h264enc ->h264parse->rtph264pay->udpsink
nvarguscamerasrc->capsfilter:从相机获得数据
nvstreammux插件:合并多个数据源 ,组成一个新的数据

nvinfer 插件(核心插件):导入指定模型文件并执行推理操作,并将推理结果记录至元数据字段
nvdsosd 功能说明:该插件将元数据输出至图像中。具体而言,则是以 RGB 格式为基础添加透明度转换为 RGBA 格式。其中 RGBA 格式的定义包括 RGB、BGR、BGRA、RGBx、ARGB 和 BGRx 等其他类型。




deepstream 环境中才有 gst-inspect-1.0 nvdsosd
查询不到一样删除一些缓存rm -rf ~/.cache/gstreamer-1.0

运行:

python代码
import sys
sys.path.append('../')
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstRtspServer', '1.0')
from gi.repository import GObject, Gst, GstRtspServer
from common.bus_call import bus_call
GObject.threads_init()
Gst.init(None)
pipeline = Gst.Pipeline()
camerasrc = Gst.ElementFactory.make("nvarguscamerasrc", "nv-arguscamerasrc")
caps = Gst.ElementFactory.make("capsfilter", "filter")
caps.set_property("caps", Gst.Caps.from_string("video/x-raw(memory:NVMM),width=(int)1280,height=(int)720,format=(string)NV12,framerate=(fraction)30/1"))
# Create nvstreammux instance to form batches from one or more sources.
streammux = Gst.ElementFactory.make("nvstreammux", "Stream-muxer")
streammux.set_property('width', 1280)
streammux.set_property('height', 720)
streammux.set_property('batch-size', 1)
streammux.set_property('batched-push-timeout', 4000000)
# Use nvinfer to run inferencing on decoder's output,
# behaviour of inferencing is set through config file
pgie = Gst.ElementFactory.make("nvinfer", "primary-inference") # 主推理
pgie.set_property('config-file-path', "pgie_yolov4_tiny_tao_config.txt") # 设置配置文件
# Use convertor to convert from NV12 to RGBA as required by nvosd
nvvidconv = Gst.ElementFactory.make("nvvideoconvert", "convertor") # 转换
# Create OSD to draw on the converted RGBA buffer
nvosd = Gst.ElementFactory.make("nvdsosd", "onscreendisplay") # 元数据写入图片
nvvidconv_postosd = Gst.ElementFactory.make("nvvideoconvert", "convertor_postosd") # 转换回来
# Create a caps filter
caps_postosd = Gst.ElementFactory.make("capsfilter", "caps_postosd_filter")
caps_postosd.set_property("caps", Gst.Caps.from_string("video/x-raw(memory:NVMM), format=I420"))
encoder = Gst.ElementFactory.make("nvv4l2h264enc", "encoder")
h264parse = Gst.ElementFactory.make("h264parse", "h264parse")
rtppay = Gst.ElementFactory.make("rtph264pay", "rtppay")
sink = Gst.ElementFactory.make("udpsink", "udpsink")
camerasrc.set_property('bufapi-version', 1)
encoder.set_property('preset-level', 1)
encoder.set_property('insert-sps-pps', 1)
encoder.set_property('bufapi-version', 1)
rtppay.set_property("pt", 96)
sink.set_property('host', '192.168.2.9') # 本机IP
sink.set_property('port', 5004)
sink.set_property('async', False)
sink.set_property('sync', 1)
pipeline.add(camerasrc)
pipeline.add(caps)
# 新增
pipeline.add(streammux)
pipeline.add(pgie)
pipeline.add(nvvidconv)
pipeline.add(nvosd)
pipeline.add(nvvidconv_postosd)
pipeline.add(caps_postosd)
pipeline.add(encoder)
pipeline.add(h264parse)
pipeline.add(rtppay)
pipeline.add(sink)
sinkpad = streammux.get_request_pad("sink_0") # 可以有多个数据源,选择一个数据源
srcpad = caps.get_static_pad("src") # 获取src源
camerasrc .link(caps)
srcpad.link(sinkpad)
streammux.link(pgie)
pgie.link(nvvidconv)
nvvidconv.link(nvosd)
nvosd.link(nvvidconv_postosd)
nvvidconv_postosd.link(caps_postosd)
caps_postosd.link(encoder)
encoder.link(h264parse)
h264parse.link(rtppay)
rtppay.link(sink)
server = GstRtspServer.RTSPServer.new()
server.props.service = "%d" % 8554
server.attach(None)
factory = GstRtspServer.RTSPMediaFactory.new()
factory.set_launch(
"( udpsrc name=pay0 port=%d buffer-size=524288 caps=\"application/x-rtp, media=video, clock-rate=90000, encoding-name=(string)H264, payload=96 \" )" % (
5004))
factory.set_shared(True)
server.get_mount_points().add_factory("/live", factory)
loop = GObject.MainLoop()
bus = pipeline.get_bus()
bus.add_signal_watch()
bus.connect("message", bus_call, loop)
pipeline.set_state(Gst.State.PLAYING)
print("rtsp://192.168.2.9:8554/live")
try:
loop.run()
except:
pass
pipeline.set_state(Gst.State.NULL)
AI助手
配置文件:
# Following properties are mandatory when engine files are not specified:
# int8-calib-file(Only in INT8)
# Caffemodel mandatory properties: model-file, proto-file, output-blob-names
#
# Mandatory properties for detectors:
# num-detected-classes
#
# Following properties are always recommended:
# batch-size(Default=1)
#
# Other optional properties:
# net-scale-factor(Default=1), network-mode(Default=0 i.e FP32),
# model-color-format(Default=0 i.e. RGB) model-engine-file, labelfile-path,
# mean-file, gie-unique-id(Default=0), offsets, process-mode (Default=1 i.e. primary),
# custom-lib-path, network-mode(Default=0 i.e FP32)
#
# The values in the config file are overridden by values set through GObject
# properties.
# Gst-nvinfer 插件根据网络要求对输入帧执行转换(格式转换和缩放),并将转换后的数据传递给低级库。
# 低级库对转换后的帧进行预处理(执行归一化和均值减法)并生成最终的浮点 RGB/BGR/GRAY 平面数据,该数据传递给 TensorRT 引擎进行推理。低级库生成的输出类型取决于网络类型
# y=net-scale-factor*(x-mean)
[property]
# 多个GPU的情况下,元件所使用的GPU设备ID
gpu-id=0
# 低级库对转换后的帧进行预处理(执行归一化和均值减法)并生成最终的浮点 RGB/BGR/GRAY 平面数据,该数据传递给 TensorRT 引擎进行推理。低级库生成的输出类型取决于网络类型
# y=net-scale-factor*(x-mean)
net-scale-factor=0.0039215697906911373
# caffe 模型文件路径
model-file=../../../../samples/models/Primary_Detector/resnet10.caffemodel
proto-file=../../../../samples/models/Primary_Detector/resnet10.prototxt
# 模型预先生成的序列化引擎文件的绝对路径,如果有这个就不在看 model文件
model-engine-file=../../../../samples/models/Primary_Detector/resnet10.caffemodel_b1_gpu0_int8.engine
labelfile-path=../../../../samples/models/Primary_Detector/labels.txt
# 当模型降低到8位时,验证的库
int8-calib-file=../../../../samples/models/Primary_Detector/cal_trt.bin
force-implicit-batch-dim=1
batch-size=1
# Integer
# 0: FP32
# 1: INT8
# 2: FP16
network-mode=1
num-detected-classes=4 # 目标检测类别
# 推理时要跳过的连续批数
interval=0
# 要分配给 nvinfer 实例的唯一组件 ID。用于标识由实例生成的元数据
gie-unique-id=1
# 输出检测内容的元数据名字
output-blob-names=conv2d_bbox;conv2d_cov/Sigmoid
[class-attrs-all]
# 目标检测阈值
pre-cluster-threshold=0.2
# DBSCAN algorithm 聚和算法参数
eps=0.2
# 矩形合并的阈值
group-threshold=1
AI助手
7.deepstream集成yolov4
该系统采用深度流技术和Tao训练引擎的整合方案进行深度学习模型的集成。
下载 6.01 版本


(1)安装集成步骤
第一、替换libnvinfer_plugin.so文件
第二、把tao导出的模型和配置文件下载到jetson nano
第三、修改配置 和 编译配置依赖的so 文件
第四、上传文件运行
设置CUDA:
export CUDA_HOME=/usr/local/cuda
export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64/:$LD_LIBRARY_PATH
AI助手
将上面CUDA放到bashrc

(2)查看系统几个核心组件版本
查看jetpack版本:sudo apt-cache show nvidia-jetpack

查看cuda版本
nvcc -V

查看tensorrt版本: dpkg -l | grep TensorRT

需要单独下载这个文件,下载压缩包最终只有一个链接文件

请按照指定的文件路径完成安装于宿主机环境中的相应软件组件。
sudo mv /usr/lib/aarch64-linux-gnu/libnvinfer_plugin.so.8.x.y ${HOME}/libnvinfer_plugin.so.8.x.y.bak // backup original libnvinfer_plugin.so.x.y
sudo cp $TRT_SOURCE/build/libnvinfer_plugin.so.8.m.n /usr/lib/aarch64-linux-gnu/libnvinfer_plugin.so.8.x.y
sudo ldconfig
AI助手

(3)拉取TAO训练的模型和配置文件
放到目录/GStreamer/


修改配置文件,

(4)修改配置 和 编译配置依赖的so文件
将下载的tao_app放到/GStreamer/,并编译processor
进入docker:
docker run -it --rm --net=host --runtime nvidia -e
DISPLAY=$DISPLAY -v /tmp/argus_socket:/tmp/argus_socket -- device /dev/video0 -v
~/GStreamer:/opt/nvidia/deepstream/deepstream- 6.0/sources/deepstream_python_apps/apps/GStreamer
715a93f1d755
AI助手
nvdsinfer_custombboxparser_tao.cpp编译
export CUDA_VER=10.2
make


最终配置文件:
nvinfer_config
net-scale-factor=1.0
offsets=103.939;116.779;123.68
infer-dims=3;384;1248
tlt-model-key=NDZsYWZyODZpMWZmNXNkcHFpNnI3djBnNjk6M2ZkMWJlNGQtOTI1Yi00MWYzLTk2NDgtYWEwYzEwODFiNmJm
network-type=0
num-detected-classes=1
model-color-format=1
maintain-aspect-ratio=0
output-tensor-meta=0
AI助手
[property]
gpu-id=0
net-scale-factor=1.0
offsets=103.939;116.779;123.68
model-color-format=1
labelfile-path=./export/labels.txt
model-engine-file=./export/trt.engine
#int8-calib-file=../../models/yolov4-tiny/cal.bin
tlt-encoded-model=./export/yolov4_cspdarknet_tiny_epoch_080.etlt
tlt-model-key=NDZsYWZyODZpMWZmNXNkcHFpNnI3djBnNjk6M2ZkMWJlNGQtOTI1Yi00MWYzLTk2NDgtYWEwYzEwODFiNmJm
infer-dims=3;384;1248
maintain-aspect-ratio=0
uff-input-order=0
uff-input-blob-name=Input
batch-size=1
## 0=FP32, 1=INT8, 2=FP16 mode
network-mode=1
num-detected-classes=1
interval=0
gie-unique-id=1
is-classifier=0
#network-type=0
cluster-mode=3
output-blob-names=BatchedNMS
parse-bbox-func-name=NvDsInferParseCustomBatchedNMSTLT
custom-lib-path=./export/libnvds_infercustomparser_tao.so
[class-attrs-all]
pre-cluster-threshold=0.3
roi-top-offset=0
roi-bottom-offset=0
detected-min-w=0
detected-min-h=0
detected-max-w=0
detected-max-h=0
AI助手
(4)运行自己的模型在deepstream中
清空缓存:
rm -rf ~/.cache/gstreamer-1.0/
AI助手
进入对应的docker文件
cd /opt/nvidia/deepstream/deepstream-6.0/sources/deepstream_python_apps/a
pps/GStreamer
AI助手
运行以下python文件
import sys
sys.path.append('../')
import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstRtspServer', '1.0')
from gi.repository import GObject, Gst, GstRtspServer
from common.bus_call import bus_call
GObject.threads_init()
Gst.init(None)
pipeline = Gst.Pipeline()
camerasrc = Gst.ElementFactory.make("nvarguscamerasrc", "nv-arguscamerasrc")
caps = Gst.ElementFactory.make("capsfilter", "filter")
caps.set_property("caps", Gst.Caps.from_string("video/x-raw(memory:NVMM),width=(int)1280,height=(int)720,format=(string)NV12,framerate=(fraction)30/1"))
# Create nvstreammux instance to form batches from one or more sources.
streammux = Gst.ElementFactory.make("nvstreammux", "Stream-muxer")
streammux.set_property('width', 1280)
streammux.set_property('height', 720)
streammux.set_property('batch-size', 1)
streammux.set_property('batched-push-timeout', 4000000)
# Use nvinfer to run inferencing on decoder's output,
# behaviour of inferencing is set through config file
pgie = Gst.ElementFactory.make("nvinfer", "primary-inference") # 主推理
pgie.set_property('config-file-path', "pgie_yolov4_tiny_tao_config.txt") # 设置配置文件
# Use convertor to convert from NV12 to RGBA as required by nvosd
nvvidconv = Gst.ElementFactory.make("nvvideoconvert", "convertor") # 转换
# Create OSD to draw on the converted RGBA buffer
nvosd = Gst.ElementFactory.make("nvdsosd", "onscreendisplay") # 元数据写入图片
nvvidconv_postosd = Gst.ElementFactory.make("nvvideoconvert", "convertor_postosd") # 转换回来
# Create a caps filter
caps_postosd = Gst.ElementFactory.make("capsfilter", "caps_postosd_filter")
caps_postosd.set_property("caps", Gst.Caps.from_string("video/x-raw(memory:NVMM), format=I420"))
encoder = Gst.ElementFactory.make("nvv4l2h264enc", "encoder")
h264parse = Gst.ElementFactory.make("h264parse", "h264parse")
rtppay = Gst.ElementFactory.make("rtph264pay", "rtppay")
sink = Gst.ElementFactory.make("udpsink", "udpsink")
camerasrc.set_property('bufapi-version', 1)
encoder.set_property('preset-level', 1)
encoder.set_property('insert-sps-pps', 1)
encoder.set_property('bufapi-version', 1)
rtppay.set_property("pt", 96)
sink.set_property('host', '192.168.2.9') # 本机IP
sink.set_property('port', 5004)
sink.set_property('async', False)
sink.set_property('sync', 1)
pipeline.add(camerasrc)
pipeline.add(caps)
# 新增
pipeline.add(streammux)
pipeline.add(pgie)
pipeline.add(nvvidconv)
pipeline.add(nvosd)
pipeline.add(nvvidconv_postosd)
pipeline.add(caps_postosd)
pipeline.add(encoder)
pipeline.add(h264parse)
pipeline.add(rtppay)
pipeline.add(sink)
sinkpad = streammux.get_request_pad("sink_0") # 可以有多个数据源,选择一个数据源
srcpad = caps.get_static_pad("src") # 获取src源
camerasrc .link(caps)
srcpad.link(sinkpad)
streammux.link(pgie)
pgie.link(nvvidconv)
nvvidconv.link(nvosd)
nvosd.link(nvvidconv_postosd)
nvvidconv_postosd.link(caps_postosd)
caps_postosd.link(encoder)
encoder.link(h264parse)
h264parse.link(rtppay)
rtppay.link(sink)
server = GstRtspServer.RTSPServer.new()
server.props.service = "%d" % 8554
server.attach(None)
factory = GstRtspServer.RTSPMediaFactory.new()
factory.set_launch(
"( udpsrc name=pay0 port=%d buffer-size=524288 caps=\"application/x-rtp, media=video, clock-rate=90000, encoding-name=(string)H264, payload=96 \" )" % (
5004))
factory.set_shared(True)
server.get_mount_points().add_factory("/live", factory)
loop = GObject.MainLoop()
bus = pipeline.get_bus()
bus.add_signal_watch()
bus.connect("message", bus_call, loop)
pipeline.set_state(Gst.State.PLAYING)
print("rtsp://192.168.2.9:8554/live")
try:
loop.run()
except:
pass
pipeline.set_state(Gst.State.NULL)
AI助手
将生成的引擎文件再配置回来


链接:https://pan.baidu.com/s/12nhoFcZWLD1_ticGprawUg?pwd=iujk
提取码:iujk
