下载本文的 PDF 版本 PDF

OpenCV 实时计算机视觉

移动计算机视觉技术很快将变得像触摸界面一样普及。


Kari Pulli,NVIDIA Research

Anatoly Baksheev,Itseez

Kirill Kornyakov,Itseez

Victor Eruhimov,Itseez


计算机视觉是一个快速发展的领域,致力于分析、修改和对图像进行高层次的理解。其目标是确定摄像头前正在发生的事情,并利用这种理解来控制计算机或机器人系统,或为人们提供比原始相机图像更具信息性或更美观的新图像。计算机视觉技术的应用领域包括视频监控、生物识别、汽车、摄影、电影制作、网络搜索、医学、增强现实游戏、新型用户界面等等。

现代相机能够自动对焦人脸,并在他们微笑时触发快门。光学文本识别系统帮助将扫描文档转换为可以由语音合成器分析或朗读的文本。汽车可能包含自动化驾驶员辅助系统,帮助用户停车或警告他们潜在的危险情况。智能视频监控在公共区域的安全监控中发挥着越来越重要的作用。

随着智能手机和平板电脑等移动设备配备摄像头和更强的计算能力,对计算机视觉应用的需求正在增加。这些设备已经变得足够智能,可以将多张照片合并成高分辨率全景图,或者读取二维码,识别它,并从互联网检索有关产品的信息。移动计算机视觉技术很快将变得像触摸界面一样普及。

然而,计算机视觉在计算上是昂贵的。即使是专门解决非常具体问题的算法,例如全景拼接或面部和微笑检测,也需要大量的算力。许多计算机视觉场景必须实时执行,这意味着单个帧的处理应在 30-40 毫秒内完成。这是一个非常具有挑战性的要求,特别是对于移动和嵌入式计算架构而言。通常,可以在质量和速度之间进行权衡。例如,全景拼接算法可以在源图像中找到更多匹配项,并在给定更多计算时间的情况下合成更高质量的图像。为了满足时间和计算预算的约束,开发人员要么在质量上妥协,要么投入更多时间来优化特定硬件架构的代码。

视觉和异构并行计算

过去,提高计算设备性能的一种简单方法是等待半导体工艺的改进,这导致设备时钟速度的提高。当时钟速度提高时,所有应用程序都会变得更快,而无需程序员修改它们或它们所依赖的库。不幸的是,那些日子已经结束了。

随着晶体管变得更密集,它们也会泄漏更多电流,因此能源效率降低。提高能源效率已成为重要的优先事项。现在的工艺改进允许每单位面积容纳更多的晶体管,并且有两种主要方法可以充分利用它们。第一种是通过并行化:创建更多相同的处理单元,而不是使单个单元更快更强大。第二种是通过专业化:构建特定领域的硬件加速器,可以更有效地执行特定类别的功能。将这两种思想结合起来的概念——即,将 CPU 或 CPU 与各种加速器一起运行——称为异构并行计算。

高级计算机视觉任务通常包含可以在专用硬件架构上比在 CPU 上更快运行的子任务,而其他子任务则在 CPU 上计算。例如,GPU(图形处理单元)是一种加速器,现在在每台台式计算机以及智能手机和平板电脑等移动设备上都可用。

图形硬件

第一个 GPU 是固定功能流水线,专门用于加速在计算机显示器上绘制形状,如图 1 所示。随着 GPU 获得使用彩色图像作为纹理映射输入的能力,并且它们的结果可以与 CPU 共享,而不仅仅是发送到显示器,使用 GPU 进行简单的图像处理任务成为可能。

通过添加着色器使固定功能 GPU 部分可编程是一个巨大的进步。这使程序员能够编写特殊的程序,这些程序由 GPU 在表面的每个三维点以及渲染到输出画布上的每个像素上运行。这极大地扩展了 GPU 的处理能力,聪明的程序员开始尝试在 GPU 上进行通用计算 (GPGPU),利用图形加速器执行最初并非为此设计的任务。GPU 成为图像处理和计算机视觉任务的有用工具。

然而,图形着色器没有提供对许多有用的硬件功能(例如同步和原子内存操作)的访问。现代 GPU 计算语言(例如 CUDA、OpenCL 和 DirectCompute)被明确设计为支持在图形硬件上进行通用计算。GPU 仍然不如 CPU 那么灵活,但它们执行并行流处理的效率更高,并且越来越多的非图形应用程序正在使用 GPU 计算语言重写。

计算机视觉是通常自然映射到 GPU 的任务之一。这并非巧合,因为计算机视觉解决了计算机图形问题的逆问题。图形将场景或对象描述转换为像素,而视觉将像素转换为更高级别的信息。GPU 包含许多相似的处理单元,并且在执行简单、相似的子任务(例如渲染或过滤像素)方面非常有效。此类任务通常被称为“令人尴尬的并行”,因为它们非常容易在 GPU 上高效并行化。

