嘿!您似乎在 United States,您想使用我们的 English 网站吗?
Switch to English site
Skip to main content

NVIDIA Jetson Nano應用-安裝Deep Stream SDK與執行深度影像串流範例

作者

張嘉鈞

難度

普通

材料表

Webcam X1

NVIDIA JetsonNano X1

DeepStream

現在是一個AI大世代,NVIDIA開發出DeepStream SDK讓任何人都能輕鬆快速地建立以 AI 為基礎的 GPU 加速應用程式,以進行影像分析。上述取自於NVIDIA原廠文章,除此之外我有專門寫一篇來講解比較細部的技術與特色:https://www.rs-online.com/designspark/nvidia-deepstream-cn

Jetson Nano 上安裝 DeepStream

首先,我們需要先安裝依賴套件:

$ sudo apt install \
libssl1.0.0 \
libgstreamer1.0-0 \
gstreamer1.0-tools \
gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly \
gstreamer1.0-libav \
libgstrtspserver-1.0-0 \
libjansson4=2.11-1 -y

安裝 librdkafka

下載函式庫

$ git clone https://github.com/edenhill/librdkafka.git

配置與建構 函式庫

$ cd librdkafka
$ git reset --hard 7101c2310341ab3f4675fc565f64f0967e135a6a
$ ./configure
$ make
$ sudo make install

複製 librdkafka 建置完的函式庫到DeepStream的資料夾中

$ sudo mkdir -p /opt/nvidia/deepstream/deepstream-5.0/lib
$ sudo cp /usr/local/lib/librdkafka* /opt/nvidia/deepstream/deepstream-5.0/lib

安裝完相依套件之後就可以安裝DeepStream SDK了,在這之前需要先確認一下自己的 JetPack 版本,因為DeepStream的版本也需要對應才能使用:

$ sudo apt-cache show nvidia-jetpack

0147_be16ec95a8668e8e7370f766ac767724c4930740.png

或者也可以只用 jetson_stats來查看 ( 需要額外安裝 )

$ jetson_release

0237_144592ba9d1a8b1cd023ca4c9a850276b9a96898.png

總之,只要確認自己使用的Jetpack版本之後,就可以找出對應使用的DeepStream版本,從Deep Stream的介紹文件中可以找到下方這張表格,我們的JetPack版本是4.4 對應到的是 DS 5.0, 5.0.1,如果是要使用 DS 5.1的話則需要升級成JetPack 32.5.1。

0340_dfe41edb7dcb029bfbbeb52927c567f7675b9e30.png

接著可以從下列的網址找到各版本的封存,如果你直接Google搜尋舊版本,NVIDIA都會導到最新的,所以一定要加上「Archived」,這邊我們選擇 DeepStream 5.0 的版本,並且下載壓縮檔:

0441_3bacbcd0e1647c7e6b7423f6069b4fd73acced1a.png

下載下來之後就可以將其解壓縮到根目錄

$ cd ~/Downloads
$ sudo tar -xvf deepstream_sdk_5.0_jetson.tbz2 -C /

進行安裝

$ cd /opt/nvidia/deepstream/deepstream-5.0/
$ sudo ./install.sh
$ sudo ldconfig

接著輸入下列指令確認是否安裝成功

$ deepstream-app --version-all

0538_a0fd4b521ef40e6d07925dcab7d7608e4bd6d8fa.png

只要有看到版本資訊就代表安裝成功了。

卸載DeepStream ( 補充 )

$ cd /opt/nvidia/deepstream/deepstream/
$ sudo vi uninstall.sh
set PREV_DS_VER=5.0
$ sudo chmod +x uninstall.sh
$ sudo ./uninstall.sh

0635_802f8d9637a4acc3042d5c79695cc91093bdbbf6.png

DeepStream App推論用的範例程式 (deepstream-app)

我們可以到下列路徑查看所有可以使用範例,基本上DeepStream的運行方式都會跟配置檔一起搭配使用,所以我們要稍微理解並分析一下配置檔的內容才行。

$ cd samples/configs/deepstream-app
$ ls

0740_ccb7ac64d30b0b2bb6c0cc0f373c44189d7c0a92.png

第一個範例程式 ( source1_usb_dec_infer_resnet_int8 )

運行第一個範例程式,從檔名就可以知道它是只有一個來源,是usb的device,進行的是inference並且執行的模型是resnet,資料型態是int8,不過這邊要提醒大家int8只能在Xavier上運作,Nano系列只能跑fp16,所以都需要rebuild 會耗費一些時間;要執行這些配置檔都需要透過deepstream-app這個指令來運行,在輸入檔名之前還需給予 -c 告訴程式這是配置檔。

$ deepstream-app -c source1_usb_dec_infer_resnet_int8.txt

