计算机视觉life”,选择“星标”
快速获得最新干货
前言本文分享一篇关于opencv高性能计算基础的文章,这是一个知乎作者对工作期间使用OpenCV和CUDA开发高性能算法库的过程所涉及到的知识要点和踩坑的记录,将会涉及OpenCV, CUDA和C++的一些知识。
作者:风暴洋@知乎,编辑:CV技术指南
文章仅用于学术分享。
OpenCV加速模块
OpenCV是一套Apache 2协议的C++开源库,涉及图像处理、三维重建、人工智能等领域。这些领域都对性能有着严苛的要求。OpenCV在不断的迭代中,逐渐向几个方向扩展着其计算能力,下面以OpenCV中每个方向对应的类为锚进行列举:
内存的管理是几乎每个C++项目都要谨慎考虑的问题。OpenCV中有一套高效易用的内存管理体系,使得多数情况下内存的管理不会成为效率的额外负担。此外,一些特性可能会使用户的代码产生意外的结果,有必要在用OpenCV进行开发前进行详细的了解。
引用计数
OpenCV中的各种Mat类可能具有多种含义:它们既可以用来表示一副BGR图像,也可以用来保存浮点型的视差值或者某个图像一个ROI区域的临时表示。不幸的是,这些数据通常都较大,如果经常进行深拷贝会对程序性能造成严重影响。在CUDA上,内存分配甚至可能远比Kernel耗时。对此,OpenCV的策略是,cv::Mat类以及cv::cuda::GpuMat类对同类型实例的拷贝构造函数,operator= 重载以及ROI区域截取均为浅拷贝操作,并用简单的引用计数管理共享的内存。需要注意的是,这与写时复制 (COW) 不同,OpenCV无法判断Mat的数据何时被写入,如果改变了一个副本data指针所指向的数据而在此之前没有调用create等函数改变data指针本身的值,那么所有副本的数据都会发生变化。实现Mat类的深拷贝,可以使用copyTo和clone等函数。一些常见情况如下所示:
cv::Mat src( 100, 100, CV_32FC1); //原始矩阵
cv::Mat shared1(src); //共享了内存
cv::Mat shared2 = src; //共享了内存
cv::Mat shared3(src(cv::Rect( 10, 10, 10, 10))); //共享了内存
cv::Mat independent1 = src.clone; //申请了新的内存
cv::Mat independent2;
src.copyTo(independent2); //申请了新的内存
create
在图像处理领域,存在大量类似“连续对许多尺寸和类型相同但内容不同的数据进行相同操作”的算法,如实时的深度计算或神经网络的连续推理。以Guided Filter为例,其流程如下[1]:
Guided Filter
其中I, p是输入数据,q是输出数据,中间会产生许多尺寸相同的临时对象。对于其中的每一个步骤以及算法整体,输出矩阵的尺寸仅和当前的输入相关。当中间变量的生命周期足够长(如作为成员变量时),我们有两种内存分配策略:
第一种方法使得用户可以完全控制内存分配的时机,提升程序内存和效率的稳定性;而第二种方法对于用户来说十分简单快捷,能够自动适应不同的输入。
事实上第二种方法是OpenCV对绝大多数函数参数中的 cv::OutputArray (作为输出参数的 cv::Mat 等数据结构的代理) 所采用的方法,拜其所赐我们免去了在调用OpenCV函数前对dst进行手动分配的麻烦。对于cv::Mat和cv::cuda::GpuMat,此操作由create成员函数执行,其简化的源码如下:
void cv::cuda::GpuMat::create(int _rows, int _cols, int _type) {
if(rows == _rows && cols == _cols && type == _type && data) return; //尺寸符合条件时直接返回
if(data) release; //减少引用计数
allocator->allocate(this, rows, cols, esz); //重新分配内存,data将指向新的空间
if(refcount) *refcount = 1; //为新分配的空间启用引用计数
}
可见,当实例目前的尺寸符合要求时,create将会立刻返回。假设用户对同一个cv::Mat进行了100次blur (not-in-inplace),那么只有第一次blur会申请内存。
临时缓冲区优化
由于OpenCV的算法大部分以单独的函数而非类形式提供,无法完全避免中间变量的内存分配,OpenCV提供了一些机制以减小使用临时缓冲区的代价。
理论部分到此为止,后续会更新使用OpenCV CUDA模块进行开发的一些心得。
[1] K. He, J. Sun. Fast Guided Filter.
独家重磅课程!
1、机器人导航运动规划: 运动规划和SLAM什么关系?
2、详解Cartographer: 谷歌开源的激光SLAM算法Cartographer为什么这么牛X?
3、深度学习三维重建 详解深度学习三维重建网络:MVSNet、PatchMatchNet、JDACS-MS
4、三维视觉基础 详解视觉深度估计算法(单/双目/RGB-D+特征匹配+极线矫正+代码实战)
5、视觉SLAM必备基础 SLAM的第一个实践,最适合学哪个开源框架 ?
6、 VINS:Mono+Fusion SLAM面试官:看你简历上写精通VINS,麻烦现场手推一下预积分!
7、VIO进阶:ORB-SLAM3(单/双目/RGBD+鱼眼+IMU紧耦合+多地图+闭环)独家70+讲全部上线!
8、图像三维重建课程:视觉几何三维重建教程(第2期):稠密重建,曲面重建,点云融合,纹理贴图
9、重磅来袭!基于LiDAR的多传感器融合SLAM 系列教程:LOAM、LeGO-LOAM、LIO-SAM
10、系统全面的相机标定课程:单目/鱼眼/双目/阵列 相机标定:原理与实战
联系人:徐经理
手机:13907330718
电话:0731-22222718
邮箱:hniatcom@163.com
地址: 湖南省株洲市石峰区联诚路79号轨道智谷2号倒班房6楼603室