然而,许多任务不容易并行化,因为它们包含串行段,其中后续阶段的结果取决于早期阶段的结果。这些串行算法在 GPU 上无法高效运行,并且更易于编程,并且通常在 CPU 上运行速度更快。许多迭代数值优化算法和基于堆栈的树搜索算法都属于此类。

由于许多高级任务由并行和串行子任务组成,因此可以通过在 CPU 上运行某些组件,在 GPU 上运行其他组件来加速整个任务。不幸的是,这引入了两个效率低下的来源。一个是同步:当一个子任务依赖于另一个子任务的结果时,后续阶段需要等待前一阶段完成。另一个效率低下是 GPU 和 CPU 内存之间来回移动数据的开销——并且由于计算机视觉任务需要处理大量像素,这可能意味着来回移动大量数据块。这些是在具有 CPU 和 GPU 的系统上加速计算机视觉任务的关键挑战。

OPENCV 库

OpenCV,开源计算机视觉库,最初是英特尔在 1998 年的一个研究项目。5 自 2000 年以来,它以 BSD 开源许可证提供。OpenCV 的目标是提供解决计算机视觉问题所需的工具。它包含低级图像处理功能和高级算法的混合,例如人脸检测、行人检测、特征匹配和跟踪。该库已被下载超过 300 万次。

2010 年,OpenCV 添加了一个提供 GPU 加速的新模块。GPU 模块涵盖了库的大部分功能,并且仍在积极开发中。它使用 CUDA 实现,因此受益于 CUDA 生态系统,包括 NPP(NVIDIA 性能原语)等库。

GPU 模块允许用户从 GPU 加速中受益,而无需接受 GPU 编程方面的培训。该模块与 CPU 版本的 OpenCV 兼容,这使得采用变得容易。但是,存在一些差异,其中最重要的是内存模型。OpenCV 实现了一个名为 cv::Mat 的图像容器,该容器公开了对图像原始数据的访问。在 GPU 模块中,容器 cv::gpu::GpuMat 将图像数据存储在 GPU 内存中,并且不提供对数据的直接访问。如果用户想要修改在 GPU 上运行的主程序中的像素数据,他们首先需要将数据从 GpuMat 复制到 Mat。

#include <opencv2/opencv.hpp> #include <opencv2/gpu/gpu.hpp>
using namespace cv;
...
Mat image = imread("file.png");
gpu::GpuMat image_gpu;
image_gpu .upload(image);
gpu::GpuMat result;
gpu::threshold(image_gpu, result, 128, CV_THRESH_BINARY);
result.download(image);
imshow("WindowName", image);
waitKey ();

在此示例中,从文件中读取图像,然后将其上传到 GPU 内存。图像在那里进行阈值处理,结果被下载到 CPU 内存并显示。在这个简单的例子中,只对图像执行了一个操作,但可以在 GPU 上执行其他几个操作,而无需来回传输图像。对于已经熟悉 OpenCV 的人来说,GPU 模块的用法很简单。

这种设计为用户提供了对数据如何在 CPU 和 GPU 内存之间移动的显式控制。虽然用户必须编写一些额外的代码才能开始使用 GPU,但这种方法既灵活又允许更高效的计算。总的来说,最好使用 OpenCV 的 CPU 部分研究、开发和调试计算机视觉应用程序,然后使用 GPU 模块加速它。开发人员应尝试 CPU 和 GPU 处理的不同组合,测量其时序,然后选择性能最佳的组合。

给开发人员的另一个建议是使用 CUDA 和 GPU 模块提供的异步机制。这允许数据传输、GPU 处理和 CPU 计算同时执行。例如,当 GPU 处理来自摄像头的某个帧时,下一个帧会被上传到 GPU,从而最大限度地减少数据传输开销并提高整体性能。

OPENCV GPU 模块的性能

OpenCV 的 GPU 模块包含大量函数,其中许多函数已以不同的版本实现,例如图像类型(char、short、float)、通道数和边界外推模式。这使得报告准确的性能数字具有挑战性。在提炼性能数字时,增加困难的另一个来源是同步和传输数据的开销。这意味着对于可以在 GPU 上进行大量处理的大图像,可以获得最佳性能。

为了帮助开发人员找出权衡,OpenCV 包含一个性能基准测试套件,该套件使用不同的参数和不同的数据集运行 GPU 函数。这提供了关于不同数据集在用户硬件上加速多少的详细基准。

图 2 是一个基准测试,展示了 GPU 模块的优势。加速是根据 OpenCV 的高度优化的 CPU 实现的基线来衡量的。OpenCV 是使用英特尔的 SSE(流式 SIMD 扩展)和 TBB(线程构建模块)进行多核支持编译的,但并非所有算法都使用它们。原始图像处理加速已在约 30 个函数中平均。还报告了几个高级算法的加速。