這系列提供的範例模型僅能辨識「Car」、「Bicycle」、「Person」、「RoadSign」,所以我拿了手機提供台灣街景的畫面讓它進行分析,執行效果如下。

0827_3f8c498fb31f03a1fa8bc4ddf988710ebe3edc8f.jpg

0928_9d5de038efbe2bb7663d33078cde869488ee192a.jpg

接著來分析一下它的配置檔吧!一開始會先遇到的是 App的基本設定 ( application ),enable-perf-measurement是評估性能;perf-measurement-interval-sec採樣和顯示性能評估的時間間隔(以秒為單位);。

[application]
enable-perf-measurement=1
perf-measurement-interval-sec=5
#gie-kitti-output-dir=streamscl

接著是平行顯示 ( tiled-display ) 的設定,平行顯示這裡不確定翻譯的正不正確,你們可以想像是監視器畫面的概念,可以同時顯示多個畫面。

首先enable就是要不要開啟顯示的功能,rows跟columns用來控制顯示畫面的數量,width跟height則是整個畫面的大小。

[tiled-display]
enable=1
rows=1
columns=1
width=1280
height=720

再來是顯示畫面的來源 ( source ),type用來控制我們的來源:

1: Camera (V4L2)

2: URI

3: MultiURI

4: RTSP

5: Camera (CSI) (Jetson only)

我們這裡設定為USB攝影機所以選擇1,接下來就是一些基本的設定 fps-n是最大的fps數值d則是最小的,再來使用USB攝影機很重要的點就是dev-node要設定好,可以從輸入 ls /dev 去確認,通常名稱為 video*,*從0開始。

[source0]
enable=1
#Type - 1=CameraV4L2, 2=URI, 3=MultiURI, 4=RTSP, 5=CSI
type=1
camera-width=640
camera-height=480
camera-fps-n=30
camera-fps-d=1
camera-v4l2-dev-node=0

搞定了輸入就要來搞定輸出 ( sink ) ,Type有很多種可以選擇:

1: Fakesink 不進行輸出

2: EGL based windowed sink (nveglglessink) 使用一般的Ubuntu 視窗開起

3: Encode + File Save (encoder + muxer + filesink) 儲存成影片

4: Encode + RTSP streaming 使用RTSP串流方式輸出

5: Overlay (Jetson only) 強制覆蓋在畫面上

6: Message converter + Message broker

這邊可以看到我們使用的是Overlay,它會直接覆蓋在該螢幕最上層,所以如果你只有一個螢幕不建議這樣做。

sync則是輸出影片的是否要同步( 0:越快越好 1: 同步 )。

display-id跟overlay-id是只有在Overlay的時候才需要特別宣告的,display是顯示的螢幕;overlay-id是編號,一定要大於1才行。

source-id則是緩存區域的編號,會包在source的名稱當中,如果你有N個source* 跟sink*,你的source-id則要去搭配 * 的編號才行。

[sink0]
enable=1
#Type - 1=FakeSink 2=EglSink 3=File 4=RTSPStreaming 5=Overlay
type=5
sync=0
display-id=0
offset-x=0
offset-y=0
width=0
height=0
overlay-id=1
source-id=0

在介紹一下配置檔提供的另外兩種配置,第一個是輸出成檔案,這邊預設是先關閉的(enable=0),這邊註解的部分都有告訴使用者格是怎麼樣去選擇。

[sink1]
enable=0
type=3
#1=mp4 2=mkv
container=1
#1=h264 2=h265 3=mpeg4
codec=1
#encoder type 0=Hardware 1=Software
enc-type=0
sync=0
bitrate=2000000
#H264 Profile - 0=Baseline 2=Main 4=High
#H265 Profile - 0=Main 1=Main10
profile=0
output-file=out.mp4
source-id=0

而另一種配置則是輸出成網路串流 (RTSP),這是大部分業界會想要做到的功能,最主要需要設定的地方在rtsp-port端口,Windows上擷取rtsp的方法等等會再補充介紹。

[sink2]
enable=0
#Type - 1=FakeSink 2=EglSink 3=File 4=RTSPStreaming 5=Overlay
type=4
#1=h264 2=h265
codec=1
#encoder type 0=Hardware 1=Software
enc-type=0
sync=0
bitrate=4000000
#H264 Profile - 0=Baseline 2=Main 4=High
#H265 Profile - 0=Main 1=Main10
profile=0
# set below properties in case of RTSPStreaming
rtsp-port=8554
udp-port=5400

接著是處理我們在畫面中看到物件的邊界框以及標籤

[osd]
enable=1
border-width=2
text-size=15
text-color=1;1;1;1;
text-bg-color=0.3;0.3;0.3;1
font=Serif
show-clock=0
clock-x-offset=800
clock-y-offset=820
clock-text-size=12
clock-color=1;0;0;0

