之前编译过很多次opencv,但第一次为python编译,中间走了不少弯路。
在百度网盘共享了:
opencv-4.2.0-vc14_vc15.exe
opencv_contrib_4.2.0.zip
opencv42_cache.7z(cmake需要下载的部分)
链接:https://pan.baidu.com/s/1E-FmVbnwv2gjuL9UAiMDkQ 提取码:mf0f
因为python和numpy是安装在conda中的,所以cmake必须在conda环境中运行。不然没法自动检测到numpy,即使手动指定,仍然没法通过检测。这里走了不少弯路。。。
2. cmake下载文件
点击Configure,这时会检测计算的配置,下载需要的组件。
第一次Configure会提示Warning说找到的python.exe不是python2。没有问题,那是python3,不用处理,以后configure就没有警告了。
这时会出现很多配置选项,将OPENCV_EXTRA_MODULES_PATH设置为opencv_contrib_4.2.0.zip解包后的modules文件夹。再次Configure,又需要下载几个文件。
由于服务器大都在国外,速度非常慢,而opencv默认的下载超时只有10分钟,又不支持断点续传,于是不管下载多少次也不行。
修改代码
“TIMEOUT 600”改为“TIMEOUT 6000”,100分钟应该足够了。
set(OPENCV_DOWNLOAD_PARAMS INACTIVITY_TIMEOUT 60 TIMEOUT 600 CACHE STRING "Download parameters to be passed to file(DOWNLAOD ...)")
如果网络实在不好,不仅慢而且掉线,就需要使用下载工具(aria2、IDM等)来下载这些链接,即使掉线,可以接着下,总有下载完的一天。去cmake的build目录下打开CMakeDownloadLog.txt
#do_unpack "v0.1.1f.zip" "b624b995ec9c439cbc2e9e6ee940d3a2" "https://github.com/opencv/ade/archive/v0.1.1f.zip" "C:/opencv/opencv42_build2/3rdparty/ade"
#cmake_download "C:/opencv/opencv42/sources/.cache/ade/b624b995ec9c439cbc2e9e6ee940d3a2-v0.1.1f.zip" "https://github.com/opencv/ade/archive/v0.1.1f.zip"
#try 1
# timeout on name lookup is not supported
# Trying 151.101.228.133...
其中cmake_download 后面跟着的就是要下载的文件路径,和url。用下载工具下载好url后,放入前面的路径,并改成需要的名字。名字前面那串是文件的md5值,cmake会自动校验的。
3. cmake配置参数
几个常用的配置:
BUILD_SHARED_LIBS:勾选则编译动态库DLL,反之静态库|
BUILD_opencv_world:编译成单一的动态库
WITH_CUDA:使用cuda加速,需要opencv_contrib 4.2.0.zip
OPENCV_DNN_CUDA:使用cuDNN,要求CUDA_ARCH_BIN大于5.3,去掉小于5.2的。
OPENCV_ENABLE_NOFREE:编译不免费的代码(有版权问题),比如SIFT、SURF算法
可以去掉TEST,减少编译时间。编译TEST可以运行测试判断编译是否成功,运行Test还需要下载opencv_extra_4.2.0.zip,不然大部分测试会失败。说到时间,cuda编译器是单线程的,优化太差了。
如果用不到JAVA,可以不选
cmake能够自动检测Python的配置
如果没有BUILD_opencv_python3选项,需要再次检测环境,python和numpy是否安装正确。
这时会有一条警告:
CMake Warning at cmake/OpenCVGenSetupVars.cmake:54 (message):
CONFIGURATION IS NOT SUPPORTED: validate setupvars script in install
directory: C:/ProgramData/Miniconda3/Lib/site-packages
实际上就是PYTHON3_PACKAGES_PATH是绝对路径,直接就生成到python3的库里面去了,于是setup_vars_opencv4.cmd无法配置python库路径。当然也不再需要配置python库路径,直接import就可以。如果计算机中有多个python环境,如果将PYTHON3_PACKAGES_PATH添加到其他python中,就可能引起其他问题。将PYTHON3_PACKAGES_PATH改为python就可以了。需要使用时,先运行setup_vars_opencv4.cmd就可以了。也可以用build目录下的python_loadersetup.py手动安装到ptrhon库中。
4. 编译
先编译ALL_BUILD,编译工程。等待漫长的时间。。。
如果启用了OPENCV_DNN_CUDA,在VS2015上会出错,VS2017和VS2019正常编译。原因都是VS2015对c++新语法支持的不好。
16>c:opencvopencv42sourcesmodulesdnnsrccudagrid_stride_range.hpp(16): error C2912: 锟斤拷式专锟矫伙拷锟斤拷锟斤拷unsigned int cv::dnn::cuda4dnn::csl::device::detail::getGridDim<0>(void)锟斤拷锟斤拷锟角猴拷锟斤拷模锟斤拷锟阶拷没锟?
。。。
16>c:opencvopencv42sourcesmodulesdnnsrccuda4dnncslcudnn/cudnn.hpp(42): error C2912: 锟斤拷式专锟矫伙拷锟斤拷锟斤拷cudnnDataType_t cv::dnn::cuda4dnn::csl::cudnn::detail::get_data_type(void)锟斤拷锟斤拷锟角猴拷锟斤拷模锟斤拷锟阶拷没锟?
搜索给该问题,得到解决方案https://blog.csdn.net/wanggao_1990/article/details/103779760
使用using代替拖尾返回类型。
(1)修改sourcesmodulesdnnsrccudagrid_stride_range.hpp文件
替换15-33行为
using dim3_member_type = decltype(dim3::x);
template __device__ dim3_member_type getGridDim();
template <> inline __device__ dim3_member_type getGridDim<0>() { return gridDim.x; }
template <> inline __device__ dim3_member_type getGridDim<1>() { return gridDim.y; }
template <> inline __device__ dim3_member_type getGridDim<2>() { return gridDim.z; }
template __device__ dim3_member_type getBlockDim();
template <> inline __device__ dim3_member_type getBlockDim<0>() { return blockDim.x; }
template <> inline __device__ dim3_member_type getBlockDim<1>() { return blockDim.y; }
template <> inline __device__ dim3_member_type getBlockDim<2>() { return blockDim.z; }
using uint3_member_type = decltype(uint3::x);
template __device__ uint3_member_type getBlockIdx();
template <> inline __device__ uint3_member_type getBlockIdx<0>() { return blockIdx.x; }
template <> inline __device__ uint3_member_type getBlockIdx<1>() { return blockIdx.y; }
template <> inline __device__ uint3_member_type getBlockIdx<2>() { return blockIdx.z; }
template __device__ uint3_member_type getThreadIdx();
template <> inline __device__ uint3_member_type getThreadIdx<0>() { return threadIdx.x; }
template <> inline __device__ uint3_member_type getThreadIdx<1>() { return threadIdx.y; }
template <> inline __device__ uint3_member_type getThreadIdx<2>() { return threadIdx.z; }
(2) 修改sourcesmodulesdnnsrccuda4dnncslcudnncudnn.hpp文件
替换40-42行为:
using cudnn_data_enum_type = decltype(CUDNN_DATA_FLOAT);
template cudnn_data_enum_type get_data_type();
template <> inline cudnn_data_enum_type get_data_type() { return CUDNN_DATA_HALF; }
template <> inline cudnn_data_enum_type get_data_type() { return CUDNN_DATA_FLOAT; }
再次编译ALL_BUILD,提示:
2>window.obj : error LNK2019: 无法解析的外部符号 cvStartWindowThread
2>window.obj : error LNK2019: 无法解析的外部符号 cvNamedWindow
2>window.obj : error LNK2019: 无法解析的外部符号 cvShowImage
cvResizeWindow,cvMoveWindow,cvDestroyWindow,cvDestroyAllWindows, cvCreateTrackbar2,cvGetTrackbarPos,cvSetTrackbarPos,cvSetTrackbarMax,cvSetTrackbarMin,cvSetMouseCallback,cvWaitKey,cvSetModeWindow_W32,cvGetWindowRect_W32,cvGetModeWindow_W32,cvGetPropWindowAutoSize_W32,cvGetRatioWindow_W32,cvGetOpenGlProp_W32,cvGetPropVisible_W32,cvGetPropTopmost_W32,cvSetPropTopmost_W32
2>C:opencvopencv42_buildbinReleaseopencv_world420.dll : fatal error LNK1120: 23 个无法解析的外部命令
什么也没改,再次编译ALL_BUILD
========== 生成: 成功 70 个,失败 0 个,最新 15 个,跳过 0 个 ==========
编译INSTALL,生成install文件夹,就可以将install复制到其他的计算机使用了。其他计算机需要安装相同版本的cuda,cudnn。
5. 编译debug版
如果需要调试,那么就需要编译debug版。编译时遇到错误:
fatal error LNK1210: 已超过内部 ILK 大小限制;链接时使用 /INCREMENTAL:NO
搜索/INCREMENTAL
https://www.cnblogs.com/Dahaka/archive/2011/08/01/2124256.html
原来时因为函数太多了,incremental linking(增量链接)的ILT表(Incremental Linking Table)超过了大小限制,opencv的debug库是为了被我们的debug程序调用,而不是修改opencv,所以并不需要增量链接。
把Project Properties -> Configuration Properties -> Linker (General) -> Enable Incremental Linking中的Yes (/INCREMENTAL)改成No (/INCREMENTAL:NO)
再次编译ALL_BUILD,由于只剩下链接处理,很短时间就编译成功。
编译INSTALL,生成install文件夹。
6. 运行Test
设置环境变量。如果不设置OPENCV_SAMPLES_DATA_PATH_HINT,测试Samples.findFile会失败
set OPENCV_TEST_DATA_PATH=C:opencvopencv_extra-4.2.0testdata
set OPENCV_SAMPLES_DATA_PATH_HINT=C:opencvopencv42sourcessamplesdata
运行opencv_extra-4.2.0testdatadnndownload_models.py下载模型数据。
编译RUN_TESTS,运行测试。在输出窗口里没有详细的失败信息,可以在命令行里运行对应的opencv_test_******。