交通監控系統、醫療保健和零售業都從智能視頻分析( IVA )中受益匪淺。 DeepStream 是一個 IVA SDK 。 DeepStream 使您能夠在運行時附加和分離視頻流,而不會影響整個部署。
這篇文章討論了使用 DeepStream 添加和刪除流的細節。我還介紹了如何跨多個孤立的數據中心集中管理大型部署,使用來自多個攝像頭的流服務于多個用例。
NVIDIA DeepStream SDK 是一種用于多傳感器處理的流分析工具包。流式數據分析用例正在你眼前發生變化。 IVA 在更智能的空間中有著巨大的幫助。DeepStream 運行在離散的 GPU ,如NVIDIA T4 , Nvidia 安培架構和系統芯片上的平臺,如 NVIDIA Jetson 系列的設備。
DeepStream 具有靈活性,使您能夠使用以下任一功能構建復雜的應用程序:
多種深度學習框架
多流
多個模型串聯或并聯組合形成一個整體
多個模型協同工作
以不同的精度計算
自定義預處理和后處理
與庫伯內特斯的配器
DeepStream 應用程序可以有多個插件,如圖 1 所示。根據功能,每個插件可以使用 GPU 、 DLA 或專用硬件。
圖 1 。顯示 nvinferserver 和 nvinfer 插件與 DeepStream 的集成。 Nvinfer 服務器可以與 ONNX 、 TensorFlow 、 PyTorch 和 TensorRT 等后端一起工作。它還支持創建集成模型。
DeepStream 的基本功能是允許大規模部署,確保在任何給定時間的吞吐量和準確性。任何 IVA 管道的規模取決于兩個主要因素:
流管理
計算能力
流管理是任何具有多個攝像頭的大型部署的重要方面。任何大型部署都不能用于添加/刪除流。如此大規模的部署必須進行故障保護,以便在運行時處理虛假流。此外,部署預計將處理用例到使用特定模型運行的管道的運行時連接/分離。
這篇文章幫助您了解流管理的以下方面:
使用 DeepStream Python API 的河流消耗量
在運行時添加和刪除流
在運行時將特定流附加到具有特定模型的管道
涉及多個數據中心的大規模部署中的流管理
隨著應用程序復雜性的增加,更改變得越來越困難。一個深思熟慮的發展戰略從一開始就可以起到很大的作用。在下一節中,我將簡要討論開發 DeepStream 應用程序的不同方法。我還討論了如何管理流/用例分配和解除分配,并考慮一些最佳實踐。
DeepStream 應用程序開發
DeepStream 使您能夠為基于 AI 的視頻、音頻和圖像分析創建無縫流媒體管道。 DeepStream 為您提供了使用 C 或 Python 進行開發的選擇,為它們提供了更大的靈活性。 DeepStream 附帶了幾個硬件加速插件。 DeepStream 源于 Gstreamer ,提供 Python 和 C 語言之間的統一 API 。
Python 和用于 DeepStream 的 C API 是統一的。這意味著在 Python 中開發的任何應用程序都可以輕松地轉換為 C 和 C 。 Python 和 C 為開發人員提供了所有級別的自由。使用 DeepStream Python 和 C API ,可以設計在運行時處理流和用例的動態應用程序。一些示例 Python 應用程序位于: NVIDIA-AI-IOT/deepstream_python_apps 。
DeepStream SDK 基于 GStreamer 多媒體框架,包括一個 GPU 加速插件管道。 SDK 中包含用于視頻輸入、視頻解碼、圖像預處理、基于 NVIDIA TensorRT 的推理、對象跟蹤和顯示的插件,以簡化應用程序開發過程。這些功能可用于創建適應性強的多流視頻分析解決方案。
插件是制作管道的核心構建塊。輸入(即管道輸入,例如相機和視頻文件)和輸出(例如屏幕顯示)之間的每個數據緩沖區都通過插件傳遞。視頻解碼和編碼、神經網絡推理以及在視頻流頂部顯示文本就是 plug-ins 的示例。連接的插件構成 pipeline 。
PAD 是插件之間的接口。當數據在管道中從一個插件流向另一個插件時,它從一個插件的源板流向另一個插件的接收器板。每個插件可能有零個、一個或多個源/接收器組件。
圖 2 。具有多流支持的簡化 DeepStream 應用程序。
前面的示例應用程序由以下插件組成:
GstUriDecodebin:將 URI 中的數據解碼為原始媒體。它選擇一個可以處理給定方案的源插件,并將其連接到decodebin。
Nvstreammux:Gst-nvstreammux插件從多個輸入源形成一批幀。
Nvinfer:Gst-nvinfer插件使用 TensorRT 對輸入數據進行推斷。
Nvmultistream-tiler:Gst-nvmultistreamtiler插件從批處理緩沖區合成 2D 磁貼。
Nvvideoconvert:Gst-nvvideoconvert執行縮放、裁剪和視頻顏色格式轉換。
NvDsosd:Gst-nvdsosd繪制邊界框、文本和感興趣區域( ROI )多邊形。
GstEglGles:EglGlesSink在 EGL 表面上渲染視頻幀( xOverlay 界面和本機顯示)。
每個插件可以有一個或多個源和接收器焊盤。在這種情況下,當添加流時,Gst-Uridecodebin插件被添加到管道中,每個流一個插件。每個Gst-Uridecodebin插件的源組件連接到單個Nv-streammux插件上的每個接收器組件。Nv-streammux從來自所有以前插件的幀創建批,并將它們推送到管道中的下一個插件。圖 3 顯示了如何將多個攝影機流添加到管道中。
圖 3 。將焊盤顯示為插件之間的鏈接接口。
緩沖區通過管道傳輸數據。緩沖區帶有時間戳,包含由各種 DeepStream 插件附加的元數據。緩沖區攜帶諸如有多少插件在使用它、標志和指向內存中對象的指針等信息。
DeepStream 應用程序可以看作是由單個組件插件組成的管道。每個插件使用 TensorRT 或多流解碼表示一個類似于功能塊的推理。在適用的情況下,使用底層硬件加速插件,以提供最佳性能。 DeepStream 的關鍵價值在于使視頻深度學習易于訪問,讓您能夠集中精力快速構建和定制高效、可擴展的視頻分析應用程序。
運行時流添加/刪除應用程序
DeepStream 以 Python 和 C 語言提供了運行時添加/刪除功能的示例實現。樣本位于以下位置:
DeepStream 源添加和刪除( C ): https://github.com/NVIDIA-AI-IOT/deepstream_reference_apps/tree/master/runtime_source_add_delete
DeepStream 源代碼添加和刪除( Python ): https://github.com/NVIDIA-AI-IOT/deepstream_python_apps/tree/master/apps/runtime_source_add_delete
這些應用程序的設計考慮到了簡單性。這些應用程序接受一個輸入流,同一個流在設定的時間間隔后多次添加到正在運行的管道中。這就是在不重新啟動應用程序的情況下將指定數量的流添加到管道的方式。最終,在每個時間間隔刪除每個流。刪除最后一個流后,應用程序將正常停止。
要從示例應用程序開始,請執行以下步驟。
創建基于 Python 的應用程序
從 ngc 拔出 DeepStream Docker 映像 。NVIDIA 。通用域名格式。
在服務器上運行 git clone Python 應用程序存儲庫 在 Docker 容器中。
轉到 Docker 容器中的以下位置: deepstream \ u python \ u apps / apps / runtime \ u source \ u add \ u delete
設置 Python 先決條件 。
轉到應用程序/運行時\源\添加\刪除并按如下方式執行應用程序:
創建基于 C 的應用程序
從 ngc 拔出 DeepStream Docker 映像 。NVIDIA 。通用域名格式。 :
在 Docker 容器內/opt/nvidia/deepstream/deepstream/sources/apps/sample_apps/的 C 應用程序存儲庫 上運行 git clone 。
轉到deepstream_reference_apps/runtime_source_add_delete,編譯并運行應用程序,如下所示:
應用程序方面:運行時攝影機添加和刪除
DeepStream Python 或 C 應用程序在運行腳本時通常將輸入流作為參數列表。代碼執行后,會發生一系列事件,最終將流添加到正在運行的管道中。
在這里,您使用uridecodebin插件將 URI 中的數據解碼為原始媒體。它選擇一個可以處理給定方案的源插件,并將其連接到解碼箱。
以下是注冊任何流時發生的序列列表:
源 bin 是通過函數create_uridecode_bin從Curidecodebin插件創建的。函數create_uridecode_bin接受第一個參數source_id,它是一個整數,第二個參數是rtsp_url。在本例中,此整數是流的順序,從 1 …。。 N 。此整數用于創建唯一可識別的source-bin名稱,如source-bin-1、source-bin-2、…source-bin- N 。
g_source_bin_list字典在source-bin和id值之間映射。
創建源 bin 后,程序參數中的 RTSP 流 URL 將附加到此源 bin 。
稍后,uridecodebin的源 bin 值鏈接到下一個插件streammux的接收器 bin 。
創建多個uridecodebin插件,每個插件對應一個流,并連接到streammux插件。
下面的代碼示例顯示了 Python 中用于將多個流連接到 DeepStream 管道的最小代碼。
在更有組織的應用程序中,負責流添加的這些代碼行被轉移到一個函數,該函數使用兩個參數來附加流:stream_id和rtsp_url。您可以隨時調用此類函數,并將更多流附加到正在運行的應用程序中。
類似地,當流必須與應用程序分離時,會發生以下事件:
已連接流的source_id被賦予函數stop_release_source。
連接到要釋放的source_id的streammux的sink-pad與uridecodebin的source bin分離。
然后將 uridecodebin 的源 bin 從管道中移除。
活動源計數減少 1 。
下面的代碼示例顯示了 Python 和 C 從 DeepStream 管道分離流的最小代碼。
部署方面:運行時攝影機和用例管理
前面,我討論了如何在代碼中添加和刪除流。考慮到部署方面,還有一些因素。
以前,您使用命令行參數獲取所有輸入流。但是,在程序執行之后,當它處于部署中時,您不能向它提供任何附加參數。如何向正在運行的程序傳遞要附加或分離哪個流的指令?
部署需要額外的代碼,用于定期檢查是否有必須附加的新流可用。應刪除以下流:
流不再需要監視。
攝像頭問題導致沒有流。
先前附加的流必須用于另一個用例。
在多個數據中心進行流處理的情況下,優先考慮距離數據中心最近的流源。
DeepStream 管道在主螺紋中運行。需要一個單獨的線程來檢查要添加或刪除的流。謝天謝地, Glib 有一個名為g_timeout_add_seconds的函數。 Glib 是 gnuclibrary 項目,它為 GNU 系統和 GNU / Linux 系統以及許多其他使用 Linux 作為內核的系統提供核心庫。
g_timeout_add_seconds( set )是管道運行時定期調用的函數。重復調用該函數,直到返回 FALSE ,此時超時將自動銷毀,并且不會再次調用該函數。
guint g_timeout_add_seconds (guint interval, GSourceFunc function, gpointer data);
g_timeout_add_seconds接受三個輸入:
Interval:調用函數之間的時間,以秒為單位。
function:要調用的函數。
data:要傳遞給函數的數據和參數。
例如,調用函數watchDog時需要GSourceBinList。streamURL和streamId之間的字典映射。streamId是將流添加到管道后生成的內部 ID (整數)。最后一個調用方函數類似于以下代碼示例:
根據當前間隔設置,watchDog函數每 10 秒調用一次。必須維護一個數據庫來管理和跟蹤多個流。表 1 顯示了這樣一個示例數據庫表。函數watchDog可用于查詢數據庫,其中根據當前狀態和用例維護了所有可用流的列表。
表 1 。管理流和相應用例所需的最小數據庫表。
下面是一個同時管理多個流所需的最小數據庫結構( SQL / no SQL )示例:
Source ID: 一個唯一的 ID ,也是nvstreammux連接到的接收器板 ID 。source_id對于監視nv-gst事件非常有用,例如, pad 為每個流添加了已刪除的 EOS 。請記住,在前面的簡單應用程序中,您考慮過按參數輸入順序將源 bin 設置為source-bin-1、source-bin-2、…source-bin- N 。對許多攝影機使用相同的方法,并跟蹤應用程序范圍內的所有活動源存儲箱。
RTSP URL: 源插件應使用的 URL 。
Stream state: 有助于管理流的狀態,如打開或關閉。數據庫客戶機還必須能夠根據客戶機感知到的情況更改攝像頭,例如壞流、無 STREAMm 攝像頭故障等。這有助于即時維護。
Use case: 為相機分配一個用例。將選中此用例,并且僅連接模型當前處于活動狀態的攝影機。
Camera Location: 有助于根據攝像機的位置定位計算機。此檢查可避免從位于遠處的攝影機進行不必要的捕獲,并且可以更好地分配給附近的其他計算群集。
Taken: 假設部署是具有多個節點的多 GPU 。當在任何機器和任何 GPU 上運行的 DeepStream 應用程序添加任何源時,它會將標志設置為True。這可以防止另一個實例再次重復添加相同的源。
如前所述維護一個模式可以從一個中心位置輕松創建和監控儀表板。
回到watchDog函數,下面是檢查流狀態并根據位置和用例附加新視頻流的偽代碼:
在模塊加載和全局變量初始化之后,應用程序進入主功能。
在主函數中,初始化本地模塊和變量。
當應用程序第一次啟動時,它會在應用位置和用例過濾器后從數據庫請求流列表。
收到流列表后, DeepStream 管道的所有插件都將初始化、鏈接并設置為PLAY狀態。此時,應用程序正在使用提供的所有流運行。
在每個設置的時間間隔之后,一個單獨的線程檢查數據庫中當前流的狀態。如果數據庫中任何已添加流的狀態更改為OFF,則該流將被釋放。該線程還檢查數據庫中是否列出了狀態為ON的新攝像頭,在應用位置和用例過濾器后,該流將添加到 DeepStream 管道中。
添加流后,數據庫的Taken列中的標志必須設置為True,以便其他進程無法再次添加相同的流。
圖 4 顯示了有效地添加、刪除攝像機流并連接到使用適當模型運行的服務器所需的功能調用的總體流程。
圖 4 。管理流和附加/分離用例的總體控制流 。
僅僅更改源的數量沒有幫助,因為源的下游組件必須能夠根據流的數量更改其屬性。為此,已經對 DeepStream 應用程序的組件進行了優化,以在運行時更改屬性。
然而,許多插件在初始化期間使用批大小作為參數來分配計算/內存資源。在這種情況下,建議在執行應用程序時指定最大批量大小。表 2 顯示了一些這樣的插件示例:
nd cleanup of resources when sources are removed.
表 2 。插件及其適應運行時更改的能力。
當檢測到流的數量時,可以顯式更改屬性。要在運行時手動調整插件的屬性,請使用 set_property 在 Python 和 C 或 g_object_set 函數在 C 。
最佳做法
在添加到管道之前,請始終檢查流屬性。 可以使用gst-discoverer-1.0命令行實用程序檢查流屬性。它從命令行接受 URI ,并打印有關流的所有信息。了解用于生成媒體的容器和編解碼器,以及必須在管道中放入哪些插件才能播放媒體,這非常有用。 Gst Discover 可通過使用各自的 API 與 Python 和 C 一起使用。
在開發 DeepStream 應用程序時對其進行概要分析。 這是優化和調整應用程序的第一步。分析有助于理解應用程序的性能特征,并可以輕松識別代碼中有改進機會的部分。查找應用程序中的熱點和瓶頸,幫助您決定優化工作的重點。
通過分析應用程序,計算可在 GPU 上運行的最大流數。在運行時,確保將最大流保持在支持的最大值以下,以便應用程序性能保持穩定。
關于作者
wnger:
Chintan Patel是NVIDIA的高級產品經理,致力于將GPU加速的解決方案引入HPC社區。 他負責NVIDIA GPU Cloud注冊表中HPC應用程序容器的管理和提供。 在加入NVIDIA之前,他曾在Micrel,Inc.擔任產品管理,市場營銷和工程職位。他擁有圣塔克拉拉大學的MBA學位以及UC Berkeley的電氣工程和計算機科學學士學位。
審核編輯:郭婷
-
NVIDIA
+關注
關注
14文章
5075瀏覽量
103529 -
監控系統
+關注
關注
21文章
3939瀏覽量
176328
發布評論請先 登錄
相關推薦
評論