OpenCV-python DNN模块使用CUDA加速
背景
众所周知,Opencv底层是用C++编写的,大家使用最多的肯定也是在该语言下。尤其在使用CUDA加速模型推断这一块。这不由发问,难道Python就不能了吗?况且好多深度学习框架还是用Python编写。因此,这里为了相应Python的强大功能。记录一下如何用CUDA加速DNN推断过程。
问题的由来
相信有好多朋友都习惯使用Opencv自带的CUDA加速功能,通过设置:
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)
来实现CUDA加速,但是很多情况下会遇到下面的情况:
Net::Impl::setUpNet DNN module was not built with CUDA backend; switching to CPU
这时候估计很纳闷,为什么我的有GPU也有相应的CUDA环境为什么不能使用CUDA加速呢。这是由于使用官方的OpenCV-python默认是CPU版本的,没有CUDA加速功能(我一直很纳闷为什么不发布编译后的CUDA版本呢)。所以,不能很轻松的去实现CUDA加速模型推理。那难道我们使用Python就不能实现CUDA加速模型推理了吗?答案明显是否定的。下面通过一系列步骤来实现Opencv DNN模块的CUDA加速
编译Opencv-python CUDA版本
1 下载源码
这里需要下载OpenCV和opencv_contrib的源代码,下载地址如下:
https://github.com/opencv/opencv
https://github.com/opencv/opencv_contrib
将源码下载后并解压到文件夹,按如下的项目结构:
opencv
----build #用来存放编译的文件
----source
-------opencv#解压的OpenCV项目
-------opencv_contrib#解压OpenCV-contrib项目
2 CMAKE编译
这里默认你已经安装了CMAKE这个编译工具了,下面就是对CMAKE进行一些配置操作了,配置如下:
其中source code这里一定要填写的是opencv源码的根目录,build the binaries这里则是在opencv根目录下新建的编译目录。
下面就是这样的一些配置,根据自己的需求去选择VS版本和平台,其它默认就可以了。
2.1 重要的参数选择
这里有几个选项一定要勾选这是我们能成功的关键。
这个WITH_CUDA一定要勾选上,WITH_CUDNN也一定要勾选上。
这几个OpenCV DNN的选项也一定要勾选上。
这个OPENCV_ENABLE_NONFREE一定要勾选上,我第一次没有勾选。编译不报错但是OpenCV不能使用。
这里重点要强调的是,是OPENCV_EXTRA_MODULES_PATH这个选项,这里就是我们上面下载的opencv_contrib源码,但是这里到modules文件夹即可。还有一个就是CUDA_ARCH_BIN这个选项去选择,这个可以从官网去查询自己卡的算力,这里只保留自己的算力,其它值删除即可。
下面的OpenCV一些路径配置,只需配置自己的OpenCV地址即可,按照自己的路径去修改。
下面就去点击configure去生成配置,这里一定要选择一个网络较好的机器。因为这个过程中需要频繁的去下载组件的,有错也不要灰心。一定要无错误位置,最终生成的To be Build里有Python3和CUDA。如下图所示:
最后没有错误的情况下,点击Generate按钮,生成需要编译的文件。这里先不要关闭CMAKE软件,
点击Open Project用VS编译。
3 VS编译
通过前面打开Project后,就会跳转到VS界面。这里首先要确定的一点是,首先将模式调整为Release版本。
同时必须保证bindings这个目录下有opencv_python3才进行下一步,否则即使编译成功仍然不能使用CUDA加速。
首先选择ALL_BUILD->生成,接下来就是漫长的等待过程。我的机器大概编译了3个小时,
编译完成后,在INSTALL->生成,这个编译要快一点。下面就是等待他们完成了,编译完成后结果如下:
这次人品比较好,一次成功中间没出任何错。谢天谢地呀!
4 验证
编译完成后会生成cv2.cp38-win_amd64.pyd这个文件路径如下图所示,我们只需将这个文件Copy到我们前面设置的OpenCV编译版本目录即可。
下一步就可以测试了:
cv2.cuda.getCudaEnabledDeviceCount()
通过上面一段代码如果输出为不为0,则说明我们已经可以使用CUDA加速我们的Python-OpenCV了。同时也不会再出现本文开头的那句提示了。
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)
这两句也可以正常使用了。通过本人的实测使用CUDA版本加速OpenCV-Python速度提高了约40%,效果还是可以的。好的今天就先介绍到这里,有问题欢迎讨论。