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