0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

改进VPI和PyTorch之间的互操作性

星星科技指导员 来源:NVIDIA 作者:NVIDIA 2022-06-21 16:47 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

NVIDIA Vision Programming Interface ( VPI )是 NVIDIA 的一个计算机视觉和图像处理软件库,使您能够在 NVIDIA Jetson 嵌入式设备和离散 GPU 上提供的不同硬件后端上实现加速算法

库中的一些算法包括滤波方法、透视扭曲、时间降噪、直方图均衡化、立体视差和镜头畸变校正。 VPI 提供了易于使用的 Python 绑定,以及一个 C ++ API 。

除了 与 OpenCV 接口 , VPI 还能够与 PyTorch 和其他基于 Python 的库进行互操作。在本文中,我们将通过一个基于 PyTorch 的对象检测和跟踪示例向您展示这种互操作性是如何工作的。有关更多信息,请参阅 视觉编程接口( VPI ) 页和 Vision 编程接口 文档。

与 PyTorch 和其他库的互操作性

根据您在计算机视觉和深度学习管道中实现的应用程序,您可能必须使用多个库。开发此类管道的挑战之一是这些库之间交互的效率。例如,当在内存拷贝之间交换图像数据时,可能会由于内存拷贝而出现性能问题。

使用 VPI ,您现在可以与 PyTorch 或任何其他支持__cuda_array_interace__的库进行互操作。__cuda_array_interface__( CUDA Array Interface )是 Python 中的一个属性,它支持各种项目(如库)中类似 GPU Array 对象的不同实现之间的互操作性。

阵列对象(如图像)可以在一个库中创建,在另一个库中修改,而无需复制 GPU 中的数据或将其传递给 CPU

图 1 VPI 和其他库之间的互操作性使用 __cuda_array_interface__

时间噪声抑制以改进目标检测和跟踪

噪声是视频中跨帧的常见特征。这种时间噪声会对视频中目标检测和跟踪算法的性能产生负面影响。

VPI 库提供了一种时间降噪( TNR )算法,这是计算机视觉应用中用于降低视频数据中噪声的常用方法。

在本演练中,您将在嘈杂的视频上使用基于 PyTorch 的对象检测和跟踪示例。然后应用 VPI 中的 TNR 算法来减少噪声,从而改进目标检测和跟踪。

我们表明,在执行 VPI 和 PyTorch 算法的过程中, VPI 和 PyTorch 都可以无缝工作,没有任何内存拷贝。

该示例包括以下内容:

PyTorch 基于原始输入视频的目标检测与跟踪

PyTorch 基于 VPI TNR 的干净输入视频目标检测与跟踪

使用 CUDA 阵列接口实现 VPI 和 PyTorch 之间的互操作性

PyTorch 基于原始输入视频的目标检测与跟踪

首先,首先定义一个基于 PyTorch 的应用程序来检测图像中的对象。此示例应用程序基于 具有 MobileNetV3 主干的 SSDLite ,用于使用 PyTorch 和 Torchvision 进行目标检测 Example.

创建一个名为PyTorchDetection的类来处理所有 PyTorch 对象和调用。创建此类对象时,应用程序正在将用于对象检测的预训练深度学习模型加载到 GPU ,仅用于推理。以下代码示例显示了所需的导入和类构造函数定义:

import torch
import torchvision class PyTorchDetection: def __init__(self): assert torch.cuda.is_available() self.cuda_device = torch.device('cuda') self.convert = torchvision.transforms.Compose([ torchvision.transforms.ConvertImageDtype(torch.float32), torchvision.transforms.Lambda(lambda x: x.permute(2, 0, 1)), torchvision.transforms.Lambda(lambda x: x.unsqueeze(0)), ]) model = torchvision.models.detection.ssdlite320_mobilenet_v3_large(
pretrained=True) self.torch_model = model.eval().to(self.cuda_device)