接下來是設定串流,live-source是宣告是否為即時影像,最後註解掉的attach-sys-ts-as-ntp則是決定時間的顯示是要顯示網路串流的時間還是DeepStream分析完的時間。

[streammux]
##Boolean property to inform muxer that sources are live
live-source=1
batch-size=1
##time out in usec, to wait after the first buffer is available
##to push the batch even if the complete batch is not formed
batched-push-timeout=40000
## Set muxer output width and height
width=1280
height=720
## If set to TRUE, system timestamp will be attached as ntp timestamp
## If set to FALSE, ntp timestamp from rtspsrc, if available, will be attached
# attach-sys-ts-as-ntp=1

最後是設定TensorRT引擎,快速講解TensorRT引擎是由NVIDIA提出的一個AI推論加速引擎,現有的NVIDIA相關工具都是把模型轉換成TensorRT以獲得更快的體驗,而DeepStream又有一個更好玩的功能,就是它會有主要運行的模型(primary-gie)以及多個次級模型(secondary-gie%d),不過在我們這個範例當中它只有運行主要的GIE,首先要先宣告引擎的路徑 (model-engine-file);接著是要宣告bbox的顏色;接著是interval這個參數代表的是每一次會有幾個批次的資料不被推論,或許是要降低負擔才有這個參數,不過這邊只有一個引擎所以設定0全部的幀都進行推論;gie-unique-id則是GIE的編號;config-file是模型的配置檔,如果有客製化模型的需求也需要去修改這個檔案。

# config-file property is mandatory for any gie section.
# Other properties are optional and if set will override the properties set in
# the infer config file.
[primary-gie]
enable=1
model-engine-file=../../models/Primary_Detector/resnet10.caffemodel_b30_gpu0_int8.engine
#Required to display the PGIE labels, should be added even when using config-file
#property
batch-size=1
#Required by the app for OSD, not a plugin property
bbox-border-color0=1;0;0;1
bbox-border-color1=0;1;1;1
bbox-border-color2=0;0;1;1
bbox-border-color3=0;1;0;1
interval=0
#Required by the app for SGIE, when used along with config-file property
gie-unique-id=1
config-file=config_infer_primary.txt

到這邊,第一個範例程式的配置檔終於結束了。

第二個範例程式 (source8_1080p_dec_infer-resnet_tracker_tiled_display_fp16_nano.txt)

這個範例主要在示範8個來源怎麼設定平行顯示,並且添加了tracker的功能,可以追蹤辨識到的物件,那這邊我們介紹配置檔的同時也會稍微修改內容。

平行顯示最主要要設定的就在 tiled-display,我們需要把rows跟columns設定成4跟2代表著有4列2行,總共可以放8個畫面。

[tiled-display]
enable=1
rows=4
columns=2
width=1280
height=720

再來不同的地方就是來源 ( source ),這邊選擇的是MultiURI,可以讓多個顯示器都輸出同一個影片,這個型態需要宣告的是 num-sources 告訴DS總共要同時輸入幾個來源,gpu-id如果有多個GPU的話可以額外設定,cudadec-memtype則是分配CUDA內存的儲存類型。

[source0]
enable=1
#Type - 1=CameraV4L2 2=URI 3=MultiURI 4=RTSP
type=3
uri=file://../../streams/sample_1080p_h264.mp4
num-sources=8
#drop-frame-interval=2
gpu-id=0
# (0): memtype_device   - Memory type Device
# (1): memtype_pinned   - Memory type Host Pinned
# (2): memtype_unified  - Memory type Unified
cudadec-memtype=0 cudadec-memtype=0

處理好來源接著就是輸出了,這邊要補充下列這段,並且把原本的sink0的enable改為0。

[sink3]
enable=1
#Type - 1=FakeSink 2=EglSink 3=File
type=2
sync=1
source-id=0
gpu-id=0
nvbuf-memory-type=0

原本是使用Overlay,但是我實測過使用Overlay,就無法做到點擊單一來源顯示的效果,建議這邊先改成EglSink,只要是EglSink就可以偵測你滑鼠點擊的位置知道你現在要著重觀看哪一個source,並且原本平行輸出的畫面是沒有標籤等文字訊息的,點進去那些文字訊息就會跑出來。

接著就要講到tracker的部分了,這邊比較特別的地方是如果要使用tracker需要把寬高設定成32的倍數;ll-lib-file函式庫的路徑;ll-config-file配置檔的路徑;enable-batch-process開啟批次處理。

