目录
前言:
一、环境准备:
1、基本环境:
2、下载opencv源码
3、下载opencv_contrib模块
二、cmake 编译:
1、第一次"configure" 与缺失文件
2、编译项设置:
3、再次"configure"错误与缺失文件
三、工程编译
四、错误解决方法:
1、文件download失败解决方法:
2、错误 identifier "LINE_8" is undefined
3、乱码+“cv::dnn::cuda4dnn::csl::device::detail::getBlockDim” 错误
4、错误未定义标识符 "blockDim" 等
2019年12月23日,OpenCV 4.2.0版本官方发布并开放下载,这次更新的特性并不多,但非常重要的是:DNN终于支持CUDA啦!!
得知发布后,看到一直心心念的DNN模块终于支持CUDA了,再也按捺不住躁动的心,就开始下载编译了。
windows7 + VS2015+ CUDA 10.0+CUDNN 7.6.5
CUDNN版本要求不低于7.5
opencv官网https://opencv.org/releases/
下载方式有多种,可以直接下载源码,windows安装exe,或者去opencv的github主页下载。
我这里直接下载windows安装文件,
https://sourceforge.net/projects/opencvlibrary/files/4.2.0/opencv-4.2.0-vc14_vc15.exe/download
下载后双击解压到"E:\opencv4.2"路径,解压后包含build和sources两部分。
github主页,直接下载源码,或者下载压缩包,下载后解压到了"E:\opencv4.2"路径。
cmake安装可参考之前博客
打开cmake-gui.exe,选择源码路径和生成二进制路径,如下图
然后点一下config按钮,选择“Visual Studio 14 2015 Win64”
然后开始等待,config过程中会下载一些文件,包含下列文件
ippicv_2019_win_intel64_20180723_general.zip
opencv_videoio_ffmpeg.dll
opencv_videoio_ffmpeg_64.dll
ffmpeg_version.cmake
如果在下载过程中没有出错,恭喜你已经成功跳开了一个大坑。如果文件下载失败了,处理起来相对复杂,请参考本文本第四部分的解决方法。
等手动下载工作完成后,再次点击config, 保证日志内没有红色的下载失败信息
最后剩余了一个红色警告: 不用管它
这里主要关注CUDA编译,一些暂时用不到的测试模块及PYTHON模块去掉。
1、cuda
OPENCV_DNN_CUDA 选中
WITH_CUDA 选中
2、BUILD_opencv_world 选中
3、test选项 不选
4、BUILD_opencv_python.. 三个选项 不选
5、OPENCV_EXTRA_MODULES_PATH 设置为“E:\opencv4.2\opencv_contrib-master\modules”
有可能会出现错误:
CMake Error at modules/dnn/CMakeLists.txt:99 (message):
CUDA backend for DNN module requires CC 5.3 or higher. Please remove
unsupported architectures from CUDA_ARCH_BIN option.
Call Stack (most recent call first):
modules/world/CMakeLists.txt:13 (include)
modules/world/CMakeLists.txt:32 (include_one_module)
只需将CUDA_ARCH_BIN中小于5.3的选项去掉
再次点击"configure"
如果之前出现文件下载失败,这次同样可能会出现类似下面的错误
同样参考第四部分的解决方法
“configure”不再有下载错误后,依次点击“Generate”,“Open Project”按钮,用VS2015开工程
用VS2015打开后,选择“release”模式,
选择ALL_BUILD 生成。
如果出现 错误 identifier "LINE_8" is undefined 请参考下面解决方法。
如果出现 错误:乱码+unsigned int cv::dnn::cuda4dnn::csl::device::detail::getBlockDim等错误,参考下面解决方法。
编译完成后,选择INSTALL 生成。
生成的文件就保存到“e:\opencv4.2\opencv\sources\buildnew\install”文件夹内
e:\opencv4.2\opencv\sources\buildnew\install\x64\vc14\bin 目录里有生成的DLL
可以看到,编译的DLL比原来的大不少。
文件下载失败和网络有关系,而且一旦失败就会有多个文件下载失败,下面以第一个下载失败文件为例,进行说明,日志如下
从上面可以看出,下载日志在保存在“E:\opencv4.2\opencv\sources\build\CMakeDownloadLog.txt”文件内,打开文件,搜索"ippicv", 第三行即为本文件信息
其中上面为本地缓存路径,下面为下载网址,直接复制网址到浏览器下载,如果浏览器也下载失败,可以尝试将地址复制到迅雷进行下载,
下载后保存到“E:/opencv4.2/opencv/sources/.cache/ippicv/”目录,删除目录内大小0KB的文件(如果有), 并按照d222685246896fe089f88b8858e4b2f-ippicv_2019_win_intel64_20180723_general.zip重命名
其它下载失败的文件可以用同样的方法进行处理。
如果迅雷仍然下载失败,可直接访问 //download.csdn.net/download/length85/12066165 下载,我已将下载可能失败的文件都打包在一起了, 下载设置了1分,没分的朋友可直接私信我。
点开错误,我震惊了,发现"imgproc.hpp"竟然链接到了anconda安装环境中, "C:\Users\kc\Anaconda3\Library\include\opencv2", 猜测是安装环境添加到了系统变量,由于我电脑安装东西比较多,暂时把该目录下的opencv2重命名为opencv2_,opencv重命名为opencv_, 再重新编译,错误消失。
注:编译结束后重新把文件夹名修改回去,以免影响其它功能。
同样,如果出现GOOGLE_PROTOBUF_VERSION版本错误,且错误定位到了下面位置
将C:\Users\kc\Anaconda3\Library\include目录下的google重命名为google_
错误如下图:
中文显示乱码,搜索微软C2912错误描述为:显式专用化“declaration”不是函数模板的专用化,无法特化非模板函数。
这里采用修改方法:
cudnn.hpp文件,将报错行的decltype部分去掉
#if 0
template auto get_data_type()->decltype(CUDNN_DATA_FLOAT);
template <> inline auto get_data_type()->decltype(CUDNN_DATA_HALF) { return CUDNN_DATA_HALF; }
template <> inline auto get_data_type()->decltype(CUDNN_DATA_FLOAT) { return CUDNN_DATA_FLOAT; }
#else
template auto get_data_type();
template <> inline auto get_data_type() { return CUDNN_DATA_HALF; }
template <> inline auto get_data_type() { return CUDNN_DATA_FLOAT; }
#endif
grid_stride_range.hpp 文件,同样方法修改
#if 0
template __device__ auto getGridDim()->decltype(dim3::x);
template <> inline __device__ auto getGridDim<0>()->decltype(dim3::x) { return gridDim.x; }
template <> inline __device__ auto getGridDim<1>()->decltype(dim3::x) { return gridDim.y; }
template <> inline __device__ auto getGridDim<2>()->decltype(dim3::x) { return gridDim.z; }
template __device__ auto getBlockDim()->decltype(dim3::x);
template <> inline __device__ auto getBlockDim<0>()->decltype(dim3::x) { return blockDim.x; }
template <> inline __device__ auto getBlockDim<1>()->decltype(dim3::x) { return blockDim.y; }
template <> inline __device__ auto getBlockDim<2>()->decltype(dim3::x) { return blockDim.z; }
template __device__ auto getBlockIdx()->decltype(uint3::x);
template <> inline __device__ auto getBlockIdx<0>()->decltype(uint3::x) { return blockIdx.x; }
template <> inline __device__ auto getBlockIdx<1>()->decltype(uint3::x) { return blockIdx.y; }
template <> inline __device__ auto getBlockIdx<2>()->decltype(uint3::x) { return blockIdx.z; }
template __device__ auto getThreadIdx()->decltype(uint3::x);
template <> inline __device__ auto getThreadIdx<0>()->decltype(uint3::x) { return threadIdx.x; }
template <> inline __device__ auto getThreadIdx<1>()->decltype(uint3::x) { return threadIdx.y; }
template <> inline __device__ auto getThreadIdx<2>()->decltype(uint3::x) { return threadIdx.z; }
#else
template __device__ auto getGridDim();
template <> inline __device__ auto getGridDim<0>() { return gridDim.x; }
template <> inline __device__ auto getGridDim<1>() { return gridDim.y; }
template <> inline __device__ auto getGridDim<2>() { return gridDim.z; }
template __device__ auto getBlockDim();
template <> inline __device__ auto getBlockDim<0>() { return blockDim.x; }
template <> inline __device__ auto getBlockDim<1>() { return blockDim.y; }
template <> inline __device__ auto getBlockDim<2>() { return blockDim.z; }
template __device__ auto getBlockIdx();
template <> inline __device__ auto getBlockIdx<0>() { return blockIdx.x; }
template <> inline __device__ auto getBlockIdx<1>() { return blockIdx.y; }
template <> inline __device__ auto getBlockIdx<2>() { return blockIdx.z; }
template __device__ auto getThreadIdx();
template <> inline __device__ auto getThreadIdx<0>() { return threadIdx.x; }
template <> inline __device__ auto getThreadIdx<1>() { return threadIdx.y; }
template <> inline __device__ auto getThreadIdx<2>() { return threadIdx.z; }
#endif
在grid_stride_range.hpp文件内添加头文件包含,
#include
总结:我在两台电脑上测试,遇到的情况不一样,可能跟GPU的型号配置有关,也可能有些编译我没遇到,欢迎留言讨论。