PyTorchDetection类还负责从阵列创建 CUDA 图像帧,有效地将其上载到 GPU 。稍后,您将使用 OpenCV 从文件中读取输入视频,其中每个视频帧都是一个 NumPy 数组,用作该类创建函数的输入。

此外,PyTorchDetection类可以将 CUDA 图像帧转换为 CUDA 张量对象,为模型推断做好准备,并将基于 VPI 的 CUDA 帧转换为张量。最后一次转换使用 VPI 的__cuda_array_interface__互操作性来避免复制帧。

 def CreateCUDAFrame(self, np_frame): return torch.from_numpy(np_frame).to(self.cuda_device) def ConvertToTensor(self, cuda_frame): return self.convert(cuda_frame) def ConvertFromVPIFrame(self, vpi_cuda_frame): return torch.as_tensor(vpi_cuda_frame, device=self.cuda_device)

除了前面定义的函数外,PyTorchDetection类还定义了一个函数,在给定scores_threshold值的情况下,可以在当前 OpenCV 帧中检测和绘制对象:

 def DetectAndDraw(self, cv_frame, torch_tensor, title, scores_threshold=0.2): with torch.no_grad(): pred = self.torch_model(torch_tensor) (...)

在这篇文章中,我们省略了代码,以提请大家注意 PyTorch 模型的预测结果。此处下载或使用本规范即表示您接受本规范的条款和条件。 您可以下载并查看代码 。

下一节介绍如何使用 VPI 降低输入视频中的噪声,将 VPI 与 PyTorch 耦合以改进其目标检测。

PyTorch 基于 VPI TNR 的干净输入视频目标检测与跟踪

在本节中,定义一个基于 VPI 的实用程序类VPITemporalNoiseReduction,以清除视频帧中的噪声。

创建此类对象时,应用程序加载主 VPI TNR 对象和基于 VPI 的 CUDA 帧以存储清理后的输出。以下代码示例显示了所需的导入和类构造函数定义:

import vpi class VPITemporalNoiseReduction: def __init__(self, shape, image_format): if (image_format == 'BGR8'): self.vpi_image_format = vpi.Format.BGR8 else: self.vpi_image_format = vpi.Format.INVALID self.vpi_output_frame = vpi.Image(shape, format=self.vpi_image_format) self.tnr = vpi.TemporalNoiseReduction(shape, vpi.Format.NV12_ER, version=vpi.TNRVersion.V3, backend=vpi.Backend.CUDA)

类的构造函数需要每个输入图像帧的形状(图像宽度和高度)和格式。为简单起见,您只接受BGR8图像格式,因为这是OpenCV在读取输入视频时使用的格式。

此外,您正在创建 VPI 图像,以使用提供的形状和格式存储输出帧。然后使用 TNR code 版本 3 和 CUDA 后端为该形状构造 TNR 对象。 TNR 的输入格式为 NV12 \ u ER ,与输入图像帧中的格式不同。接下来将在Denoise实用程序函数中处理帧转换。

 def Denoise(self, torch_cuda_frame, tnr_strength=1.0): vpi_input_frame = vpi.asimage(torch_cuda_frame, format=self.vpi_image_format) with vpi.Backend.CUDA: vpi_input_frame = vpi_input_frame.convert(vpi.Format.NV12_ER) vpi_input_frame = self.tnr(vpi_input_frame, preset=vpi.TNRPreset.OUTDOOR_LOW_LIGHT, strength=tnr_strength) vpi_input_frame.convert(out=self.vpi_output_frame) return self.vpi_output_frame

最后一个函数执行输入图像帧的实际清理。此函数用于从基于 PyTorch 的输入 CUDA 帧中移除噪声,返回基于 VPI 的输出 CUDA 帧。

首先使用 PyTorch 函数将 PyTorch vpi.asimage帧转换为 VPI 。torch_cuda_frame与vpi_input_frame共享相同的内存空间:即不涉及内存拷贝。