对于低级函数,GPU 显示 30 倍的加速是相当正常的,对于高级函数,加速高达 10 倍,后者包括更多的开销和许多不易用 GPU 并行化的步骤。例如,颜色转换的粒度是逐像素的,使其易于并行化。另一方面,行人检测是针对每个可能的行人位置并行执行的,并且并行化每个窗口位置的处理受到片上 GPU 内存量的限制。

作为一个例子,我们加速了 ROS(机器人操作系统)8 中的两个软件包——立体视觉里程计和纹理对象检测——它们最初是为 CPU 开发的。它们包含许多功能块和类层次结构。

在任何有意义的地方,我们都将计算卸载到 GPU。例如,OpenCV GPU 实现执行 SURF(加速鲁棒特征)关键点检测、匹配和立体对应搜索(块匹配)以进行立体视觉里程计。加速后的软件包是 CPU/GPU 实现的混合。结果,视觉里程计管道加速了 2.7 倍,纹理对象检测加速了 1.5 到 4 倍,如图 3 所示。数据传输开销不是总算法运行时的重要组成部分。此示例表明,仅替换几行代码即可显着加速高级视觉应用程序。

使用 GPU 模块的立体对应

高分辨率视频中的立体对应搜索是一个要求苛刻的应用,它演示了如何重叠 CPU 和 GPU 计算。OpenCV 的 GPU 模块包含一个实现,可以在 NVIDIA GTX580 上实时(每秒 24 帧)处理全高清分辨率立体对。

在立体系统中,两个摄像头以相同的方向安装。虽然远处的物体在每个摄像头上都投影到相同的图像位置,但附近的物体会投影到不同的位置。这称为视差。通过为左侧摄像头图像上的每个像素定位同一表面点在右侧图像上投影到的位置,您可以使用视差来计算到该表面点的距离。在立体图像对中找到这些像素之间的对应关系是立体视觉的关键挑战。

通过校正图像可以更容易地完成此任务。校正将图像扭曲为理想的立体对,其中每个场景表面点都投影到匹配的图像行。这样,只需要搜索同一扫描线上的点。通过比较像素小窗口与候选匹配像素的相似性来评估匹配质量。然后,将右侧图像中其窗口与左侧图像上像素的窗口最匹配的像素选择为相应的匹配项。

计算需求显然会随着图像尺寸的增加而增加,因为有更多的像素要处理。在较大的图像中,以像素为单位测量的视差范围也会增加,这需要更大的搜索半径。对于小分辨率图像,CPU 可能足以计算视差;但是,对于全高清分辨率图像,只有 GPU 才能提供足够的处理能力。

图 4 显示了一个块匹配管道,它生成一个视差图像 d(x,y),使得 LeftImage(x,y) 对应于 RightImage(x - d(x,y),y)。该管道首先校正图像,然后找到最佳匹配,如前所述。在纹理很少的区域(例如,空白墙),计算出的匹配不可靠,因此所有此类区域都被标记为在以后的处理中忽略。由于视差值预计仅在对象边界附近发生很大变化,因此散斑过滤阶段消除了视差图像大连续区域内的散斑噪声。不幸的是,散斑过滤算法需要基于堆栈的深度优先搜索,这种搜索很难并行化,因此它在 CPU 上运行。最后,使用伪彩色图像可视化结果。

除了散斑过滤之外的所有步骤都在 GPU 上实现。计算量最大的步骤是块匹配。NVIDIA GTX580 将其加速到比在具有 SSE 和 TBB 优化的四核 Intel i5-760 2.8-GHz 处理器上的 CPU 实现快七倍。在这种加速之后,散斑过滤成为瓶颈,消耗了 50% 的帧处理时间。

一种优雅的并行处理解决方案是在 CPU 上并行于 GPU 处理运行散斑过滤。当 GPU 处理下一帧时,CPU 对当前帧执行散斑过滤。这可以使用异步 OpenCV GPU 和 CUDA 功能来完成。异构 CPU/GPU 系统现在为高分辨率立体对应问题提供了七倍的加速,从而在全高清分辨率下实现了实时(24 fps)性能。

KINECTFUSION

微软的 KinectFusion4 是一个应用程序示例,该应用程序以前需要缓慢的批处理,但现在,在 GPU 的支持下,可以以交互速度运行。Kinect 是一款生成彩色图像和深度图像的摄像头。只需在室内场景周围瞄准 Kinect 设备,就可以惊人地保真地数字化室内场景的 3D 几何形状,如图 5 所示。这种扫描应用程序的开源实现基于点云库6,它是 OpenCV 的配套库,它使用 3D 点和体素而不是 2D 像素作为基本图元。

