iT邦幫忙

2026 iThome 鐵人賽

DAY 6
0
Software Development

深入認識DeepStream,不只是停在執行範例系列 第 6

[Day 06] 讓我們的串流加入影像模型

  • 分享至 

  • xImage
  •  

昨天我們已經開始在串流應用中使用了GPU的硬體資源,那今天就要正式進入DeepStream的核心,那就是影像模型。首先我們要知道DeepStream設計的目的就是要讓即時串流也可以加上AI應用,有高吞吐量才能讓串流維持即時運作,所以為了提高推論的吞吐量,DeepStream主要是以NVIDIA自家的TensorRT作為推論框架。

讓你的串流加上物件偵測

在開始前建議大家也開啟你的DeepStream容器一起操作,我們用tmux打開兩個Terminal,分別負責執行指令和開啟nvtop。讓我們執行下面的指令並且觀察nvtop的變化

gst-launch-1.0 nvurisrcbin uri=file:///opt/nvidia/deepstream/deepstream/samples/streams/sample_720p.mp4 ! mux.sink_0 \
nvstreammux name=mux batch-size=1 width=1280 height=720 ! \
nvinfer config-file-path=/opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/deepstream-test1/dstest1_pgie_config.txt ! \
nvdsosd ! \
nvv4l2h264enc ! \
h264parse ! \
mp4mux ! \
filesink location=/ironman/demo_infer.mp4

你會發現開始執行後,程式會卡在一個步驟叫做

Try to create engine from model files

而此時的nvtop會呈現一個GPU使用率極高的狀態並維持一段時間,之後才會看到程式顯示影片的播放時間

demo_build_engine
demo_after_build

執行完之後我們就會多出一個MP4檔案在/ironman/demo_infer.mp4,我們可以直接在主機端查看輸出影片

demo_output_video

就是這樣一個簡單的指令就完成了一個有模有樣的物件偵測串流程式,那接下來我們就來細看DeepStream到底幫你做了什麼事情

影像模型

訓練、匯出、佈署

大部分的模型開發和訓練都還是在PyTorch完成的,而NVIDIA也有自己的框架叫TAO,不過他們家的框架我就不熟了,主要是推出許多模型搭配DeepStream做展示。模型訓練完後下一步得先按照你使用的框架匯出ONNX版本的模型,現在主流的影像模型應用都是先以ONNX作為中繼檔案,最後才將ONNX模型轉換成TensorRT版本的模型。

ONNX簡介

ONNX是將模型儲存成一個開放格式,任何人都可以根據格式去解析模型的內容,可以理解成將模型開源的一種手段

速度與相容性的取捨

大費周章把模型轉換到TensorRT終究還是為了提高推論的速度,但為什麼這麼做速度就能提高呢?因為TensorRT是綁定硬體的,他會根據你產生模型當下的硬體做最佳化,而且連版本都是強行綁定,這種優化方式可以大幅提高硬體的使用效率,讓運算速度得到大幅度的提升,這也是ONNX這個中繼檔案存在的理由。除了NVIDIA,各家硬體供應商也是採取同樣的手段,將ONNX轉換到自家的模型格式做最後的推論應用。

範例中的模型

DeepStream容器內已經有佈署執行範例所需要的ONNX模型,本次範例的模型在這個位置/opt/nvidia/deepstream/deepstream/samples/models/Primary_Detector/resnet18_trafficcamnet_pruned.onnx,因為我們已經執行過範例,所以同一個目錄底下會有另外一個檔案resnet18_trafficcamnet_pruned.onnx_b1_gpu0_fp16.engine,這個就是執行初期程式停住時在產生的TensorRT模型,只要有這個模型就不必再重新產生,可以立即進行推論。

簡單說明一下這個模型檔名的涵義:

  • b1 代表這個模型最大支援同時推論一個影像,即batch size是1
  • gpu0 代表這個模型是用GPU-0建置的,前面有提到TensorRT是硬體綁定的
  • fp16 代表這個模型在會使用FP16精度做運算

元件解析

最後我們來看一下Pipeline中的各個元件分別負責做什麼事吧

nvurisrcbin

這是DeepStream提供的一個高階元件,只要給他URI就能輸出video/x-raw(memory:NVMM)資料,相當方便。但我們看一下他的Pad說明

nvurisrcbin_pad
會發現Availability是Sometimes,代表這個Pad是由元件決定什麼時候產生,我們得監聽元件發出的事件,在Pad產生時才把他接到下一個元件,這也是為什麼指令是這樣寫的原因

gst-launch-1.0 nvurisrcbin uri=<uri> ! mux.sink_0 \
nvstreammux name=mux batch-size=1 width=1280 height=720
[...]

這是gst-launch-1.0提供此情況的寫法,必須把下游元件命名,這裡是命名為mux,程式會自動將nvurisrcbin在運行時產生的vsrc_0接到muxsink_0上面,記得mux.sink_0後面就不要加上驚嘆號了,因為寫驚嘆號代表要接上下一個元件。

nvstreammux

負責將多個影像來源組合成Batch,讓推論元件可以做批次推論,提高運算效率。我們看一下他的Pad

nvstreammux_pad
輸入端是On request,要主動向元件請求Pad,指令上是透過mux.sink_0這一步去請求產生sink_0。而輸出則固定只有一個src,日後會再跟大家介紹為什麼輸出只有一個Pad,以及其中有什麼祕密等著我們去揭露。

nvinfer

負責運行TensorRT模型的元件。透過預先寫好的元件設定檔,這個元件會將輸入的原始影像轉換為tensor,執行批次推論,最後將輸出tensor做後處理產生所謂的Metadata附加到當前的串流資料上,串流資料會繼續傳遞給下一個元件。我們在輸出影片中看到的紅框跟標籤就是這個元件所產生的「資料」,記住這邊只產生資料。

nvdsosd

這個元件會去從串流資料中尋找剛才提到的Metadata,當Metadata中有物件偵測的資料時,它就可以根據設定畫出邊界框(Bounding Box)以及對應的標籤(Label),就是我們看到的紅色框、Person、Car。

nvv4l2h264enc

負責將原始影像編碼為.h264的數據流。它的目標也很明確,就是使用GPU上的硬體編碼器,所以程式執行時可以看到ENC的使用率會上升。

h264parse

這個就是GStreamer本來就有的元件,負責整理編碼完的.h264數據流,我們只要知道這個步驟在存.mp4影片是必須的。

mp4mux

把.h264數據流封裝進mp4容器內

filesink

把任意數據流寫入檔案

結語

今天的內容就是這樣啦,我後續會安排幾天去更深入介紹DeepStream的元件在做什麼,以及它的原理,大家就先嘗試看看用前面分享的知識來打造自己的串流程式吧


上一篇
[Day 05] 認識工具 gst-launch-1.0
下一篇
[Day 07] 多路串流的功臣nvstreammux
系列文
深入認識DeepStream,不只是停在執行範例13
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言