接下来,将输入帧从给定的输入格式( BGR8 )转换为 CUDA 中的 NV12 \ u ER 进行处理。

使用 TNR 预设OUTDOOR_LOW_LIGHT和给定的 TNR 强度,在转换后的输入帧上执行 TNR 算法。

清理后的输入帧( TNR 算法的输出)被转换回原始格式( BGR8 ),并存储在基于 VPI 的 CUDA 输出帧中。

生成的输出帧将返回,以供 PyTorch 稍后使用。

使用 CUDA 阵列接口实现 VPI 和 PyTorch 之间的互操作性

最后,在主模块中定义一个MainWindow类。此类基于 PySide2 ,并为本例提供了图形用户界面。

窗口界面显示两个输出图像帧,一个仅使用 PyTorch 进行检测,另一个在 VPI TNR 后使用 PyTorch 。此外,窗口界面包含两个滑块,用于控制用于 PyTorch 检测的分数阈值和用于去除 VPI 时间噪声的 TNR 强度。

import cv2
import numpy as np
(...)
from PySide2 import QtWidgets, QtGui, QtCore
(...)
from vpitnr import VPITemporalNoiseReduction
from torchdetection import PyTorchDetection class MainWindow(QMainWindow): def __init__(self, input_path): super().__init__() #-------- OpenCV part -------- self.video_capture = cv2.VideoCapture(input_path) if not self.video_capture.isOpened(): self.Quit() self.input_width = int(self.video_capture.get(cv2.CAP_PROP_FRAME_WIDTH)) self.input_height = int(self.video_capture.get(cv2.CAP_PROP_FRAME_HEIGHT)) self.output_video_shape = (self.input_height * 2, self.input_width, 3) self.output_frame_shape = (self.input_height, self.input_width, 3) self.cv_output_video = np.zeros(self.output_video_shape, dtype=np.uint8) #-------- Main objects of this example -------- self.torch_detection = PyTorchDetection() self.vpi_tnr = VPITemporalNoiseReduction((self.input_width, self.input_height), 'BGR8') (...) def UpdateDetection(self): in_frame = self.cv_input_frame if in_frame is None: return cuda_input_frame = self.torch_detection.CreateCUDAFrame(in_frame) # -------- Top Frame: No VPI --------- cuda_tensor = self.torch_detection.ConvertToTensor(cuda_input_frame) self.torch_detection.DetectAndDraw(self.TopFrame(), cuda_tensor, 'Pytorch only (no VPI)', self.scores_threshold) # -------- Bottom Frame: With VPI --------- vpi_output_frame = self.vpi_tnr.Denoise(cuda_input_frame, self.tnr_strength) with vpi_output_frame.rlock_cuda() as cuda_frame: cuda_output_frame=self.torch_detection.ConvertFromVPIFrame(cuda_frame) cuda_tensor = self.torch_detection.ConvertToTensor(cuda_output_frame) self.torch_detection.DetectAndDraw(self.BottomFrame(), cuda_tensor, 'Pytorch + VPI TNR', self.scores_threshold) (...)

类的构造函数需要输入视频的路径。它使用OpenCV读取输入视频,并创建一个高度为输入视频两倍的输出视频帧。这用于存储两个输出帧,一个仅用于PyTorch输出,另一个用于VPI+ PyTorch 输出。

构造函数还为 PyTorch 检测和 VPI TNR 创建对象。在本文中,我们省略了创建图形用户界面小部件和处理其回调的代码。我们还省略了创建主窗口和启动应用程序的代码。有关 TNR code 这一部分的更多信息,请下载示例。

当有新的输入视频帧可用时,调用UpdateDetection函数,从 NumPy OpenCV 输入帧创建基于 PyTorch 的 CUDA 输入帧。然后将其转换为张量,以检测并绘制PyTorchDetection类。顶部帧的管道直接在输入视频帧中运行 PyTorch 检测。