实现 KinectFusion 并非易事。Kinect 不会返回所有像素的范围测量值,并且仅在连续光滑的哑光表面上可靠地工作。它返回的范围测量值是有噪声的,并且根据表面形状和反射率特性,噪声可能很大。噪声也会随着到测量表面的距离的增加而增加。Kinect 每秒生成 30 个新的深度帧。如果用户移动 Kinect 设备太快,算法会变得混乱,并且无法使用范围数据跟踪运动。然而,通过巧妙地结合良好的算法和使用 GPU 提供的处理能力,KinectFusion 可以稳健地工作。

有三个关键概念使稳健的交互式实现成为可能。首先,跟踪算法能够如此快速地处理新的扫描数据,以至于摄像头在连续帧之间有时间移动非常小的距离。这使得仅使用范围数据跟踪摄像头的位置和方向成为可能。

其次,深度数据的融合是使用体积表面表示完成的。演示文稿是一个大型体素网格,与基于表面的表示相比,它可以更轻松地合并来自不同扫描的数据。为了获得高质量的模型,网格分辨率被选择为尽可能密集 (512x512x512),因此必须由 GPU 处理以实现实时速率。

最后,新数据与旧数据合并的方式会随着收集更多数据而减少噪声和不确定性,并且模型的准确性不断提高。随着模型变得更好,跟踪也变得更容易。通过体积的并行光线投射在 GPU 上完成以获得深度信息,该深度信息用于下一帧的相机跟踪。因此,帧到帧的运动估计仅在第一帧和第二帧之间执行。所有其他运动都在模型到帧数据上计算,这使得相机跟踪非常稳健。

所有这些步骤都是计算密集型的。体积积分需要只有 GPU 才能提供的宽内存带宽,且价格足够低,普通消费者可以承受。如果没有 GPU,这个系统根本不可行。

然而,并非计算的每个步骤都易于在 GPU 上完成。例如,摄像头位置是在 CPU 上跟踪的。虽然摄像头位置估计所需的线性方程矩阵完全在 GPU 上计算,但计算最终解决方案无法很好地并行化,因此它在 CPU 上完成,这会导致一些下载和 API 调用开销。另一个问题是分层图像处理方法中的底层图像仅为 160x120,这不足以完全加载 GPU。所有其他部分都非常适合 GPU,但受到可用 GPU 内存量和计算资源的限制。

进一步的开发需要更强大的 GPU 性能。目前,场景的大小受到体积表示的限制。使用相同数量的体素但使其更大将允许我们捕获更大的场景,但分辨率会降低。在扫描更大的场景时保持相同的分辨率将需要更多的体素,但体素的数量受到 GPU 上可用内存量及其计算能力的限制。

加速移动设备上的计算机视觉

虽然 PC 通常内置了 CPU 和 GPU 两个独立的芯片,但智能手机和平板电脑等移动设备将所有计算元件都放在一个芯片上。这种 SoC(片上系统)包含一个或多个 CPU 和一个 GPU,以及用于音频和视频处理以及数据通信的多个信号处理器。所有现代智能手机和一些平板电脑也包含一个或多个摄像头,并且 OpenCV 在 Android 和 iOS 操作系统上都可用。借助所有这些组件,可以创建移动视觉应用程序。以下部分更详细地介绍了移动硬件,以 NVIDIA 的 Tegra 2 和 Tegra 3 SoC 为例,然后介绍了几个有用的多媒体 API。最后,介绍了两个移动视觉应用程序:全景图创建和视频稳定。

移动计算机视觉工具

任何通用计算机的核心都是 CPU。虽然英特尔的 x86 指令集在台式计算机上占据主导地位,但几乎所有手机和平板电脑都由 ARM 的 CPU 驱动。ARM 处理器遵循 RISC(精简指令集计算)方法,这可以从 ARM 的原名 Advanced Risc Machines 中推断出来。虽然 x86 处理器传统上设计用于高计算能力,但 ARM 处理器主要设计用于低功耗,这对于电池供电设备来说是一个明显的优势。随着英特尔在其面向移动设备的 Atom 系列中降低功耗,以及最近的 ARM 设计变得越来越强大,它们未来可能会达到类似的设计点,至少在移动计算设备的高端领域。Tegra 2 和 Tegra 3 都使用 ARM Cortex-A9 CPU。

手机过去只有一个 CPU,但现代移动 SoC 开始配备多个 CPU,提供对称多处理。原因是节能的潜力。使用两个以 1 GHz 运行的内核比使用一个以 2 GHz 运行的内核可以达到大致相似的性能水平。由于功耗随着时钟速度呈超线性增长,因此这两个较慢的内核的总功耗低于单个更快的内核。Tegra 2 提供两个 ARM 内核,而 Tegra 3 提供四个。Tegra 3 实际上包含五个(四个加一个)内核,其中可以同时激活一个、两个、三个或四个内核。其中一个内核,称为影子或伴随内核,旨在使用特别少的能量,但只能以相对较慢的速度运行。该模式足以满足待机、听音乐、语音通话和其他依赖专用硬件(例如音频编解码器)且仅需要少量 CPU 周期的应用程序的需求。当需要更多处理能力时(例如,阅读电子邮件),较慢的内核被更快的内核之一取代,并且为了提高性能(浏览、游戏),额外的内核会启动。

