NVIDIA VPI -1
英偉達(dá)的vpi感覺還是要擼一擼 學(xué)學(xué)~~~
而且VPI將取代VisonWorks 注意:NVIDIA也說了,將來VisionWorks將停止開發(fā),將被VPI替代.
好了 過多介紹自行百度把, 這里說話說下VPI在jetson上的使用
NVIDIA 視覺編程接口 (VPI) 是一個軟件庫,可提供一組計算機視覺和圖像處理算法。這些算法的實現(xiàn)在 NVIDIA Jetson 嵌入式計算機或獨立 GPU 上可用的不同硬件引擎上得到加速。
在這說下Jetson 產(chǎn)品系列上運行時間降噪 (TNR) 示例應(yīng)用程序。有關(guān)更多信息,請參閱:
https://docs.nvidia.com/vpi/index.html ?
在 Jetson 設(shè)備上設(shè)置 VPI
通過 SDK Manger設(shè)置 Jetson 設(shè)備時,請確保選中 Jetson SDK 組件框。然后在設(shè)備刷機時安裝 VPI。有關(guān)安裝的更多信息,請參閱: https://developer.nvidia.com/nvidia-sdk-manager
安裝完成后,可以在如下路徑下找到VPI:
/opt/nvidia/vpi1/要驗證環(huán)境設(shè)置是否正確,請將 VPI 示例應(yīng)用程序復(fù)制到您的主目錄中,然后構(gòu)建 TNR 示例。
$ vpi1_install_samples.sh $HOME $ cd $HOME/NVIDIA_VPI–samples/09-tnr $ cmake 。 $ makeTNR 示例應(yīng)用
VPI 提供了一組 CV 算法,這些算法利用多個后端來有效地使用設(shè)備的可用計算資源。TNR 是一種降噪方法,常用于在 Jetson 設(shè)備上運行的計算機視覺應(yīng)用程序。這篇博文使用 TNR 示例應(yīng)用程序來演示如何使用 VPI 中的一些關(guān)鍵概念和組件來實現(xiàn)自己的應(yīng)用程序。
我們在這篇文章中涵蓋了以下主題:
- 創(chuàng)建構(gòu)建 VPI 管道所需的元素
- 了解與 OpenCV 的互操作性是如何發(fā)生的
- 將處理任務(wù)提交到流
- 同步流中的任務(wù)
- 鎖定圖像緩沖區(qū),以便 CPU 可以訪問它
TNR 示例可以在以下路徑中找到:
$HOME/NVIDIA_VPI–samples/09-tnr/main.cpp有關(guān)示例應(yīng)用程序和算法的更多信息,請參閱以下資源: 1.應(yīng)用程序:https://docs.nvidia.com/vpi/sample_tnr.html
2.算法:https://docs.nvidia.com/vpi/algo_tnr.html
去噪前:
不會貼動圖就這樣了....
硬件引擎在 VPI 中被命名為后端。這些后端使您能夠卸載可并行處理階段并通過使用 Jetson 設(shè)備固有的可用系統(tǒng)級并行性來加速應(yīng)用程序。后端是 CPU、CUDA (GPU)、PVA 和 VIC。特定后端引擎的確切可用性取決于部署應(yīng)用程序的 Jetson 平臺。
VPI 目前為 TNR 提供了兩種不同的實現(xiàn)方式,分別適合不同的場景和需求。這些版本采用雙邊濾波的組合來平滑平坦區(qū)域,同時保留邊緣,并結(jié)合使用運動檢測器的時間無限脈沖響應(yīng) (IIR) 濾波來處理跨幀的時間噪聲。
- VPI_TNR_V2 —與 VPI_TNR_V3 相比,此版本提供了更輕的降噪和一定程度的可配置性,即可以調(diào)整光照條件以更好地適應(yīng)給定場景。這個版本減少了計算需求,這轉(zhuǎn)化為速度。它適用于執(zhí)行時間比降噪質(zhì)量更重要的用例。
- VPI_TNR_V3 —適用于需要更好質(zhì)量的降噪的用例。使用此變體,與 VPI_TNR_V2 相比,您應(yīng)該預(yù)計計算需求會增加。在此之上,可配置性得到進(jìn)一步擴展。推薦用于具有挑戰(zhàn)性的低光場景。
- VPI_TNR_DEFAULT —您可以使用默認(rèn)值,而不是指定確切的版本,該值會選擇給定后端支持的降噪最強的版本。
在決定哪種算法版本適合您的用例時要考慮的另一個標(biāo)準(zhǔn)是它對不同后端和設(shè)備的支持。下表總結(jié)了 TNR 支持。
VPI_TNR_V2 和 VPI_TNR_V3 都允許您明確設(shè)置您正在捕捉的場景的照明條件,從而啟用調(diào)整。這在低光場景或以高增益捕獲的流的背景下很重要,這些流可能包含更高的噪聲級別,因此需要更高級別的降噪。
更高的強度級別可能會影響幀紋理區(qū)域中的細(xì)節(jié)數(shù)量,從而使它們平滑。另一個副作用是在有快速移動物體的場景中出現(xiàn)重影。支持的場景照明條件在類型(室內(nèi)、室外)和強度(低、中和高)方面有所不同,如下表所示。
通過不同的版本和相關(guān)的照明條件預(yù)設(shè),您可以根據(jù)用例的具體情況調(diào)整 TNR 算法。這可以通過所謂的強度系數(shù)進(jìn)一步定制。它是一個范圍從 0 到 1 的浮點參數(shù),其中較大的值對應(yīng)于增加的降噪強度。
通過不同的版本和相關(guān)的照明條件預(yù)設(shè),您可以根據(jù)用例的具體情況調(diào)整 TNR 算法。這可以通過所謂的強度系數(shù)進(jìn)一步定制。它是一個范圍從 0 到 1 的浮點參數(shù),其中較大的值對應(yīng)于增加的降噪強度。
VPI應(yīng)用
VPI 的關(guān)鍵方面之一是它如何管理和協(xié)調(diào)在不同后端之間運行應(yīng)用程序所需的資源。使用 VPI,可以避免處理階段之間浪費的內(nèi)存副本。VPI 為高效內(nèi)存管理而強制執(zhí)行的另一種機制是其接口處的內(nèi)存包裝。
利用 VPI 的所有內(nèi)存管理功能取決于您的代碼的結(jié)構(gòu)。最佳實踐是將您的代碼視為一個三階段工作流:
大多數(shù)內(nèi)存分配應(yīng)該發(fā)生在初始化階段。這在嵌入式應(yīng)用程序的上下文中尤為重要,這些應(yīng)用程序在可用資源方面有限制的設(shè)備上運行。最重要的是,可以更有效、更謹(jǐn)慎地進(jìn)行內(nèi)存管理,以避免可能的內(nèi)存泄漏。
VPI 中的一個好做法是指定使用一塊內(nèi)存的后端。在這一點上,當(dāng)管道在這些后端之間流動時,僅將 VPI 對象訂閱到您需要的一組后端可確保您獲得最有效的內(nèi)存路徑。
處理循環(huán)是執(zhí)行處理管道的地方。想象一個應(yīng)用程序迭代具有數(shù)百個單獨幀的視頻文件。主循環(huán)將主要負(fù)責(zé)對像素信息執(zhí)行所需的轉(zhuǎn)換,以實現(xiàn)給定計算機視覺任務(wù)的預(yù)期結(jié)果。
最后,清理階段處理在任務(wù)執(zhí)行期間使用的資源的所有必要釋放和重新分配。堅持這種范式使 VPI 能夠使用最高效的處理管道,并幫助您堅持良好的編碼實踐。
與 OpenCV 接口
VPI 與 OpenCV 的互操作性是該庫的一個顯著特征。如果您熟悉 OpenCV,您可以輕松地將 VPI 與您的工作流集成或擴展現(xiàn)有數(shù)據(jù)管道,以更好地使用 VPI 提供的硬件加速。
這在 TNR 示例中通過以下實用函數(shù)進(jìn)行了演示,該函數(shù)將使用 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 }首先深入研究前面描述的函數(shù)。它旨在將 OpenCV 矩陣 ( cv::Mat) 對象包裝到 VPI 圖像對象 ( VPIImage) 中。就上下文而言,VPI 圖像本質(zhì)上是任何可以根據(jù)寬度、高度和格式進(jìn)行描述的 2D 數(shù)據(jù)結(jié)構(gòu)。盡管將圖像數(shù)據(jù)視為VPIImage對象很直觀,但其用途也可以擴展到其他類型的數(shù)據(jù),例如 2D 矢量場和熱圖。
實用程序包裝函數(shù)調(diào)用與 VPIOpenCVInterop.hpp模塊相關(guān)的另外兩個函數(shù),旨在提供有用的基礎(chǔ)設(shè)施來將基于 OpenCV 的代碼與 VPI 集成。
vpiImageCreateOpenCVMatWrapper — 一個重載函數(shù),將cv:Mat對象包裝成VPIImage兩種不同的風(fēng)格。第一個嘗試直接從輸入類型(遵循特定規(guī)則)推斷格式,而第二個將顯式格式作為其參數(shù)之一。
vpiImageSetWrappedOpenCVMat —重用為特定cv::Mat對象定義的包裝器來包裝新的傳入cv::Mat對象。這里的重點是避免首先創(chuàng)建包裝器引起的內(nèi)存分配,因此更有效。傳入的cv::Mat對象必須具有與創(chuàng)建時使用的原始對象相同的特征(格式和尺寸)。
流創(chuàng)建
main 函數(shù)捕獲設(shè)置 VPI 管道以完成工作的相關(guān)步驟。管道的定義很簡單,也很直觀。在 VPI 中,管道是流經(jīng)不同處理階段的一個或多個數(shù)據(jù)流的組合。
圖 1 以通用方式顯示了管道及其構(gòu)建塊(流、緩沖區(qū)、算法等)。為簡單起見,省略了一些組件。
流的目的是強制執(zhí)行數(shù)據(jù)需要通過的排隊步驟序列來完成特定的計算機視覺任務(wù)。這些步驟可能包括數(shù)據(jù)的預(yù)處理或后處理,甚至包括 TNR 等成熟的算法。圖 2 顯示了 VPIStream 對象的示例。
VPI 適應(yīng)不同范圍的管道復(fù)雜性。您可以使用單個流實現(xiàn)一個簡單的管道,或者使用多個并行流實現(xiàn)更復(fù)雜的實現(xiàn),這些并行流將不同階段卸載到不同的計算后端。這是 API 的一項強大功能,因為它使您能夠更好地控制 Jetson 設(shè)備提供的系統(tǒng)級并行性。
以下代碼示例演示了如何在 TNR 示例中創(chuàng)建流。
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));正在將選擇的后端傳遞到流中。這是一個可選步驟。使用零值將啟用所有可用的后端。但是,推薦的做法是分配一組特定的后端,因為它有助于優(yōu)化內(nèi)存分配。
TNR 有效載荷
有效負(fù)載本質(zhì)上是管道執(zhí)行期間所需的臨時資源。例如,有效載荷可以是一個中間內(nèi)存緩沖區(qū),用于存儲在流的后續(xù)階段之間交易的數(shù)據(jù)。許多算法,包括 TNR,都需要顯式創(chuàng)建有效載荷,這可以通過以下方式實現(xiàn)。
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 負(fù)載,提供以下參數(shù):
- 圖片尺寸(寬高)
- 后端
- 圖片數(shù)據(jù)的格式(目前只支持NV12)
- TNR算法版本
- 光照條件
- 降噪強度
- 參考算法有效載荷
最終,該函數(shù)創(chuàng)建一個有效負(fù)載并將其綁定到指定的后端。
圖像緩沖區(qū)
除了流和負(fù)載創(chuàng)建之外,還必須創(chuàng)建 VPI 算法所需的圖像緩沖區(qū)。在 TNR 中,使用雙邊和 IIR 濾波器的組合,因此需要三種不同的緩沖器;即當(dāng)前和上一個圖像輸入和圖像輸出。
可以按如下方式創(chuàng)建圖像緩沖區(qū):
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));這將創(chuàng)建具有以下指定特征的空緩沖區(qū):
- 圖片尺寸(寬高)
- 格式(根據(jù)算法要求)
- 圖像標(biāo)志(當(dāng)前用于分配后端)
- 指向VPIImage返回創(chuàng)建圖像句柄的變量的指針
流處理
構(gòu)建塊已經(jīng)就位后,您可以進(jìn)入主處理循環(huán),在那里執(zhí)行降噪算法。在 TNR 樣本上,循環(huán)迭代視頻文件中的每個單獨幀,并執(zhí)行必要的順序步驟以實現(xiàn)所需的結(jié)果。
當(dāng)從視頻中收集幀時,第一步是VPIImage使用前面描述的效用函數(shù)將其包裝成一個對象。
186 frameBGR = ToVPIImage(frameBGR, cvFrame);包裝完成后,VPI 現(xiàn)在可以對 VPIImage 對象中的像素數(shù)據(jù)進(jìn)行操作。由于 TNR 要求幀為 NV12 格式,因此需要一個轉(zhuǎn)換步驟。
188 // First convert it to NV12 189 CHECK_STATUS(vpiSubmitConvertImageFormat(stream,VPI_BACKEND_CUDA, frameBGR, imgCurrent, NULL));在這個階段,轉(zhuǎn)換圖像的特定任務(wù)與之前實例化的流相關(guān)聯(lián)。最重要的是,任務(wù)被設(shè)置為在 GPU 上執(zhí)行。輸入幀的圖像緩沖區(qū)以及剛剛從cv::Mat對象中包裝的數(shù)據(jù)用于此目的。
當(dāng)格式轉(zhuǎn)換完成后,可以將輸入緩沖區(qū)傳遞給 TNR 算法進(jìn)行處理。
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要調(diào)用 TNR 算法,請設(shè)置以下參數(shù):
- 算法關(guān)聯(lián)的流
- 后端
- 算法負(fù)載,如之前實例化的
- 圖像緩沖區(qū):以前和當(dāng)前的輸入和輸出
在第一次迭代 ( curFrame == 1) 時,緩沖區(qū)中沒有有效的先前圖像,而是傳遞了一個空指針。對于以下迭代,緩沖區(qū)會相應(yīng)地填充。在執(zhí)行 TNR 算法后,輸出緩沖區(qū)可以從 NV12 轉(zhuǎn)換回其先前的 BGR 格式。
197 // Convert output back to BGR 198 CHECK_STATUS(vpiSubmitConvertImageFormat(stream,VPI_BACKEND_CUDA, imgOutput, frameBGR, NULL));在這一點上,重要的是要提到 VPI 對流階段強制執(zhí)行非阻塞異步范式。這對于作為后端的不同協(xié)處理器之間分布的工作負(fù)載的平穩(wěn)和高效編排至關(guān)重要。對于進(jìn)一步的步驟,請確保在繼續(xù)之前已完成向流發(fā)出的所有活動。這時候同步功能就派上用場了。
199 CHECK_STATUS(vpiStreamSync(stream));VPI 現(xiàn)在確保與流相關(guān)的每個正在進(jìn)行的活動都已完成,然后再進(jìn)入管道的下一個階段。同步完成后,該幀已準(zhǔn)備就緒并可在連接到指定后端的輸出緩沖區(qū)中使用。為了能夠?qū)⑵鋵懭胼敵鲆曨l流(在本例中為文件),必須鎖定圖像,以便 CPU 可以使用緩沖區(qū)。
這解釋了為什么在鎖定幀之前同步是避免處理問題的關(guān)鍵步驟。因為 VPI 是異步操作的,所以可能會發(fā)生在沒有同步的情況下,緩沖區(qū)在前一階段完成之前被鎖定。這里的結(jié)果將是不可預(yù)測的。
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));如您所見,鎖定的緩沖區(qū)由 CPU 處理以供進(jìn)一步使用。鎖被設(shè)置為只讀,然后圖像緩沖區(qū)被映射到 CPU。鎖定時,VPI 無法在緩沖區(qū)上工作。CPU 將輸出幀提供給視頻編碼器后,緩沖區(qū)可以解鎖并進(jìn)一步供 VPI 使用。
VPI數(shù)據(jù)流
TNR 示例應(yīng)用程序可以總結(jié)為以下數(shù)據(jù)流。其他小步驟也是應(yīng)用程序的一個組成部分,但為了簡單起見,圖 3 中只包含了宏步驟。
?
官網(wǎng)都是 代碼 我找了倆個整個工程的git
py的?https://github.com/oyton/vpi_101
c+的?https://github.com/jugfk/NVIDIA_VPI-1.0-samples? 不過竟然是棒子的... 我是看不懂啊啊~~
總結(jié)
以上是生活随笔為你收集整理的NVIDIA VPI -1的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于KSWEB服务器与NAT123端口映
- 下一篇: 单片机软件定时器的使用方法