NVIDIA 图灵架构引入了一种新的硬件功能,用于以非常高的性能计算一对图像之间的光流。 NVIDIA 光流 SDK 公开了使用这种光流硬件(也称为 NVOFA )加速应用程序的 API 。我们很高兴地宣布光流 SDK 3 . 0 的可用性具有以下新功能:
- DirectX 12 光流 API
- 通过单个 API 的前后向光流
- 全球流动矢量
DirectX 12 光流 API
DirectX 12 是一个来自 Microsoft 的低级编程 API ,与它的前身 DirectX 11 相比,它减少了驱动程序开销。 DirectX 12 为开发人员提供了更大的灵活性和细粒度的控制。开发人员现在可以利用 DirectX 12 中的低级编程 API 并优化其应用程序,以提供比早期 DirectX 版本更好的性能—同时,客户端应用程序本身必须负责资源管理、同步, DirectX 12 在游戏和其他图形应用程序中迅速发展。
光流 SDK 3 . 0 支持 DirectX 12 应用程序使用 NVIDIA 光流引擎。计算出的光流可用于提高游戏和视频中的帧速率,以获得更平滑的体验或用于目标跟踪。为了提高帧速率, F rame R ate U p C onversion ( FRUC )技术通过在原始帧之间插入插值帧来使用。插值算法使用帧对之间的流来生成中间帧。
光流硬件的所有代支持 DirectX 12 光流接口。光流 SDK 包包含头( S )、演示使用的示例应用程序、可根据需要重新使用或修改的 C ++包装类和文档。用于访问光流硬件的所有其他组件都包含在 NVIDIA 显示驱动程序中。 Windows 20H1 或更高版本的操作系统支持 DirectX 12 光流 API 。
除了显式同步之外, directx12 光流 API 的设计与 SDK 中已有的其他接口( CUDA 和 DirectX 11 )非常接近, DirectX 12 光流 API 由初始化、流量估计和销毁三个核心功能组成。
typedef NV_OF_STATUS(NVOFAPI* PFNNVOFINIT) (NvOFHandle hOf, const NV_OF_INIT_PARAMS* initParams); typedef NV_OF_STATUS(NVOFAPI* PFNNVOFEXECUTED3D12) (NvOFHandle hOf, const NV_OF_EXECUTE_INPUT_PARAMS_D3D12* executeInParams, NV_OF_EXECUTE_OUTPUT_PARAMS_D3D12* executeOutParams); typedef NV_OF_STATUS(NVOFAPI* PFNNVOFDESTROY) (NvOFHandle hOf);
初始化和销毁 API 在所有接口上都是相同的,但在 DirectX 12 和其他接口(即 DirectX 11 和 CUDA )之间执行 API 是不同的。尽管在 DirectX 12 中传递给 executeapi 的大多数参数与其他两个接口中的参数相同,但在功能上还是存在一些差异。 DirectX 11 和 CUDA 接口中的同步由操作系统运行时和驱动程序自动处理。但是,在 DirectX 12 中,需要有关围栏和围栏值的附加信息作为执行 API 的输入参数。这些围栏对象将用于同步 CPU ↔ GPU 和 GPU ↔ GPU 操作。有关详细信息,请参阅光流 SDK 附带的编程指南。
DirectX 12 中的缓冲区管理 API 接口也需要 fence 对象来进行同步。
所有接口的光流输出质量相同。与其他两个接口相比, DirectX 12 的性能应该非常接近。
正反向光流
没有一种光流算法能给出 100% 的准确流量。在闭塞区域,流动通常是扭曲的。有时, NVOA 提供的成本也可能不代表流动的真实可信度。通常采用的一个简单检查是比较向前和向后流动。如果正向流和反向流之间的欧氏距离超过阈值,则该流可以标记为无效。
为了估计两个方向上的流,客户机必须调用 Execute API 两次:一次调用输入和引用图像,第二次调用在反转输入和引用图像之后。像这样两次调用 Optical Flow Execute API 可能会由于上下文切换、线程切换等开销而导致性能不佳。 Optical Flow sdk3 . 0 公开了一个新的 API ,以便在单个 Execute 调用中生成双向流。可以通过在初始化中设置 NV_OF_INIT_PARAMS::predDirection to NV_OF_PRED_DIRECTION_BOTH
并在 NV_OF_EXECUTE_OUTPUT_PARAMS/NV_OF_EXECUTE_OUTPUT_PARAMS_D3D12::bwdOutputBuffer, NV_OF_EXECUTE_OUTPUT_PARAMS/NV_OF_EXECUTE_OUTPUT_PARAMS_D3D12::bwdOutputCostBuffer
.
中提供接收反向流和/或开销所需的缓冲区来启用此功能
一旦在两个方向上生成流,客户端应用程序就可以比较两个方向的流向量,根据适当的标准(例如,向前和向后流向量之间的欧几里德距离)丢弃不准确的流向量,并使用孔填充算法来填充这些丢弃的流向量。
注意,由于一些优化, FB 流的输出质量可能不同于单向流。
演示 FB flow API 编程和一致性检查的示例代码:
// Initialization of API NV_OF_INIT_PARAMS initParams = { 0 }; ... initParams.predDirection = NV_OF_PRED_DIRECTION_BOTH; ... NvOFAPI->nvOFInit(hNvOF, &initParams); // Estimation of forward and backward flow NV_OF_EXECUTE_INPUT_PARAMS executeInParams = { 0 }; ... NV_OF_EXECUTE_OUTPUT_PARAMS executeOutParams = { 0 }; ... executeOutParams.outputBuffer = forwardFlowBuffer; executeOutParams.outputCostBuffer = forwardFlowCostBuffer; executeOutParams.bwdOutputBuffer = backwardFlowBuffer; executeOutParams.bwdOutputCostBuffer = backwardFlowCostBuffer; NvOFAPI->nvOFExecute(hNvOF, &executeInparams, &executeOutParams) // Invalidating flow vectors for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // read forward flow vector float mvx = GetFlowX(forwardFlowBuffer, x, y); float mvy = GetFlowY(forwardFlowBuffer, x, y); // derive the corresponding position in the backward flow (assuming 1x1 grid size) // and read the backward flow vector int x2 = x + mvx; int y2 = y + mvy; if (x2 < 0 || x2 > width - 1 || y2 < 0 || y2 < height - 1) { SetFlowInvalid(forwardFlowBuffer, x, y); continue; } float mvx2 = -1 * GetFlowX(backwardFlowBuffer, x2, y2); float mvy2 = -1 * GetFlowY(backwardFlowBuffer, x2, y2); // mark flow vector as invalid if the distance is greater than a threshold if (((mvx - mvx2) * (mvx - mvx2) + (mvy - mvy2) * (mvy - mvy2)) > thresh) { SetFlowInvalid(forwardFlowBuffer, x, y); } } }
全球流量估算
视频序列或游戏中的全局流是由摄影机平移运动引起的。全局流估计是一个重要的工具,广泛应用于图像分割、视频拼接或基于运动的视频分析应用中。
全局流矢量也可以启发式地用于计算背景运动。一旦估计出背景运动,它就可以用来填充遮挡区域中的流矢量,也可以用来处理插值帧中扭曲像素的碰撞。
全局流量是基于发生频率和其他一些启发式算法,在前向流矢量上计算的。
为了能够生成全局流,初始化 API 需要设置标志 初始化参数的 NV \ u :: enableGlobalFlow ,并在 executeapi 中提供额外的缓冲区 NV _ OF _ EXECUTE _ OUTPUT _ PARAMS / NV _ OF _ EXECUTE _ OUTPUT _ PARAMS _ D3D12 ::全局流缓冲区 。
参考
- NVIDIA 光流 SDK
- 开发者博客: NVIDIA 光流 SDK 简介
- 开发者博客: 用 NVIDIA 图灵 GPU s 加速 OpenCV :光流算法