借助 NVIDIA 視覺編程接口庫(kù)(VPI),您可以更有效地利用 Jetson Thor 的計(jì)算性能。
構(gòu)建自主機(jī)器人需要具備可靠且低延遲的視覺感知能力,以實(shí)現(xiàn)在動(dòng)態(tài)環(huán)境中的深度估計(jì)、障礙物識(shí)別、定位與導(dǎo)航。這些功能對(duì)計(jì)算性能有較高要求。NVIDIA Jetson平臺(tái)雖為深度學(xué)習(xí)提供了強(qiáng)大的GPU支持,但隨著AI模型復(fù)雜性的提升以及對(duì)實(shí)時(shí)性能的更高需求,GPU可能面臨過(guò)載風(fēng)險(xiǎn)。若將所有感知任務(wù)完全依賴GPU執(zhí)行,不僅容易造成性能瓶頸,還可能導(dǎo)致功耗上升和散熱壓力加劇,這在功耗受限且散熱條件有限的移動(dòng)機(jī)器人應(yīng)用中尤為突出。
為解決上述挑戰(zhàn),NVIDIA Jetson平臺(tái)將高性能GPU與專用硬件加速器相結(jié)合。Jetson AGX Orin和Jetson Thor等平臺(tái)均配備專用硬件加速器,專為高效執(zhí)行圖像處理和計(jì)算機(jī)視覺任務(wù)而設(shè)計(jì),從而釋放GPU資源,使其能夠?qū)W⒂谔幚砀鼜?fù)雜的深度學(xué)習(xí)工作負(fù)載。NVIDIA視覺編程接口(VPI)進(jìn)一步充分激活了不同類型硬件加速器的性能潛力。
在本博客中,我們將探討使用這些加速器的優(yōu)勢(shì),并詳細(xì)介紹開發(fā)者如何通過(guò)VPI充分發(fā)揮Jetson平臺(tái)的性能潛力。作為示例,我們將展示如何運(yùn)用這些加速器開發(fā)一個(gè)用于立體視差的低延遲、低功耗的感知應(yīng)用。首先,我們將構(gòu)建單路立體攝像頭的工作流,隨后擴(kuò)展至多流工作流,在Thor T5000上支持8路立體攝像頭同時(shí)以30 FPS運(yùn)行,其性能相較Orin AGX 64 GB提升至10倍。
在開始開發(fā)之前,讓我們快速了解Jetson平臺(tái)提供的各類加速器,它們的優(yōu)勢(shì)所在,能夠支持哪些應(yīng)用場(chǎng)景,以及VPI如何為開發(fā)提供助力。
除了GPU之外,Jetson還配備了哪些其他加速器?
Jetson設(shè)備配備了強(qiáng)大的GPU,適用于深度學(xué)習(xí)任務(wù),但隨著AI復(fù)雜性的提升,對(duì)GPU資源的高效管理變得愈發(fā)重要。Jetson為計(jì)算機(jī)視覺(CV)工作負(fù)載提供了專用的硬件加速引擎。這些引擎與GPU協(xié)同工作,在保持靈活性的同時(shí),顯著提升了計(jì)算效率。通過(guò)VPI,開發(fā)者可以更便捷地訪問(wèn)這些硬件資源,簡(jiǎn)化實(shí)驗(yàn)流程并實(shí)現(xiàn)高效的負(fù)載分配。