SIMD(单指令,多数据)处理对于像素数据特别有用,因为相同的指令可以同时用于多个像素。SSE 是英特尔的 SIMD 技术,它存在于所有现代 x86 芯片中。ARM 有一项类似的技术,称为 NEON,它是 Cortex A9 中的可选协处理器。NEON 可以同时处理多达八个甚至 16 个像素,而 CPU 一次只能处理一个元素。这对计算机视觉开发人员非常有吸引力,因为它通常很容易获得三到四倍的性能加速——通过仔细优化甚至可以获得超过六倍的加速。Tegra 2 不包含 NEON 扩展,但 Tegra 3 的每个 ARM 内核都有一个 NEON 协处理器。

所有现代智能手机都包含 GPU。第一代移动 GPU 实现了 OpenGL ES 1.0 和 1.1 的固定功能图形流水线。即使 GPU 是为 3D 图形设计的,它们也可以用于有限类别的图像处理操作,例如扭曲和混合。当前的移动 GPU 更加灵活,并支持使用 OpenGL ES 2.0 API 的 GLSL(OpenGL 着色语言)编程,允许程序员在每个像素上运行相当复杂的着色器。因此,大约 10 年前为台式 GPU 开发的许多老式 GPGPU 技巧现在可以在移动设备上重用。更灵活的 GPU 计算语言(例如 CUDA 和 OpenCL)将在未来几年取代这些技巧,但目前尚不可用。

音频和视频内容的消费和创建是现代移动设备上的重要用例。为了支持它们,智能手机包含专用的硬件编码器和解码器,用于音频和视频。此外,许多设备都有一个特殊的 ISP(图像信号处理器),用于处理从摄像头流出的像素。这些媒体加速器不像计算机视觉处理那样容易访问和有用,但 OpenMAX 标准有所帮助。1 OpenMAX 定义了三个不同的层:AL(应用程序)、IL(集成)和 DL(开发)。最低层 DL 规定了来自五个领域的原始函数集:音频、视频和图像编码,以及图像和信号处理。其中一些对于计算机视觉开发人员可能感兴趣,特别是视频编码和图像处理,因为它们提供了许多简单的过滤器、颜色空间转换和算术运算。IL 旨在供系统程序员用于实现多媒体框架,并提供用于诸如摄像头控制等目的的工具。AL 旨在供应用程序开发人员使用,并提供高级抽象和对象,例如摄像头、媒体播放器和媒体录制器。OpenMAX API 可用于在各种加速器和其他 API(例如 OpenGL ES)之间有效地传递图像数据。

传感器为计算机视觉开发人员提供了另一个有趣的机会。许多设备包含传感器,例如加速度计、陀螺仪、指南针和 GPS。它们不能执行计算,但如果应用程序需要重建摄像头方向或 3D 轨迹,则它们可能很有用。从一组帧中提取摄像头运动的问题在性能和准确性方面都具有挑战性。SLAM(同时定位和建图)、SfM(运动结构)和其他方法可以计算摄像头位置,甚至可以计算摄像头看到的物体的形状,但这些方法不易于实现、校准和优化,并且需要大量的处理能力。尽管如此,传感器可以以仅依赖视觉处理的一小部分成本提供相当准确的设备方向估计。为了获得准确的结果,传感器输入应仅用作起点,并使用计算机视觉技术进行细化。

TEGRA 上的 OPENCV

OpenCV 的主要设计和实现目标之一始终是高性能。但是,将 OpenCV 和使用它的应用程序移植到移动设备需要小心,以保持足够的性能水平。OpenCV 从 2010 年 Google Summer of Code 开始在 Android 上可用,当时它首次在 Google Nexus One 上构建和运行。几个演示应用程序展示了几乎实时的行为,但很明显 OpenCV 需要针对移动硬件进行优化和微调。

这就是 NVIDIA 和 Itseez 决定创建 Tegra 优化版本的 OpenCV 的原因。这项工作受益于三个主要的优化机会:使用 NEON 进行代码向量化,使用英特尔 TBB(线程构建模块)库进行多线程处理,以及使用 GLSL 进行 GPGPU。

利用 NEON 指令集是这三个选择中最具吸引力的。图 6 比较了原始版本和 NEON 优化版本的 OpenCV 的性能。一般来说,NEON 需要使用简单且规则的内存访问模式进行基本算术运算。图像处理原语通常满足这些要求,这几乎是 NEON 向量运算加速的理想选择。由于这些原语通常位于高级计算机视觉工作流程的关键路径中,因此 NEON 指令可以显着加速 OpenCV 例程。

