NVIDIA VPI -1
英偉達的vpi感覺還是要擼一擼 學學~~~
而且VPI將取代VisonWorks 注意:NVIDIA也說了,將來VisionWorks將停止開發,將被VPI替代.
好了 過多介紹自行百度把, 這里說話說下VPI在jetson上的使用
NVIDIA 視覺編程接口 (VPI) 是一個軟件庫,可提供一組計算機視覺和圖像處理算法。這些算法的實現在 NVIDIA Jetson 嵌入式計算機或獨立 GPU 上可用的不同硬件引擎上得到加速。
在這說下Jetson 產品系列上運行時間降噪 (TNR) 示例應用程序。有關更多信息,請參閱:
https://docs.nvidia.com/vpi/index.html ?
在 Jetson 設備上設置 VPI
通過 SDK Manger設置 Jetson 設備時,請確保選中 Jetson SDK 組件框。然后在設備刷機時安裝 VPI。有關安裝的更多信息,請參閱: https://developer.nvidia.com/nvidia-sdk-manager
安裝完成后,可以在如下路徑下找到VPI:
/opt/nvidia/vpi1/要驗證環境設置是否正確,請將 VPI 示例應用程序復制到您的主目錄中,然后構建 TNR 示例。
$ vpi1_install_samples.sh $HOME $ cd $HOME/NVIDIA_VPI–samples/09-tnr $ cmake 。 $ makeTNR 示例應用
VPI 提供了一組 CV 算法,這些算法利用多個后端來有效地使用設備的可用計算資源。TNR 是一種降噪方法,常用于在 Jetson 設備上運行的計算機視覺應用程序。這篇博文使用 TNR 示例應用程序來演示如何使用 VPI 中的一些關鍵概念和組件來實現自己的應用程序。
我們在這篇文章中涵蓋了以下主題:
- 創建構建 VPI 管道所需的元素
- 了解與 OpenCV 的互操作性是如何發生的
- 將處理任務提交到流
- 同步流中的任務
- 鎖定圖像緩沖區,以便 CPU 可以訪問它
TNR 示例可以在以下路徑中找到:
$HOME/NVIDIA_VPI–samples/09-tnr/main.cpp有關示例應用程序和算法的更多信息,請參閱以下資源: 1.應用程序:https://docs.nvidia.com/vpi/sample_tnr.html
2.算法:https://docs.nvidia.com/vpi/algo_tnr.html
去噪前:
不會貼動圖就這樣了....
硬件引擎在 VPI 中被命名為后端。這些后端使您能夠卸載可并行處理階段并通過使用 Jetson 設備固有的可用系統級并行性來加速應用程序。后端是 CPU、CUDA (GPU)、PVA 和 VIC。特定后端引擎的確切可用性取決于部署應用程序的 Jetson 平臺。
VPI 目前為 TNR 提供了兩種不同的實現方式,分別適合不同的場景和需求。這些版本采用雙邊濾波的組合來平滑平坦區域,同時保留邊緣,并結合使用運動檢測器的時間無限脈沖響應 (IIR) 濾波來處理跨幀的時間噪聲。
- VPI_TNR_V2 —與 VPI_TNR_V3 相比,此版本提供了更輕的降噪和一定程度的可配置性,即可以調整光照條件以更好地適應給定場景。這個版本減少了計算需求,這轉化為速度。它適用于執行時間比降噪質量更重要的用例。
- VPI_TNR_V3 —適用于需要更好質量的降噪的用例。使用此變體,與 VPI_TNR_V2 相比,您應該預計計算需求會增加。在此之上,可配置性得到進一步擴展。推薦用于具有挑戰性的低光場景。
- VPI_TNR_DEFAULT —您可以使用默認值,而不是指定確切的版本,該值會選擇給定后端支持的降噪最強的版本。
在決定哪種算法版本適合您的用例時要考慮的另一個標準是它對不同后端和設備的支持。下表總結了 TNR 支持。
VPI_TNR_V2 和 VPI_TNR_V3 都允許您明確設置您正在捕捉的場景的照明條件,從而啟用調整。這在低光場景或以高增益捕獲的流的背景下很重要,這些流可能包含更高的噪聲級別,因此需要更高級別的降噪。
更高的強度級別可能會影響幀紋理區域中的細節數量,從而使它們平滑。另一個副作用是在有快速移動物體的場景中出現重影。支持的場景照明條件在類型(室內、室外)和強度(低、中和高)方面有所不同,如下表所示。
通過不同的版本和相關的照明條件預設,您可以根據用例的具體情況調整 TNR 算法。這可以通過所謂的強度系數進一步定制。它是一個范圍從 0 到 1 的浮點參數,其中較大的值對應于增加的降噪強度。
通過不同的版本和相關的照明條件預設,您可以根據用例的具體情況調整 TNR 算法。這可以通過所謂的強度系數進一步定制。它是一個范圍從 0 到 1 的浮點參數,其中較大的值對應于增加的降噪強度。
VPI應用
VPI 的關鍵方面之一是它如何管理和協調在不同后端之間運行應用程序所需的資源。使用 VPI,可以避免處理階段之間浪費的內存副本。VPI 為高效內存管理而強制執行的另一種機制是其接口處的內存包裝。
利用 VPI 的所有內存管理功能取決于您的代碼的結構。最佳實踐是將您的代碼視為一個三階段工作流:
大多數內存分配應該發生在初始化階段。這在嵌入式應用程序的上下文中尤為重要,這些應用程序在可用資源方面有限制的設備上運行。最重要的是,可以更有效、更謹慎地進行內存管理,以避免可能的內存泄漏。
VPI 中的一個好做法是指定使用一塊內存的后端。在這一點上,當管道在這些后端之間流動時,僅將 VPI 對象訂閱到您需要的一組后端可確保您獲得最有效的內存路徑。
處理循環是執行處理管道的地方。想象一個應用程序迭代具有數百個單獨幀的視頻文件。主循環將主要負責對像素信息執行所需的轉換,以實現給定計算機視覺任務的預期結果。
最后,清理階段處理在任務執行期間使用的資源的所有必要釋放和重新分配。堅持這種范式使 VPI 能夠使用最高效的處理管道,并幫助您堅持良好的編碼實踐。
與 OpenCV 接口
VPI 與 OpenCV 的互操作性是該庫的一個顯著特征。如果您熟悉 OpenCV,您可以輕松地將 VPI 與您的工作流集成或擴展現有數據管道,以更好地使用 VPI 提供的硬件加速。
這在 TNR 示例中通過以下實用函數進行了演示,該函數將使用 OpenCV 捕獲的輸入視頻幀包裝到 VPI 圖像對象中。
69 // Utility function to wrap a cv::Mat into a VPIImage 70 static VPIImage ToVPIImage(VPIImage image, const cv::Mat &frame)71 { 72 if (image == nullptr) 73 { 74 // Create a VPIImage that wraps the frame 75 CHECK_STATUS(vpiImageCreateOpenCVMatWrapper(frame, 0, &image)); 76 } 77 else 78 { 79 // reuse existing VPIImage wrapper to wrap the new frame. 80 CHECK_STATUS(vpiImageSetWrappedOpenCVMat(image, frame)); 81 } 82 return image; 83 }首先深入研究前面描述的函數。它旨在將 OpenCV 矩陣 ( cv::Mat) 對象包裝到 VPI 圖像對象 ( VPIImage) 中。就上下文而言,VPI 圖像本質上是任何可以根據寬度、高度和格式進行描述的 2D 數據結構。盡管將圖像數據視為VPIImage對象很直觀,但其用途也可以擴展到其他類型的數據,例如 2D 矢量場和熱圖。
實用程序包裝函數調用與 VPIOpenCVInterop.hpp模塊相關的另外兩個函數,旨在提供有用的基礎設施來將基于 OpenCV 的代碼與 VPI 集成。
vpiImageCreateOpenCVMatWrapper — 一個重載函數,將cv:Mat對象包裝成VPIImage兩種不同的風格。第一個嘗試直接從輸入類型(遵循特定規則)推斷格式,而第二個將顯式格式作為其參數之一。
vpiImageSetWrappedOpenCVMat —重用為特定cv::Mat對象定義的包裝器來包裝新的傳入cv::Mat對象。這里的重點是避免首先創建包裝器引起的內存分配,因此更有效。傳入的cv::Mat對象必須具有與創建時使用的原始對象相同的特征(格式和尺寸)。
流創建
main 函數捕獲設置 VPI 管道以完成工作的相關步驟。管道的定義很簡單,也很直觀。在 VPI 中,管道是流經不同處理階段的一個或多個數據流的組合。
圖 1 以通用方式顯示了管道及其構建塊(流、緩沖區、算法等)。為簡單起見,省略了一些組件。
流的目的是強制執行數據需要通過的排隊步驟序列來完成特定的計算機視覺任務。這些步驟可能包括數據的預處理或后處理,甚至包括 TNR 等成熟的算法。圖 2 顯示了 VPIStream 對象的示例。
VPI 適應不同范圍的管道復雜性。您可以使用單個流實現一個簡單的管道,或者使用多個并行流實現更復雜的實現,這些并行流將不同階段卸載到不同的計算后端。這是 API 的一項強大功能,因為它使您能夠更好地控制 Jetson 設備提供的系統級并行性。
以下代碼示例演示了如何在 TNR 示例中創建流。
143 VPIStream stream; 144 // PVA backend doesn't have currently Convert Image Format algorithm. 145 // Use the CUDA backend to do that. 146 CHECK_STATUS(vpiStreamCreate(VPI_BACKEND_CUDA | backend, &stream));正在將選擇的后端傳遞到流中。這是一個可選步驟。使用零值將啟用所有可用的后端。但是,推薦的做法是分配一組特定的后端,因為它有助于優化內存分配。
TNR 有效載荷
有效負載本質上是管道執行期間所需的臨時資源。例如,有效載荷可以是一個中間內存緩沖區,用于存儲在流的后續階段之間交易的數據。許多算法,包括 TNR,都需要顯式創建有效載荷,這可以通過以下方式實現。
172 // Create a TNR payload configured to process NV12 173 // frames under outdoor low-light scenarios. 174 VPIPayload tnr; 175 CHECK_STATUS(vpiCreateTemporalNoiseReduction(backend, w, h, VPI_IMAGE_FORMAT_NV12_ER, VPI_TNR_DEFAULT, 176 VPI_TNR_PRESET_INDOOR_LOW_LIGHT, 1, &tnr));?whaosoft aiot?http://143ai.com
對于 TNR 負載,提供以下參數:
- 圖片尺寸(寬高)
- 后端
- 圖片數據的格式(目前只支持NV12)
- TNR算法版本
- 光照條件
- 降噪強度
- 參考算法有效載荷
最終,該函數創建一個有效負載并將其綁定到指定的后端。
圖像緩沖區
除了流和負載創建之外,還必須創建 VPI 算法所需的圖像緩沖區。在 TNR 中,使用雙邊和 IIR 濾波器的組合,因此需要三種不同的緩沖器;即當前和上一個圖像輸入和圖像輸出。
可以按如下方式創建圖像緩沖區:
167 VPIImage imgPrevious, imgCurrent, imgOutput; 168 CHECK_STATUS(vpiImageCreate(w, h,VPI_IMAGE_FORMAT_NV12_ER, 0, &imgPrevious)); 169 CHECK_STATUS(vpiImageCreate(w, h,VPI_IMAGE_FORMAT_NV12_ER, 0, &imgCurrent)); 170 CHECK_STATUS(vpiImageCreate(w, h,VPI_IMAGE_FORMAT_NV12_ER, 0, &imgOutput));這將創建具有以下指定特征的空緩沖區:
- 圖片尺寸(寬高)
- 格式(根據算法要求)
- 圖像標志(當前用于分配后端)
- 指向VPIImage返回創建圖像句柄的變量的指針
流處理
構建塊已經就位后,您可以進入主處理循環,在那里執行降噪算法。在 TNR 樣本上,循環迭代視頻文件中的每個單獨幀,并執行必要的順序步驟以實現所需的結果。
當從視頻中收集幀時,第一步是VPIImage使用前面描述的效用函數將其包裝成一個對象。
186 frameBGR = ToVPIImage(frameBGR, cvFrame);包裝完成后,VPI 現在可以對 VPIImage 對象中的像素數據進行操作。由于 TNR 要求幀為 NV12 格式,因此需要一個轉換步驟。
188 // First convert it to NV12 189 CHECK_STATUS(vpiSubmitConvertImageFormat(stream,VPI_BACKEND_CUDA, frameBGR, imgCurrent, NULL));在這個階段,轉換圖像的特定任務與之前實例化的流相關聯。最重要的是,任務被設置為在 GPU 上執行。輸入幀的圖像緩沖區以及剛剛從cv::Mat對象中包裝的數據用于此目的。
當格式轉換完成后,可以將輸入緩沖區傳遞給 TNR 算法進行處理。
191 // Apply TNR 192 // For first frame, you must pass nullptr as the previous frame, this resets the internal 193 // state. 194 CHECK_STATUS(vpiSubmitTemporalNoiseReduction(stream, 0, tnr, curFrame == 1 ? nullptr : imgPrevious, 195 imgCurrent, imgOutput)); 196要調用 TNR 算法,請設置以下參數:
- 算法關聯的流
- 后端
- 算法負載,如之前實例化的
- 圖像緩沖區:以前和當前的輸入和輸出
在第一次迭代 ( curFrame == 1) 時,緩沖區中沒有有效的先前圖像,而是傳遞了一個空指針。對于以下迭代,緩沖區會相應地填充。在執行 TNR 算法后,輸出緩沖區可以從 NV12 轉換回其先前的 BGR 格式。
197 // Convert output back to BGR 198 CHECK_STATUS(vpiSubmitConvertImageFormat(stream,VPI_BACKEND_CUDA, imgOutput, frameBGR, NULL));在這一點上,重要的是要提到 VPI 對流階段強制執行非阻塞異步范式。這對于作為后端的不同協處理器之間分布的工作負載的平穩和高效編排至關重要。對于進一步的步驟,請確保在繼續之前已完成向流發出的所有活動。這時候同步功能就派上用場了。
199 CHECK_STATUS(vpiStreamSync(stream));VPI 現在確保與流相關的每個正在進行的活動都已完成,然后再進入管道的下一個階段。同步完成后,該幀已準備就緒并可在連接到指定后端的輸出緩沖區中使用。為了能夠將其寫入輸出視頻流(在本例中為文件),必須鎖定圖像,以便 CPU 可以使用緩沖區。
這解釋了為什么在鎖定幀之前同步是避免處理問題的關鍵步驟。因為 VPI 是異步操作的,所以可能會發生在沒有同步的情況下,緩沖區在前一階段完成之前被鎖定。這里的結果將是不可預測的。
201 // Now add it to the output video stream 202 VPIImageData imgdata; 203 CHECK_STATUS(vpiImageLock(frameBGR,VPI_LOCK_READ, &imgdata)); 204 205 cv::Mat outFrame; 206 CHECK_STATUS(vpiImageDataExportOpenCVMat(imgdata, &outFrame)); 207 outVideo << outFrame; 208 209 CHECK_STATUS(vpiImageUnlock(frameBGR));如您所見,鎖定的緩沖區由 CPU 處理以供進一步使用。鎖被設置為只讀,然后圖像緩沖區被映射到 CPU。鎖定時,VPI 無法在緩沖區上工作。CPU 將輸出幀提供給視頻編碼器后,緩沖區可以解鎖并進一步供 VPI 使用。
VPI數據流
TNR 示例應用程序可以總結為以下數據流。其他小步驟也是應用程序的一個組成部分,但為了簡單起見,圖 3 中只包含了宏步驟。
?
官網都是 代碼 我找了倆個整個工程的git
py的?https://github.com/oyton/vpi_101
c+的?https://github.com/jugfk/NVIDIA_VPI-1.0-samples? 不過竟然是棒子的... 我是看不懂啊啊~~
總結
以上是生活随笔為你收集整理的NVIDIA VPI -1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于KSWEB服务器与NAT123端口映
- 下一篇: 单片机软件定时器的使用方法