圖1:面向Jetson開發(fā)者的視覺編程接口(VPI)
下面我們逐一深入了解每個(gè)加速器,以及其用途與優(yōu)勢(shì)。
可編程視覺加速器(PVA):
PVA是一款可編程的數(shù)字信號(hào)處理(DSP)引擎,配備超過(guò)1024位的單指令多數(shù)據(jù)(SIMD)單元,以及支持靈活直接內(nèi)存訪問(wèn)(DMA)的本地內(nèi)存,專為視覺和圖像處理任務(wù)優(yōu)化,具備出色的每瓦性能。它能夠與CPU、GPU及其他加速器異步運(yùn)行,除NVIDIA Jetson Nano外,其他所有Jetson平臺(tái)均配備該加速器。
通過(guò)VPI,開發(fā)者可以調(diào)用現(xiàn)成的算法,如AprilTag檢測(cè)、物體追蹤,和立體視差估計(jì)。對(duì)于需要自定義算法的場(chǎng)景,Jetson開發(fā)者現(xiàn)在還可使用PVA SDK,該SDK提供了C/C++ API及相關(guān)工具,支持直接在PVA上開發(fā)視覺算法。
光流加速器(OFA):
OFA是一種固定功能的硬件加速器,用于基于立體攝像頭對(duì)的數(shù)據(jù),計(jì)算光流和立體視差。OFA支持兩種工作模式:在視差模式下,通過(guò)處理立體攝像頭的左右校正圖像來(lái)生成視差圖;在光流模式下,則用于估算連續(xù)兩幀之間的二維運(yùn)動(dòng)矢量。
視頻和圖像合成器(VIC):
VIC是Jetson設(shè)備中的一種專用硬件加速器,具備固定功能,能夠高效節(jié)能地處理圖像縮放、重映射、扭曲、色彩空間轉(zhuǎn)換和降噪等基礎(chǔ)圖像處理任務(wù)。
哪些用例可以從這些加速器中獲益?
在某些場(chǎng)景下,開發(fā)者可能會(huì)考慮采用GPU以外的解決方案,以更好地滿足特定應(yīng)用的需求。
GPU資源過(guò)載應(yīng)用:為實(shí)現(xiàn)高效運(yùn)行,開發(fā)者應(yīng)優(yōu)先將深度學(xué)習(xí)(DL)工作負(fù)載分配給GPU,同時(shí)利用VPI將計(jì)算機(jī)視覺任務(wù)卸載至PVA、OFA或VIC等專用加速器。例如,DeepStream的Multi+ Object Tracker在Orin AGX平臺(tái)上若僅依賴GPU,可處理12路視頻流;而通過(guò)引入PVA實(shí)現(xiàn)負(fù)載均衡后,支持的視頻流數(shù)量可提升至16路。
功耗敏感型應(yīng)用:在哨兵模式(sentry mode)或持續(xù)監(jiān)控等場(chǎng)景中,將主要計(jì)算任務(wù)轉(zhuǎn)移至低功耗加速器(如PVA、OFA、VIC),有助于顯著提升效率。
存在熱限制的工業(yè)應(yīng)用:在高溫運(yùn)行環(huán)境下,合理分配任務(wù)至各類加速器可有效降低GPU負(fù)載,減少因過(guò)熱導(dǎo)致的性能節(jié)流,從而在限定的熱預(yù)算內(nèi)維持穩(wěn)定的延遲與吞吐表現(xiàn)。
如何使用VPI解鎖所有加速器
VPI提供了一個(gè)統(tǒng)一且靈活的框架,使開發(fā)者能夠在Jetson模組、工作站或配備獨(dú)立GPU的PC等不同平臺(tái)上無(wú)縫訪問(wèn)加速器。
現(xiàn)在,我們來(lái)看一個(gè)綜合運(yùn)用上述內(nèi)容的示例。
示例:立體視覺工作流
現(xiàn)代機(jī)器人系統(tǒng)通常采用被動(dòng)立體視覺技術(shù)實(shí)現(xiàn)對(duì)周圍環(huán)境的三維感知。因此,計(jì)算立體視差圖成為構(gòu)建復(fù)雜感知系統(tǒng)的關(guān)鍵環(huán)節(jié)。本文將介紹一個(gè)示例流程,幫助開發(fā)者生成立體視差圖及其對(duì)應(yīng)的置信度圖。同時(shí),我們將展示如何利用VPI提供的各類加速器,構(gòu)建低延遲、高能效的處理工作流。