在高达四个对称 CPU 上的多线程可以在更高级别上提供帮助。TBB 和其他线程技术使应用程序开发人员能够获得多个 CPU 内核的并行处理优势。在应用程序级别,独立活动可以分布在不同的内核之间,操作系统将负责负载平衡。这种方法与 OpenCV 的多线程通用策略一致——并行化整个算法管道——而在移动平台上,我们通常也必须加速原始函数。

一种方法是将低级函数拆分为几个较小的子任务,这将产生更快的结果。一种流行的技术是将输入图像拆分为几个水平条纹并同时处理它们。另一种方法是创建后台线程并在主程序处理问题的其他部分时稍后获取结果。例如,在视频稳定应用程序中,一个特殊的类会从上一次迭代返回异步计算的结果。多线程将加速因子限制为内核数量,而当前最先进的移动平台上的内核数量为四个,而 NEON 支持对 16 个元素进行向量运算。当然,这两种技术可以结合使用。但是,如果算法受到内存访问速度的限制,则多线程可能无法提供预期的性能提升。例如,cv::resize 的 NEON 版本不会因添加新线程而受益,因为单个线程已经完全消耗了内存总线容量。

在 Tegra 平台 OpenCV 库优化期间应用的最后一种方法是使用 GLSL 着色器的 GPGPU。虽然移动 GPU 具有如前所述的限制,但在某些类别的算法上,GPU 能够显示出令人印象深刻的性能提升,同时消耗非常少的能量。在移动 SoC 上,可以在 CPU 和 GPU 之间共享内存,这允许交错处理同一图像缓冲区的 C++ 和 GLSL。图 7 显示了 OpenCV 库中某些过滤器和几何变换的示例加速。

使用 GPU 的另一个好处是,在全速运行时,它的平均功耗低于 CPU。在移动设备上,这尤其重要,因为消费者主要的可使用性因素之一是电池一次充电的持续时间。我们测量了执行 10,000 次某些优化 C++ 函数的平均功耗和经过的时间,并将其与用 GLSL 编写的相同函数进行了比较。由于这些函数在 GPU 上都更快,并且 GPU 以较低的峰值功率运行,因此结果是显着的节能(参见表 1)。在将这些函数移植到 GPU 时,我们测量了 3-15 倍的节能效果。

应用

我们使用 OpenCV 开发了两个移动视觉应用程序:一个应用程序将多张普通照片拼接成一张全景图像,另一个应用程序稳定流式视频。性能要求具有挑战性。我们的目标是实时性能,其中每个帧应在大约 30 毫秒内处理完毕,其中诸如简单复制 1280x720 像素帧之类的基本操作可能需要 8 毫秒。因此,在很大程度上,应用程序的最终设计及其底层算法由此约束决定。

在这两种情况下,我们都能够通过使用 GPU 优化应用程序的瓶颈来满足时间限制。一些几何变换函数,例如图像大小调整和各种类型的图像扭曲,已移植到 GPU,使应用程序的性能提高了一倍。当使用 NEON 和多线程执行相同的任务时,结果远没有那么好。原因之一是这两个应用程序都处理高分辨率四通道图像。结果,内存总线过载,CPU 内核争夺缓存内存。与此同时,我们需要手动编程双线性插值;此过程在 GPU 硬件中实现。我们了解到,CPU 在全帧几何变换方面效果不佳,而 GPU 的帮助是无价的。让我们更详细地考虑这两个应用程序。

全景拼接

在全景拼接应用程序中,我们的目标是将多张普通图像组合成一张全景图,该全景图具有比输入图像大得多的 FOV(视场)。7 图 8 展示了将多张详细照片拼接成一张整个图像的高分辨率图像。

图 9 展示了 OpenCV 全景拼接应用程序的处理流程。移植到 Tegra 的过程始于一些算法改进,随后进行了 NEON 和多线程优化;然而,经过所有这些努力,该应用程序仍然不够响应迅速,无法以交互速度拼接和预览最终的全景图。主要的瓶颈包括图像缩放和变形。之所以需要缩放,是因为不同的算法步骤在不同的分辨率下执行,并且每个输入帧会根据算法参数进行大约三次缩放。所需的变形类型取决于所需的投影模式(球形、圆柱形等),并且图像在最终全景图混合之前会进行变形。

借助 GPU 版本的 cv::resize,我们能够将每个输入帧的缩放时间从 41 毫秒减少到 26 毫秒,相当于 1.6 倍的局部加速。由于图像变形的 GPU 实现,我们可以获得更好的局部改进——性能提升 8-14 倍,具体取决于投影类型。结果,应用程序的总加速比为 1.5-2.0 倍,满足了性能要求。

视频稳定

不使用三脚架录制视频的负面后果之一是相机抖动,这会显著降低观看体验。为了获得视觉上令人愉悦的效果,所有运动都应平滑,并且需要过滤相机方向和平移中的高频变化。已经开发了许多方法,其中一些已成为开源或商业可用的工具。存在离线计算密集型方法,需要大量时间,而轻量级在线算法更适合移动设备。高端方法通常会重建相机的 3D 运动并应用复杂的非刚性图像变形来稳定视频。2 在移动设备上,使用平移、仿射变形或平面透视变换等更轻量级的方法可能更有意义。3