底部帧的下一条管道首先对基于 PyTorch CUDA 的输入帧进行去噪。去噪后的输出是一个名为vpi_output_frame的基于 VPI 的 CUDA 帧,使用rlock_cuda函数在 CUDA 中锁定读取。此函数为cuda_frame对象中的 VPI CUDA 互操作性提供__cuda_array_interface__。该对象将转换为 PyTorch CUDA 帧,然后转换为张量。再次,对管道的结果调用 detect and draw 函数。第二条管道在 VPI 去噪功能之后运行PyTorchDetection。

结果

图 3 显示了在公共场所行人噪声输入视频上,无 VPI TNR 和有 VPI TNR 的 PyTorch 目标检测和跟踪的结果。正如您可以从带有注释的输出视频中看到的那样,在检测之前应用去噪可以改善检测和跟踪结果(右)。

图 3 PyTorch 无 VPI TNR 和(右)有 VPI TNR 的目标检测和跟踪(左)

视频帧右下角显示的每秒帧数( FPS )( 32.8 仅适用于 PyTorch , 32.1 适用于 VPI + PyTorch )表明,将 VPI 添加到 PyTorch 检测管道不会增加太多开销。这在一定程度上是由于避免了从 CUDA 内存到 CPU 内存的每帧超过 20Mb 的拷贝,这是通过使用__cuda_array_interface__启用的。

总结

在这篇文章中,我们以 PyTorch 对象检测和跟踪为例,展示了 VPI 和其他支持__cuda_array_interface__的库之间的互操作性。在目标检测和跟踪之前,您应用了 VPI 的时间噪声抑制来改进它。我们还证明了在 PyTorch 管道中添加 VPI 不会导致性能损失。

关于作者

Sandeep Hiremath 是NVIDIA 计算机视觉的首席技术产品经理。他是一位经验丰富的产品领导者,专长于计算机视觉、机器学习嵌入式系统领域。在NVIDIA ,他负责为汽车、医疗保健、机器人和研究领域的开发人员提供一组计算机视觉和图像处理解决方案的产品愿景和战略。

André de Almeida Maximo 是 NVIDIA 的系统工程师,专注于嵌入式平台的软件。他曾在多家工业公司的研究中心工作,帮助塑造不同行业的人工智能。在空闲时间,安德烈喜欢跑步和阅读小说。