圖2:在Jetson多加速器上部署的立體視覺流程示意圖。PVA+:可編程視覺陣列;VIC:視頻與圖像合成器;OFA:光流加速器。
在CPU上進(jìn)行預(yù)處理:預(yù)處理步驟可以在CPU上運(yùn)行,因?yàn)樗话l(fā)生一次。該步驟計(jì)算一個(gè)校正映射(rectification map),用于糾正立體相機(jī)幀中的鏡頭畸變。
在VIC上進(jìn)行重映射:這一步驟使用預(yù)計(jì)算的校正映射對(duì)相機(jī)幀去畸變并對(duì)齊,確保兩條光軸水平且平行。VPI支持多項(xiàng)式與魚眼畸變模型,并允許開發(fā)者定義自定義warp映射。更多細(xì)節(jié)可參考Remap文檔。
在OFA上計(jì)算立體視差:校正后的圖像對(duì)作為半全局匹配(SGM)算法的輸入。在實(shí)際應(yīng)用中,SGM可能會(huì)產(chǎn)生噪聲或錯(cuò)誤的視差值。通過(guò)生成置信度圖,可以剔除低置信度的視差估計(jì),從而提升結(jié)果質(zhì)量。有關(guān)SGM算法及其支持參數(shù)的更多信息,請(qǐng)參閱立體視差文檔。
在PVA上生成置信度圖:VPI提供三種置信度圖模式:絕對(duì)值(Absolute)、相對(duì)值(Relative)和推理(Inference)。絕對(duì)值和相對(duì)值模式需要兩個(gè)OFA通道(左/右視差)并結(jié)合PVA的交叉檢查機(jī)制;而推理模式僅需一個(gè)OFA通道,并在PVA上運(yùn)行一個(gè)輕量級(jí)CNN(包含兩個(gè)卷積層和兩個(gè)非線性激活層)。跳過(guò)置信度計(jì)算雖然速度較快,但會(huì)產(chǎn)生噪聲視差圖;相比之下,采用相對(duì)值或推理模式可顯著提升視差結(jié)果的精度與可靠性。
VPI的統(tǒng)一內(nèi)存架構(gòu)避免了跨引擎的不必要數(shù)據(jù)復(fù)制,其異步流與事件機(jī)制使開發(fā)者能夠提前規(guī)劃任務(wù)負(fù)載和同步點(diǎn)。由硬件管理的調(diào)度支持跨引擎并行執(zhí)行,既釋放了CPU資源,又通過(guò)高效的流式流程設(shè)計(jì)避免了延遲。
使用VPI構(gòu)建高性能立體視差工作流
開始使用Python API
本教程介紹如何使用VPI Python API實(shí)現(xiàn)基礎(chǔ)的立體視差工作流,且無(wú)需進(jìn)行圖像重映射。
需要提前準(zhǔn)備:
NVIDIA Jetson設(shè)備(例如Jetson AGX Thor)
通過(guò)NVIDIA SDK Manager或apt安裝VPI
Python庫(kù):vpi、numpy、Pillow、opencv-python
在本教程中,我們將:
加載左右立體圖像
轉(zhuǎn)換圖像格式以適配處理需求
同步數(shù)據(jù)流,確保信息準(zhǔn)備就緒
執(zhí)行立體匹配算法以計(jì)算視差
對(duì)輸出結(jié)果進(jìn)行后處理并保存
設(shè)置和初始化
第一步是導(dǎo)入所需的庫(kù)并創(chuàng)建VPIStream對(duì)象。VPIStream充當(dāng)命令隊(duì)列,可用于提交任務(wù)以實(shí)現(xiàn)異步執(zhí)行。為了演示并行處理,我們將使用兩個(gè)流。
import vpi import numpy as np from PIL import Image from argparse import ArgumentParser # Create two streams for parallel processing streamLeft = vpi.Stream() streamRight = vpi.Stream()
streamLeft用于處理左側(cè)圖像,streamRight用于處理右側(cè)圖像。
加載和轉(zhuǎn)換圖像
VPI的Python API可直接使用NumPy數(shù)組。我們首先通過(guò)Pillow加載圖像,然后利用VPI的asimage函數(shù)將其封裝為VPI圖像對(duì)象。接著,將圖像轉(zhuǎn)換為適用于立體匹配算法的格式。在本例中,圖像將從RGBA8格式轉(zhuǎn)換為Y8_ER_BL格式(即8位灰度、塊線性布局)。
# Load images and wrap them in VPI images left_img = np.asarray(Image.open(args.left)) right_img = np.asarray(Image.open(args.right)) left = vpi.asimage(left_img) right = vpi.asimage(right_img) # Convert images to Y8_ER_BL format in parallel on different backends left = left.convert(vpi.Format.Y8_ER_BL, scale=1, stream=streamLeft, backend=vpi.Backend.VIC) right = right.convert(vpi.Format.Y8_ER_BL, scale=1, stream=streamRight, backend=vpi.Backend.CUDA)
左側(cè)圖像通過(guò)streamLeft提交至VIC后端進(jìn)行處理,右側(cè)圖像則通過(guò)streamRight提交給NVIDIA CUDA后端。這種設(shè)計(jì)使得兩項(xiàng)操作能夠在不同的硬件單元上并行執(zhí)行,充分體現(xiàn)了VPI的核心優(yōu)勢(shì)。
同步并執(zhí)行立體差異
在執(zhí)行立體差異計(jì)算之前,必須確保兩張圖像均已準(zhǔn)備就緒。我們調(diào)用streamLeft.sync()來(lái)阻塞主線程,直至左側(cè)圖像的轉(zhuǎn)換完成。隨后,便可向streamRight提交vpi.stereodisp操作。
# Synchronize streamLeft to ensure the left image is ready streamLeft.sync() # Submit the stereo disparity operation on streamRight disparityS16 = vpi.stereodisp(left, right, backend=vpi.Backend.OFA|vpi.Backend.PVA|vpi.Backend.VIC, stream=streamRight)
立體差異算法在VPI后端(OFA、PVA、VIC)的組合上運(yùn)行,以充分利用專用硬件,最終生成一張S16格式的差異圖,用于表示兩幅圖像中對(duì)應(yīng)像素之間的水平偏移。
后處理和可視化
對(duì)原始差異圖進(jìn)行后處理以實(shí)現(xiàn)可視化時(shí),將Q10.5定點(diǎn)格式表示的差異值縮放到0-255范圍內(nèi)并保存。
# Post-process the disparity map
# Convert Q10.5 to U8 and scale for visualization
disparityU8 = disparityS16.convert(vpi.Format.U8, scale=255.0/(32*128), stream=streamRight, backend=vpi.Backend.CUDA)
# make accessible in cpu
disparityU8 = disparityU8.cpu()
#save with pillow
d_pil = Image.fromarray(disparityU8)
d_pil.save('./disparity.png')
最后一步是將原始數(shù)據(jù)轉(zhuǎn)換為人類可讀的圖像,其中灰度值代表深度信息。
使用C++ API的多流差異工作流
先進(jìn)的機(jī)器人技術(shù)依賴于高吞吐量,而VPI通過(guò)并行多流傳輸實(shí)現(xiàn)了這一需求。憑借簡(jiǎn)潔的API與硬件加速器的高效結(jié)合,VPI使開發(fā)者能夠構(gòu)建快速且可靠的視覺處理流程——與波士頓動(dòng)力(Boston Dynamics)新一代機(jī)器人系統(tǒng)的處理流程相似。
VPI采用VPIStream對(duì)象,這些對(duì)象作為先進(jìn)先出(FIFO)的命令隊(duì)列,可異步地向后端提交任務(wù),從而實(shí)現(xiàn)不同硬件單元上的并行運(yùn)算執(zhí)行(異步流)。
對(duì)于任務(wù)關(guān)鍵、追求極致性能的應(yīng)用,VPI的C++ API是理想之選。
以下代碼片段源自C++基準(zhǔn)測(cè)試,用于演示多流立體視差工作流的構(gòu)建與執(zhí)行過(guò)程。該示例通過(guò)SimpleMultiStreamBenchmarkC++應(yīng)用實(shí)現(xiàn):首先預(yù)生成合成的NV12_BL格式圖像,以消除運(yùn)行時(shí)生成數(shù)據(jù)帶來(lái)的開銷;隨后并行處理多個(gè)數(shù)據(jù)流,并測(cè)量每秒幀數(shù)(FPS)以評(píng)估吞吐性能。此外,該工具支持保存輸入圖像以及差異圖和置信度圖,便于調(diào)試分析。通過(guò)預(yù)生成數(shù)據(jù)的方式,本示例可有效模擬高速實(shí)時(shí)工作負(fù)載場(chǎng)景。
資源配置、對(duì)象聲明與初始化
我們首先聲明并初始化VPI中執(zhí)行該流水線所需的全部對(duì)象,包括創(chuàng)建流、輸入/輸出圖像以及立體視覺處理所需的有效載荷。由于立體算法的輸入圖像格式為NV12_BL,因此我們將其與Y8_Er圖像類型一同設(shè)置為中間格式轉(zhuǎn)換的格式。
int totalIterations = itersPerStream * numStreams; std::vectorleftInputs(numStreams), rightInputs(numStreams), confidences(numStreams), leftTmps(numStreams), rightTmps(numStreams); std::vector leftOuts(numStreams), rightOuts(numStreams), disparities(numStreams); std::vector stereoPayloads(numStreams); std::vector streamsLeft(numStreams), streamsRight(numStreams); std::vector events(numStreams); int width = cvImageLeft.cols; int height = cvImageLeft.rows; int vic_pva_ofa = VPI_BACKEND_VIC | VPI_BACKEND_OFA | VPI_BACKEND_PVA; VPIStereoDisparityEstimatorCreationParams stereoPayloadParams; VPIStereoDisparityEstimatorParams stereoParams; CHECK_STATUS(vpiInitStereoDisparityEstimatorCreationParams(&stereoPayloadParams)); CHECK_STATUS(vpiInitStereoDisparityEstimatorParams(&stereoParams)); stereoPayloadParams.maxDisparity = 128; stereoParams.maxDisparity= 128; stereoParams.confidenceType = VPI_STEREO_CONFIDENCE_RELATIVE; for (int i = 0; i < numStreams; i++) { CHECK_STATUS(vpiImageCreateWrapperOpenCVMat(cvImageLeft, 0, &leftInputs[i])); CHECK_STATUS(vpiImageCreateWrapperOpenCVMat(cvImageRight, 0, &rightInputs[i])); CHECK_STATUS(vpiStreamCreate(0, &streamsLeft[i])); CHECK_STATUS(vpiStreamCreate(0, &streamsRight[i])); CHECK_STATUS(vpiImageCreate(width, height, VPI_IMAGE_FORMAT_Y8_ER, 0, &leftTmps[i])); CHECK_STATUS(vpiImageCreate(width, height, VPI_IMAGE_FORMAT_NV12_BL, 0, &leftOuts[i])); CHECK_STATUS(vpiImageCreate(width, height, VPI_IMAGE_FORMAT_Y8_ER, 0, &rightTmps[i])); CHECK_STATUS(vpiImageCreate(width, height, VPI_IMAGE_FORMAT_NV12_BL, 0, &rightOuts[i])); CHECK_STATUS(vpiCreateStereoDisparityEstimator(vic_pva_ofa, width, height, VPI_IMAGE_FORMAT_NV12_BL, &stereoPayloadParams, &stereoPayloads[i])); CHECK_STATUS(vpiEventCreate(0, &events[i])); } int outCount = saveOutput ? (numStreams * itersPerStream) : numStreams; disparities.resize(outCount); confidences.resize(outCount); for (int i = 0; i < outCount; i++) { CHECK_STATUS(vpiImageCreate(width, height, VPI_IMAGE_FORMAT_S16, 0, &disparities[i])); CHECK_STATUS(vpiImageCreate(width, height, VPI_IMAGE_FORMAT_U16, 0, &confidences[i])); }
轉(zhuǎn)換圖像格式
我們使用VPI的C API為每個(gè)流提交圖像轉(zhuǎn)換操作,將來(lái)自攝像頭的NV12_BL輸入模擬幀進(jìn)行格式轉(zhuǎn)換。
for (int i = 0; i < numStreams; i++)
{
CHECK_STATUS(vpiSubmitConvertImageFormat(streamsLeft[i], VPI_BACKEND_CPU, leftInputs[i], leftTmps[i], NULL));
CHECK_STATUS(vpiSubmitConvertImageFormat(streamsLeft[i], VPI_BACKEND_VIC, leftTmps[i], leftOuts[i], NULL));
CHECK_STATUS(vpiEventRecord(events[i], streamsLeft[i]));
CHECK_STATUS(vpiSubmitConvertImageFormat(streamsRight[i], VPI_BACKEND_CPU, rightInputs[i], rightTmps[i], NULL));
CHECK_STATUS(vpiSubmitConvertImageFormat(streamsRight[i], VPI_BACKEND_VIC, rightTmps[i], rightOuts[i], NULL));
CHECK_STATUS(vpiStreamWaitEvent(streamsRight[i], events[i]));
}
for (int i = 0; i < numStreams; i++)
{
CHECK_STATUS(vpiStreamSync(streamsLeft[i]));
CHECK_STATUS(vpiStreamSync(streamsRight[i]));
}
我們將操作分別提交到兩個(gè)獨(dú)立流的不同硬件上,具體類型由輸入/輸出圖像的類型推斷得出。此次,我們還將在左側(cè)流完成轉(zhuǎn)換操作后記錄一個(gè)VPIEvent。VPIEvent是一種VPI對(duì)象,能夠在流錄制過(guò)程中等待另一個(gè)流完成所有操作。通過(guò)這種方式,我們可以讓右側(cè)流等待左側(cè)流的轉(zhuǎn)換操作完成,而無(wú)需阻塞調(diào)用線程(即主線程),從而實(shí)現(xiàn)多個(gè)左側(cè)流與右側(cè)流的并行執(zhí)行。
同步并執(zhí)行立體差異
我們通過(guò)VPI的C API提交立體匹配計(jì)算任務(wù),并使用std::chrono對(duì)其性能進(jìn)行基準(zhǔn)測(cè)試。
auto benchmarkStart = std::chrono::high_resolution_clock::now();
for (int iter = 0; iter < itersPerStream; iter++)
{
for (int i = 0; i < numStreams; i++)
{
int dispIdx = saveOutput ? (i * itersPerStream + iter) : i;
CHECK_STATUS(vpiSubmitStereoDisparityEstimator(streamsRight[i], vic_pva_ofa, stereoPayloads[i], leftOuts[i],
rightOuts[i], disparities[dispIdx], confidences[dispIdx],
&stereoParams));
}
}
// ====================
// End Benchmarking
for (int i = 0; i < numStreams; i++)
{
CHECK_STATUS(vpiStreamSync(streamsRight[i]));
}
auto benchmarkEnd = std::chrono::high_resolution_clock::now();
我們繼續(xù)使用confidenceMap提交計(jì)算任務(wù),并生成結(jié)果差異圖。同時(shí),停止基準(zhǔn)測(cè)試計(jì)時(shí)器,記錄轉(zhuǎn)換和生成差異所耗的時(shí)間。在向所有流提交任務(wù)后,顯式同步各個(gè)流,以確保調(diào)用線程在提交過(guò)程中不會(huì)被阻塞。
后處理和清理
我們利用VPI的C API與OpenCV的互操作性對(duì)差異圖進(jìn)行后處理,并在每次迭代循環(huán)中將其保存。可根據(jù)需要選擇保留輸出數(shù)據(jù)以供檢查,循環(huán)結(jié)束后再清理相關(guān)對(duì)象。
// ====================
// Save Outputs
if (saveOutput)
{
for (int i = 0; i < numStreams * itersPerStream; i++)
{
VPIImageData dispData, confData;
cv::Mat cvDisparity, cvDisparityColor, cvConfidence, cvMask;
CHECK_STATUS(
vpiImageLockData(disparities[i], VPI_LOCK_READ, VPI_IMAGE_BUFFER_HOST_PITCH_LINEAR, &dispData));
vpiImageDataExportOpenCVMat(dispData, &cvDisparity);
cvDisparity.convertTo(cvDisparity, CV_8UC1, 255.0 / (32 * stereoParams.maxDisparity), 0);
applyColorMap(cvDisparity, cvDisparityColor, cv::COLORMAP_JET);
CHECK_STATUS(vpiImageUnlock(disparities[i]));
std::ostringstream fpStream;
fpStream << "stream_" << i / itersPerStream << "_iter_" << i % itersPerStream << "_disparity.png";
imwrite(fpStream.str(), cvDisparityColor);
// Confidence output (U16 -> scale to 8-bit and save)
CHECK_STATUS(
vpiImageLockData(confidences[i], VPI_LOCK_READ, VPI_IMAGE_BUFFER_HOST_PITCH_LINEAR, &confData));
vpiImageDataExportOpenCVMat(confData, &cvConfidence);
cvConfidence.convertTo(cvConfidence, CV_8UC1, 255.0 / 65535.0, 0);
CHECK_STATUS(vpiImageUnlock(confidences[i]));
std::ostringstream fpStreamConf;
fpStreamConf << "stream_" << i / itersPerStream << "_iter_" << i % itersPerStream << "_confidence.png";
imwrite(fpStreamConf.str(), cvConfidence);
}
}
// ====================
// Clean Up VPI Objects
for (int i = 0; i < numStreams; i++)
{
CHECK_STATUS(vpiStreamSync(streamsLeft[i]));
CHECK_STATUS(vpiStreamSync(streamsRight[i]));
vpiStreamDestroy(streamsLeft[i]);
vpiStreamDestroy(streamsRight[i]);
vpiImageDestroy(rightInputs[i]);
vpiImageDestroy(leftInputs[i]);
vpiImageDestroy(leftTmps[i]);
vpiImageDestroy(leftOuts[i]);
vpiImageDestroy(rightTmps[i]);
vpiImageDestroy(rightOuts[i]);
vpiPayloadDestroy(stereoPayloads[i]);
vpiEventDestroy(events[i]);
}
// Destroy all disparity and confidence images
for (int i = 0; i < (int)disparities.size(); i++)
{
vpiImageDestroy(disparities[i]);
}
for (int i = 0; i < (int)confidences.size(); i++)
{
vpiImageDestroy(confidences[i]);
}
收集基準(zhǔn)測(cè)試結(jié)果
我們現(xiàn)在能夠收集并展示基準(zhǔn)測(cè)試的結(jié)果。
double totalTimeSeconds = totalTime / 1000000.0; double avgTimePerFrame = totalTimeSeconds / totalIterations; double throughputFPS= totalIterations / totalTimeSeconds; std::cout << "\n" << std::string(70, '=') << std::endl; std::cout << "SIMPLE MULTI-STREAM RESULTS" << std::endl; std::cout << std::string(70, '=') << std::endl; std::cout << "Input: RGB8 -> Y8_BL_ER" << std::endl; std::cout << "Total time: " << totalTimeSeconds << " seconds" << std::endl; std::cout << "Avg time per frame: " << (avgTimePerFrame * 1000) << " ms" << std::endl; std::cout << "THROUGHPUT: " << throughputFPS << " FPS" << std::endl; std::cout << std::string(70, '=') << std::endl; std::cout << "THROUGHPUT: " << throughputFPS << " FPS" << std::endl; std::cout << std::string(70, '=') << std::endl;
查看結(jié)果
在圖像分辨率為960 × 600、最大視差為128的條件下,該方案在Thor T5000上以30 FPS的幀率運(yùn)行立體視差估計(jì),同時(shí)支持8個(gè)并行數(shù)據(jù)流(包括置信度圖),且無(wú)需占用GPU資源。在MAX_N功耗模式下,其性能相比Orin AGX 64 GB提升至10倍。具體性能數(shù)據(jù)如表1所示。
| 立體視差全工作流(相對(duì)模式,分辨率:960 × 600,最大差異:128)的幀率(FPS)加速比隨流數(shù)量變化情況:Orin AGX(64 GB)、Jetson Thor、T5000分別達(dá)到122、122.5、212、111.9、54.6、58.9、78.3、299.7。 | |||
| 幀率(FPS) | 加速比 | ||
| 流數(shù)量 | Orin AGX(64 GB) | Jetson Thor T5000 | |
| 1 | 22 | 122 | 5.5 |
| 2 | 12 | 111 | 9.5 |
| 4 | 6 | 58 | 9.7 |
| 8 | 3 | 29 | 9.7 |
表1:Orin AGX與Thor T5000在RELATIVE模式下,立體視差處理流程的對(duì)比
波士頓動(dòng)力如何使用VPI
作為Jetson平臺(tái)的深度用戶,波士頓動(dòng)力借助視覺編程接口(VPI)來(lái)加速其感知系統(tǒng)的處理流程。
VPI支持無(wú)縫訪問(wèn)Jetson的專用硬件加速器,提供一系列優(yōu)化的視覺算法(如AprilTags和SGM立體匹配),以及ORB、Harris Corner、Pyramidal LK等特征檢測(cè)器,和由OFA加速的光流計(jì)算。這些技術(shù)構(gòu)成了波士頓動(dòng)力感知系統(tǒng)的核心,可通過(guò)負(fù)載均衡同時(shí)支撐原型驗(yàn)證與系統(tǒng)優(yōu)化。通過(guò)采用VPI,工程師能夠快速適配硬件更新,顯著縮短從開發(fā)到實(shí)現(xiàn)價(jià)值的周期。
要點(diǎn)總結(jié)
Jetson Thor平臺(tái)以及VPI等庫(kù)在硬件功能上的進(jìn)步,使開發(fā)者能夠?yàn)檫吘壎藱C(jī)器人設(shè)計(jì)出高效且低延遲的解決方案。
通過(guò)充分發(fā)揮Jetson平臺(tái)上各款可用加速器的獨(dú)特優(yōu)勢(shì),像波士頓動(dòng)力這樣的機(jī)器人公司能夠?qū)崿F(xiàn)高效且可擴(kuò)展的復(fù)雜視覺處理,從而推動(dòng)智能自主機(jī)器人在多種現(xiàn)實(shí)應(yīng)用場(chǎng)景中的落地與發(fā)展。
關(guān)于作者
Chintan Intwala 是 NVIDIA 核心計(jì)算機(jī)視覺產(chǎn)品管理團(tuán)隊(duì)的成員,專注于構(gòu)建 AI 賦能的云技術(shù),為各行各業(yè)的大型計(jì)算機(jī)視覺開發(fā)者提供支持。在加入 NVIDIA 之前,Chintan 曾在 Adobe 工作,專注于構(gòu)建 AI/ML 和 AR/Camera 產(chǎn)品及功能。他擁有麻省理工學(xué)院斯隆分校 (MIT Sloan) 的 MBA 學(xué)位,并已獲得超過(guò) 25 項(xiàng)美國(guó)專利。
Jonas Toelke 是 NVIDIA 核心計(jì)算機(jī)視覺團(tuán)隊(duì)的一員,領(lǐng)導(dǎo)的團(tuán)隊(duì)專注于構(gòu)建經(jīng)過(guò)優(yōu)化的計(jì)算機(jī)視覺產(chǎn)品,為各行各業(yè)的 TegraSoC 提供支持。加入 NVIDIA 之前,Jonas 曾就職于 Halliburton,專注于構(gòu)建 AI/ ML 應(yīng)用以解決石油物理問(wèn)題。他擁有慕尼黑理工大學(xué)工程學(xué)博士學(xué)位,并已獲得 20 項(xiàng)專利。
Colin Tracey 是 NVIDIA 的高級(jí)系統(tǒng)軟件工程師。他在 Jetson 和 DRIVE 平臺(tái)的嵌入式計(jì)算機(jī)視覺庫(kù)和 SDK 上工作。
Arjun Verma 是 NVIDIA 的系統(tǒng)軟件工程師,也是 NVIDIA 嵌入式設(shè)備計(jì)算機(jī)視覺產(chǎn)品的核心開發(fā)者。Arjun 最近剛從佐治亞理工學(xué)院獲得機(jī)器學(xué)習(xí)碩士學(xué)位。
-
機(jī)器人
+關(guān)注
關(guān)注
213文章
31075瀏覽量
222199 -
接口
+關(guān)注
關(guān)注
33文章
9519瀏覽量
157020 -
加速器
+關(guān)注
關(guān)注
2文章
839瀏覽量
40098 -
NVIDIA
+關(guān)注
關(guān)注
14文章
5592瀏覽量
109722 -
gpu
+關(guān)注
關(guān)注
28文章
5194瀏覽量
135433
原文標(biāo)題:在 NVIDIA Jetson Thor 上提升機(jī)器人感知效率
文章出處:【微信號(hào):NVIDIA-Enterprise,微信公眾號(hào):NVIDIA英偉達(dá)企業(yè)解決方案】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
NVIDIA Jetson AGX Thor Developer Kit開發(fā)環(huán)境配置指南
如何在NVIDIA Jetson AGX Thor上通過(guò)Docker高效部署vLLM推理服務(wù)
NVIDIA Jetson的相關(guān)資料分享
基于 NVIDIA Jetson 使用硬件在環(huán)設(shè)計(jì)機(jī)器人
NVIDIA Jetson還能讓AI驅(qū)動(dòng)維修機(jī)器人?
使用NVIDIA Jetson打造機(jī)器人導(dǎo)盲犬
NVIDIA Jetson + Isaac SDK 在人形機(jī)器人領(lǐng)域的方案詳解
NVIDIA Jetson + Isaac SDK 人形機(jī)器人方案全面解析
基于 NVIDIA Blackwell 的 Jetson Thor 現(xiàn)已發(fā)售,加速通用機(jī)器人時(shí)代的到來(lái)
如何在NVIDIA Jetson Thor上提升機(jī)器人感知效率
評(píng)論