我们尝试了平移和仿射模型,在这两种情况下,GPU 都能够消除主要热点,即将补偿变换应用于输入帧。平移以补偿运动仅意味着沿 X 轴和 Y 轴移动输入帧,并裁剪掉一些边界区域,其中一些帧现在不包含颜色信息(参见图 10)。

在编程方面,应该选择一个位置合适的子矩阵,然后将其缩放到与原始视频流相同分辨率的新图像中,如图 11 所示。令人惊讶的是,这个简单的步骤消耗了 140 多毫秒。我们的 GPU GLSL 实现比 C++ 快五到六倍,耗时约 25 毫秒。

然而,25 毫秒对于实时算法来说仍然太长,这就是为什么我们接下来尝试从异步调用中获得更多速度。创建了一个特殊的类用于在 GPU 上稳定帧。该类立即从其图像缓冲区字段中存储的先前迭代返回结果,并创建一个 TBB::task 用于处理下一帧。因此,GPU 处理在后台执行,并且对于调用者而言,表面成本和延迟等于仅复制完整帧。这个技巧也应用于昂贵的颜色转换过程,并且通过进一步优化内存访问模式,我们实现了实时处理性能。

未来方向

GPU 最初是为了加速将 3D 场景描述转换为 2D 图像以实现交互速率而开发的,但随着它们变得更可编程和灵活,它们也被用于执行相反的任务,即处理和分析 2D 图像和图像流以创建 3D 描述,控制某些应用程序以便它们可以对用户或环境中的事件做出反应,或者仅仅是为了创建更高质量的图像或视频。随着计算机视觉应用程序变得越来越普遍,看看是否会创建一种不同类型的计算机视觉处理器,它将更适合与 GPU 一起进行图像处理,或者 GPU 是否仍然适合这项任务,这将很有趣。当前的移动 GPU 还没有像大型计算机上的 GPU 那样灵活,但这很快就会改变。

OpenCV(以及其他相关的 API,如 Point Cloud Library)使应用程序开发人员更容易使用计算机视觉。它们是文档完善且充满活力的开源项目,不断发展,并且正在适应新的计算技术。这种演变的例子包括 OpenCV 中从 C 到 C++ API 的过渡以及 OpenCV GPU 模块的出现。然而,OpenCV 的基本架构主要是以 CPU 为中心设计的。也许现在是时候设计一种新的 API,明确考虑异构多处理,其中主程序可以在一个 CPU 或多个 CPU 上运行,而视觉 API 的主要部分可以在不同类型的硬件上运行:GPU、DSP(数字信号处理器),甚至专用视觉处理器。事实上,Khronos 最近已经开始开发这样一种 API,它可以作为一个抽象层,允许硬件方面的独立创新,并允许在这一层之上开发诸如 OpenCV 之类的高级 API,同时在某种程度上与底层硬件架构的变化隔离开来。

致谢

我们要感谢同事们在数值实验和建设性讨论方面的帮助;感谢 Colin Tracey 和 Marina Kolpakova 在功耗分析方面的帮助;感谢 Andrey Pavlenko 和 Andrey Kamaev 提供的 GLSL 和 NEON 代码;感谢 Shalini Gupta、Shervin Emami 和 Michael Stewart 提供的额外评论。NVIDIA 提供了支持,例如实验中使用的所有硬件。

参考文献

1. Khronos OpenMAX 标准; http://www.khronos.org/openmax

2. Liu, F., Gleicher, M., Wang, J., Jin, H., Agarwala, A. 2011. Subspace video stabilization. Transactions on Graphics 30(1):4:1–4:10.

3. Matsushita, Y., Ofek, E., Ge, W., Tang, X., Shum, H.-Y. 2006. Full-frame video stabilization with motion inpainting. IEEE Transactions on Pattern Analysis and Machine Intelligence 28(7):1150–1163.

4. Newcombe, R. A., Izadi, S., Hilliges, O., Molyneaux, D., Kim, D., Davison, A. J., Kohli, P., Shotton, J., Hodges, S., Fitzgibbon, A. W. 2011. Kinectfusion: Real-time dense surface mapping and tracking. IEEE International Symposium on Mixed and Augmented Reality (ISMAR): 127–136.

5. OpenCV 库; http://code.opencv.org

6. Point Cloud Library; http://pointclouds.org

7. Szeliski, R. 2006. Image alignment and stitching: a tutorial. Foundations and Trends in Computer Graphics and Vision 2(1):1–104.

8. Willow Garage. Robot Operating System; http://www.ros.org/wiki/

喜欢还是讨厌?请告诉我们

[email protected]