审核编辑:郭婷

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5209

    文章

    20629

    浏览量

    336796
  • gpu
    gpu
    +关注

    关注

    28

    文章

    5266

    浏览量

    136040
  • 计算机
    +关注

    关注

    19

    文章

    7837

    浏览量

    93447
  • pytorch
    +关注

    关注

    2

    文章

    813

    浏览量

    14921
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    为什么选择 Nordic 的低功耗蓝牙解决方案?

    ,我们的协议栈可提供具有行业领先操作性的强大蓝牙 LE 通信。 经过验证的质量、可靠操作性: 在数以千计的开发人员和数十亿无线 So
    发表于 04-16 10:40

    吉事励引领电动汽车充电操作性与兼容测试新风向

    在电动汽车行业蓬勃发展的进程中,充电桩的操作性与兼容已成为决定行业能否持续稳健前行的核心要素。这不仅关系到用户充电体验的优劣,更影响着整个产业生态的健康发展。
    的头像 发表于 03-30 15:27 607次阅读
    吉事励引领电动汽车充电<b class='flag-5'>互</b><b class='flag-5'>操作性</b>与兼容<b class='flag-5'>性</b>测试新风向

    Durin:Aliro标准赋能,打造无缝移动入户体验

    随着移动入户技术的快速发展,用户对智能门锁的安全操作性与无感体验提出了更高要求。Durin作为聚焦下一代家居入户体验的创新企业,摒弃传统共享密码模式,提供无需手动输入、强身份识别且高隐私保护
    的头像 发表于 03-25 15:53 324次阅读
    Durin:Aliro标准赋能,打造无缝移动入户体验

    PyTorch 中RuntimeError分析

    ? 错误原因 这个 RuntimeError 是因为在 PyTorch 中,upsample_nearest2d_out_frame(最近邻2D上采样)操作尚未对 BFloat16 数据类型提供
    发表于 03-06 06:02

    是德科技携手爱立信赋能Pre-6G操作性验证

    是德科技(NYSE: KEYS )近日宣布,与爱立信携手合作,使用是德科技的WaveJudge无线分析仪解决方案,对爱立信Pre-6G基站(gNB)与Pre-6G原型设备间的操作性进行故障排查
    的头像 发表于 03-03 16:10 549次阅读

    通过恩智浦RW612三频无线MCU提升多协议操作性

    无线连接是现代智能家居和工业系统的基石,推动着无数更智能、更自主设备的普及。恩智浦非常重视无线操作性,确保生态合作体系中的每台设备能够无缝协同工作的关键能力。
    的头像 发表于 03-03 11:47 1319次阅读

    IO序列化操作:提升系统操作性的关键技术

    在异构系统并存的今天,IO序列化操作成为实现系统间操作性的核心技术。通过标准化的数据格式(如JSON、Protobuf、Hessian等),不同语言、平台的系统得以无缝交换信息。合理设计序列化策略
    的头像 发表于 02-25 16:02 187次阅读
    IO序列化<b class='flag-5'>操作</b>:提升系统<b class='flag-5'>互</b><b class='flag-5'>操作性</b>的关键技术

    Pytorch 与 Visionfive2 兼容吗?

    Pytorch 与 Visionfive2 兼容吗? $ pip3 install torch torchvision torchaudio --index-url https
    发表于 02-06 08:28

    Matter 1.5版本解析,智能家居又添惊喜

    连接标准联盟推出Matter 1.5版本,增强设备操作性,华普微支持其落地测试,推动智能家居生态发展。
    的头像 发表于 12-13 16:50 3319次阅读

    是德科技与HEAD acoustics成功完成新一代eCall系统操作性测试

    是德科技(NYSE: KEYS )近日宣布,其基于UXM的新一代eCall(NG eCall)解决方案,已成功与全球汽车声学测试领导者HEAD acoustics GmbH完成操作性测试。
    的头像 发表于 11-18 11:29 753次阅读

    DP1363F 多协议NFC 兼容CLRC663开发资料

    ​DP1363F是高度集成的收发器芯片,用于13.56Mhz的非接触式通讯。集强大的多协议支持、最高射频输出功率,以及突破技术低功耗卡片检测等优势于一身,满足市场对更高集成度、更小外壳和操作性
    发表于 11-03 14:01

    Microchip与AVIVA Links实现ASA-ML操作性验证

    汽车行业正加速从专有串行器/解串器(SerDes)解决方案向汽车串行器/解串器联盟(Automotive SerDes Alliance)及其首个开放标准——ASA Motion Link(ASA-ML)构建的可操作系统生态过渡。
    的头像 发表于 10-23 17:13 1406次阅读

    Matter 1.4.2版本解析,我们的智能家居仍在持续进步

    Matter 1.4.2增强安全与兼容,支持Wi-Fi配网,降低设备成本,提升智能家居操作性
    的头像 发表于 08-22 15:25 2411次阅读
    Matter 1.4.2版本解析,我们的智能家居仍在持续进步

    Matter 智能家居的通用语言

    Matter由连接标准联盟(CSA)创建,旨在解决智能家居的操作性问题。Matter 基于简单性、操作性、可靠和安全
    发表于 05-19 15:35

    解读新发布的 Matter 1.4:推动智能家居设备操作性的关键升级

    着Matter 1.4的发布,智能家居和物联网(IoT)行业迎来了新的里程碑。Matter作为全球统一的智能家居互联协议,在操作性、安全和能效优化等方面取得了重大突破。本文将从Matter
    的头像 发表于 05-16 17:38 1135次阅读