[tracker]
enable=1
# For the case of NvDCF tracker, tracker-width and tracker-height must be a multiple of 32, respectively
tracker-width=640
tracker-height=384
#ll-lib-file=/opt/nvidia/deepstream/deepstream-5.0/lib/libnvds_mot_iou.so
#ll-lib-file=/opt/nvidia/deepstream/deepstream-5.0/lib/libnvds_nvdcf.so
ll-lib-file=/opt/nvidia/deepstream/deepstream-5.0/lib/libnvds_mot_klt.so
#ll-config-file required for DCF/IOU only
#ll-config-file=tracker_config.yml
#ll-config-file=iou_config.txt
gpu-id=0
#enable-batch-process and enable-past-frame applicable to DCF only
enable-batch-process=1
enable-past-frame=0
display-tracking-id=1

關於tracker的選擇,在原廠網站的文件中可以找到相關資訊,圖片如下

1163_82764cdeaf505a9dc088526f9f871bad7b250a2d.png

圖片來源: https://docs.nvidia.com/metropolis/deepstream/5.0DP/plugin-manual/

第三個範例程式 (source4_1080p_dec_infer-resnet_tracker_sgie_tiled_display_int8.txt)

1251_fe303eeb918a3fbb16359ed5924c2e9f9ab27b89.jpg

1348_1230b740216361d33ffba5cddcf729db4f31b481.jpg

這個範例從檔名來分析的話是具有tracker以及sgie的額外功能,這也是唯一一個有使用到second gie的範例,我們就直接來看看配置檔的部分吧!

其實設置的方法很簡單,只需要增加 [secondary-gie%d] 這個項目,這邊導入了 VehicleTypes的引擎可以用來辨識車子的種類;gie-unique-id這邊則是從3開始,其實不要跟Primary的id衝突到應該就可以了;operate-on-gie-id表示將這個gie應用在哪一個gie上面;operate-on-class-ids可以特別選擇應用在第幾個類別的項目上,secondary可以自動進行IOU的分割並進行二次的辨識,針對這個部分我們可以設定成辨識到車子再開啟secondary辨識。

[secondary-gie0]
enable=1
model-engine-file=../../models/Secondary_VehicleTypes/resnet18.caffemodel_b16_gpu0_int8.engine
gpu-id=0
batch-size=16
gie-unique-id=4
operate-on-gie-id=1
operate-on-class-ids=0;
config-file=config_infer_secondary_vehicletypes.txt

第二個則是辨識車子的顏色

[secondary-gie1]
enable=1
model-engine-file=../../models/Secondary_CarColor/resnet18.caffemodel_b16_gpu0_int8.engine
batch-size=16
gpu-id=0
gie-unique-id=5
operate-on-gie-id=1
operate-on-class-ids=0;
config-file=config_infer_secondary_carcolor.txt

最後試辨識車子的廠牌。

[secondary-gie2]
enable=1
model-engine-file=../../models/Secondary_CarMake/resnet18.caffemodel_b16_gpu0_int8.engine
batch-size=16
gpu-id=0
gie-unique-id=6
operate-on-gie-id=1
operate-on-class-ids=0;
config-file=config_infer_secondary_carmake.txt

結論

看了三個範例之後應該大部分的參數都了解了吧!接著就可以按照自己的需求去更動了,不過目前都只是在使用他提供的模型,如果要使用自己的模型怎麼辦?在下一篇文章中我會帶大家操作使用DeepStream運行YOLOv4的方法,接著再教大家怎麼透過YOLOv4進行Transfer Learning訓練自己的數據集,最後整合在一起就完成在DeepStream上辨識自己想要辨識的東西了。最後補充怎麼在DeepStream輸出RTSP並且在Windows電腦上接收畫面。

(補充) DS輸出RTSP並在Win10上顯示

步驟如下:

1.安裝VLC : https://www.videolan.org/vlc/index.zh_TW.html

1436_27eee3e253a85432697aaede12f771238407a7a9.png

2.開啟網路串流,可以輸入快速鍵 Ctrl+N。

1531_a975d7eb01519ca36fcbf99af2517bcc2c7fd138.png

3.輸入網址,在DeepStream程式開起來的前幾行會提示應該怎麼輸入,基本上沒動到的話,埠號是8554,後面加上資料名稱 ds-test,按下播放即可。

1636_b860c056f745b4097469d2a623a872abb20b228e.png

4.大功告成

1728_9772148ee7bcaca322f83e72839bbd1ca6e1c19e.png

CAVEDU Education is devoted into robotics education and maker movement since 2008, and is intensively active in teaching fundamental knowledge and skills. We had published many books for readers in all ages, topics including Deep Learning, edge computing, App Inventor, IoT and robotics. Please check CAVEDU's website for more information: http://www.cavedu.com, http://www.appinventor.tw
DesignSpark Electrical Logolinkedin