KARI PULLI 是 NVIDIA Research 的高级主管,在那里他领导移动视觉计算研究团队,并研究与移动设备上的摄像头、成像和视觉相关的主题。此前,他在诺基亚工作,是第六位诺基亚院士和 CEO 技术委员会成员。他曾在 Khronos 和 JCP 参与移动媒体 API 标准化工作,并曾担任斯坦福大学数字米开朗基罗项目的技术主管。他拥有明尼苏达大学的理学学士学位,奥卢大学(芬兰)的理学硕士和技术执照学位,以及华盛顿大学(西雅图)的博士学位,所有学位均为计算机科学/工程专业;以及奥卢大学的 MBA 学位。他是 Mobile 3D Graphics (Morgan Kaufmann, 2007) 的作者。

ANATOLY BAKSHEEV 是 Itseez 的项目经理。他于 2006 年在那里开始了他的职业生涯,并且是多投影仪系统 Argus Planetarium 的首席开发人员。2008 年,他在 OpenCV 团队担任高级工程师。自 2010 年以来,他一直担任 OpenCV GPU 项目的负责人,该项目将计算密集型视觉算法引入 GPU。他担任 OpenCV GPU 模块的架构师和首席开发人员,并于 2011 年开始从事 Point Cloud Library 的 GPU 加速模块的开发。Anatoly 毕业于俄罗斯下诺夫哥罗德州立大学,获得计算机科学硕士学位。

KIRILL KORNYAKOV 是 Itseez 的项目经理,在那里他领导移动设备的 OpenCV 库的开发。他管理移动操作系统支持和计算机视觉应用程序开发方面的活动,包括 NVIDIA Tegra 平台的性能优化。他还从事开源和商业产品的实时计算机视觉系统开发,其中包括 GPU 上的立体视觉和复杂环境中的人脸检测。Kirill 拥有俄罗斯下诺夫哥罗德州立大学的理学学士和硕士学位。

VICTOR ERUHIMOV 是 Itseez 的首席技术官。在共同创立公司之前,他曾在英特尔担任项目经理和高级研究科学家,在那里他应用计算机视觉和机器学习方法来自动化英特尔工厂并彻底改变半导体制造中的数据处理。在加入制造部门之前,他一直在开发用于人体运动捕捉、图像检索、超分辨率和人脸分析的技术。他是 20 多篇计算机视觉和机器学习论文的作者,并拥有多项美国和国际专利。

© 2012 1542-7730/12/0400 $10.00

acmqueue

最初发表于 Queue vol. 10, no. 4
数字图书馆 中评论本文





更多相关文章

Vinnie Donati - 推动组织可访问性
在本文中,我们将探讨 Microsoft 如何在其整个组织中推动可访问性,并将仔细研究促进包容性文化的基本框架和实践。通过检查意识建设、战略发展、可访问性成熟度建模等方面,我们的目标是为开始可访问性之旅的组织提供指南。我们的想法是分享我们所学到的知识,希望您可以借鉴它,对其进行调整以适应您公司的宗旨,并以一种不仅仅是复选框活动,而是真正融入您文化的方式来培养可访问性。


Shahtab Wahid - 设计系统是可访问性交付工具
设计系统是为消费者(设计师和开发人员)构建的基础设施,他们致力于应用程序。一个成功的设计系统允许组织中的消费者快速扩展跨应用程序的设计和开发,提高生产力并建立一致性。然而,许多消费者并没有准备好为可访问性而构建。组织能否使应用程序的可访问性支持构建变得可扩展、高效且一致?本文探讨了设计系统如何成为支持可访问性的重要工具。


Juanami Spencer - 移动应用程序的可访问性考虑
在创建移动应用程序时,考虑可访问性至关重要,以确保尽可能广泛的受众可以使用和享受它们。与桌面体验相比,移动可访问性有其独特的考虑因素,但它为那些在日常活动中依赖移动设备的用户提供了巨大的价值。通过牢记这些考虑因素,移动产品开发团队可以更好地支持和改善所有用户的生活。本文探讨了移动应用程序的一些关键可访问性考虑因素,并重点介绍了 Bloomberg Connects 应用程序如何在产品和流程中支持可访问性的几种方式。


Chris Fleizach, Jeffrey P. Bigham - 系统级可访问性
本文通过我们使 iPhone 能够使用 VoiceOver 屏幕阅读器进行非视觉使用的工作来说明系统级可访问性。我们为非视觉使用重新构想了触摸屏输入,引入了适用于屏幕阅读器控制的新手势,并且对于输出,我们添加了对合成语音和可刷新盲文显示器(输出触觉盲文字符的硬件设备)的支持。我们添加了新的可访问性 API,应用程序可以采用这些 API,并使我们的用户界面框架默认包含它们。最后,我们添加了一个可访问性服务,以桥接这些新的输入和输出与应用程序之间。





© 保留所有权利。

© . All rights reserved.