基于CMake构建MSVC_CUDA及MinGW编译环境下的的OpenCV项目

前言

第一次搭建OpenCV开发环境的时候各种报错,内心那个烦啊,简直了。当时只能针对某个特定的错误去寻找特定的解决方法,在OpenCV构建过程中出现最多的问题就是各个模块文件的下载问题,本质上这类问题的解决思路都是一样的,奈何我装完了才意识到。

文件下载

构建OpenCV的源码编译环境除了基本的编译环境外还需要下面几个东西:

  • CUDA工具包
  • cuDNN库
  • opencv源码
  • opencv_contrib源码,注意下载版本需要与opencv的版本保持一致
  • opencv_3rdparty源码
  • CMake

NVIDIA的网页浏览有点慢,但是下载速度还可以,cuDNN下载需要注册NVIDIA的会员。OpenCV的下载速度就比较闹心了,从github拉取贼慢,但是可以使用油猴安装github的脚本提高拉取速度,也可以在码云里面搜索合适的镜像拉取。CUDA的安装就不写了,cuDNN的安装是将下载的文件解压到CUDA的安装目下,例如我的CUDA的安装目录是 D:\NVIDIA GPU Computing Toolkit\CUDA\v11.1 ,cuDNN解压的目录也是这个。

想省事的可以直接使用我打包好的 opencv-4.5.1,这个压缩包已经解决了我所遇到的所有关于下载错误的问题,应该可以直接配置,如果出现其他错误就自行搜索解决方法。
其他几个包:
opencv_contrib-4.5.1
opencv_3rdparty_part1
opencv_3rdparty_part2

配置MSVC和CUDA编译环境下的OpenCV项目

步骤一

注意这个目录结构,后面会频繁的在这几个目录中切换,容易搞混。我测试的目录是 F:/Desktop/test,在这个目录下面有三个opencv相关的源码。

友情提示一下,在准备自己的目录结构之前,保证至少有30G左右的硬盘空间,如果你打算同时编译Debug和Release版本的,要多大的空间,你懂的😏。我有一次辛辛苦苦编译了好几个小时到快结束的时候失败了,这都是血泪史啊😂。

运行 CMake 后首先设置 opencv 的源码目录;然后设置构建目录;勾选分组以便查看构建选项;如果没有提前创建构建目录,那么在 Configure 时CMake会询问是否创建目录;随后就是设置编译环境的相关配置,根据你自己需要进行设置即可,最后点击 Finish 进行初次配置。

OpenCV_1.png

初次配置过程中通常都会出现错误,第一个错误就是 Python 版本问题,这个错误不用管,后面配置时会自动得到修正。

OpenCV_2.png

步骤二(重要)

然后就是比较常见的 ippicv 和 FFmpeg 文件下载错误,这类错误基本占据了整个 OpenCV 构建过程中的一半,幸运的是这类错误解决思路是一致的,掌握这个解决思路以后安装就会非常容易。ippicv 的操作过程忘记截图了,我就以 FFmpeg 的修改作为例子简单说明。

CMake-GUI错误信息解读

首先看看 CMake 给出的错误信息,这里给出了几个比较关键的信息:

  1. 是哪一个文件下载失败了;
  2. 去哪儿看下载错误的日志; (ps:正确的位置是CMake刚开始配置的build目录下,下面的截图是之前测试的,名称不对。)
  3. 最后调用错误的位置。

OpenCV_3.png

下面是FFmpeg的另外两个错误,错误都是类似的。

OpenCV_4.png

OpenCV_5.png

下载错误日志解读

下载错误日志的位置去哪儿找在前面已经提过了,找到后可以看到具体的错误操作。每一个文件下载错误都有三个关键的地方:

  1. 错误的文件名;
  2. 错误文件的MD5校验值;
  3. 下载文件存放在什么位置;从图里面可以看出,存放的位置其实就是在opencv源码目录中新建了一个 .cache 目录,然后将下载的文件存放在所属模块目录下,而文件名的形式是 “MD5校验值 - 文件名”;
    OpenCV_6.png

迷之操作(重要)

查询Git分支号

从CMake-GUI的错误信息读取中,我们看到与FFmpeg相关的三个错误调用堆栈最后的位置是 3rdparty/ffmpeg/ffmpeg.cmake:20 ,此时的上层目录是opencv的源码目录。既然知道了位置那就去这个文件看看到底是个什么鬼,看下图,注意文件所在的位置。这个文件开始有4条关键的语句,通过命名我们可以知道第一条语句是Git的分支号;第二条语句是FFmpeg的32位库文件MD5校验值;第三条语句是FFmpeg的64位库文件MD5校验值;第四条语句是FFmpeg的cmake文件MD5校验值。

OpenCV_7.png

文件拷贝
  • 首先使用命令行终端进入到已经拉取的opencv_3rdparty目录下

    • cd /d F:/Desktop/test/opencv_3rdparty/
  • 然后通过Git命令切换分支到上面这个过程查询的分支号

    • git checkout 6152e132572dfdaa32887eabeb7199bef49b14dc
  • 从下载错误的日志中我们已经知道了ffmpeg下载的文件应该存放在什么位置,先将那个存放位置的所有内容删掉

  • 在切换分支以后的opencv_3rdparty目录下找到下载错误的文件,并将其拷贝到上一个操作中的目录中

    • OpenCV_8.png
获取并更新MD5校验值
  • 从下载错误的日志我们还知道,文件名的形式应该是“MD5校验值-文件名”,因此我们需要先获取MD5校验值,然后进行文件的重命名操作。

    • 获取MD5的可以直接使用命令行,然后手动进行文件重命名

      • certutil.exe -hashfile “文件名” md5
    • 我嫌麻烦,写了个简单的Python脚本,这个脚本的功能就是获取脚本文件所在目录下的所有文件的MD5校验值,并进行重命名操作

      • import hashlib
        import osdef TraverseFile():return (file for root, dirs, files in os.walk(".") for file in filesif "RenameFile.py" != file)def RenameFile(files):for file in files:md5 = hashlib.md5()with open(file, "rb") as file_detect:for data in iter(lambda: file_detect.read(8096), b''):md5.update(data)result = md5.hexdigest()with open("md5.txt", "a") as write_result:write_result.write(file + " : " + result + "\n")os.rename(file, result + "-" + file)RenameFile(TraverseFile())
        
  • 知道了MD5校验值以后还需要回到最终调用错误的那个文件(就是获取Git分支号的文件)中将MD5的校验值更新一下,这里更新的时候注意别改错了,否则就会校验失败,那么CMake仍然会去下载文件

  • OpenCV_9.png

  • 更新完毕后我们再次执行 configure 操作,可以发现错误已经消失。只要后续遇到所有类似下载错误都按这个分析过程来处理基本上可以保证解决大部分下载失败的问题

步骤三

步骤三主要是给OpenCV 配置一些额外的模块,在搜索框中输入 “extra”,然后在对应的值中写入opencv_contrib中modules的路径,注意CMake的路径是“/“形式,然后再次进行 configure,过程依然会有错误。按照步骤二的操作一步一步解决即可,不过需要注意的是,引入opencv_contrib后调用堆栈最后位置给出的是全路径,要找Git分支号和更新MD5校验值需要按照这个路径查找,而不是opencv的源码目录中查找。

OpenCV_10.png

步骤四

步骤四是配置OpenCV的CUDA构建选项,在搜索框中输入 “CUDA”,将CUDA相关的选项都勾选上,再次重新进行 configure ,如果之前CUDA安装顺利这里应该也非常顺利。最后点击 configure 旁边的 Generate 生成OpenCV的编译项目。

OpenCV_11.png

步骤五

步骤5是生成对应编译环境的OpenCV项目,并对项目编译生成运行库。项目生成后我们使用Visual Studio对其进行编译。找到 CMakeTargets 目录下的 ALL_BUILD,配置生成的库为Debug或者Release,然后进行编译,编译完成后继续编译 INSTALL,然后会在最开始的构建目录下生成install文件目录,将这个目录的内容拷贝到指定的地方,然后添加环境变量就可以使用啦!

2021-01-11_180225.png

配置MinGW编译环境下的OpenCV项目

配置MinGW编译环境下的OpenCV项目与MSVC编译环境类似,主要区别是在步骤一、步骤四以及步骤五。由于在Windows系统下CUDA不支持MinGW的编译环境,因此没有步骤四,那么主要区别就是步骤一及步骤五。

步骤一

OpenCV_12.png

步骤五

由于使用MinGW编译环境,因此在编译生成运行库的时候有所不同。

  • 首先命令行进入到构建目录中

    • cd /d F:/Desktop/test/opencv/build
  • 然后使用 mingw32-make 开始编译

    • mingw32-make -j8
  • 最后使用 mingw32-make 生成安装目录即可

    • mingw32-make install

简单测试

Visual Studio 2019 - MSVC

#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>#ifndef NDEBUG
// Debug
#pragma comment(lib, "opencv_core451d.lib")
#pragma comment(lib, "opencv_imgcodecs451d.lib")
#pragma comment(lib, "opencv_highgui451d.lib")
#else
// Release
#pragma comment(lib, "opencv_core451.lib")
#pragma comment(lib, "opencv_imgcodecs451.lib")
#pragma comment(lib, "opencv_highgui451.lib")
#endif // !NDEBUGint main() {cv::Mat img = cv::imread("cplusplus.png");cv::namedWindow("test", cv::WINDOW_AUTOSIZE);cv::imshow("test", img);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

CLion - MinGW

# CMakeLists.txtcmake_minimum_required(VERSION 3.17)project(Test_OpenCV VERSION 1.0.0 LANGUAGES CXX)set(CMAKE_CXX_STANDARD 14)add_executable(${CMAKE_PROJECT_NAME})
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE D:/OpenCV4.5.1/MinGW_8_x64/include/)
file(GLOB SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp)
target_sources(${CMAKE_PROJECT_NAME} PRIVATE ${SRCS})
file(GLOB LIBS D:/OpenCV4.5.1/MinGW_8_x64/x64/mingw/bin/*.dll)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE ${LIBS})
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>int main() {cv::Mat img = cv::imread("cplusplus.png");cv::namedWindow("test", cv::WINDOW_AUTOSIZE);cv::imshow("test", img);cv::waitKey(0);cv::destroyAllWindows();return 0;
}

更新2021-01-13

又发现了新的坑。。。这两天用python测试了一下opencv,发现无法正确导入包,试了一圈都不行,它也不报什么错误信息!!!!!我多试了几次后发现C盘空间满了。。😤,分析了一下磁盘才发现它会在C:\Users\用户名\AppData\Local\CrashDumps下会产生较大的崩溃文件,崩溃一次写一个文件。后来我发现编译源码时INSTALL的日志里面了拷贝了生成的文件到python的库里面,又想起我之前已经单独安装过python版本的opencv了。
OpenCV_13.png
这么来看,应该是文件被覆盖了导致的崩溃。由于python版本的文件已经被覆盖,因此需要将原来python版本的opencv彻底卸载掉,卸载掉之后在Visual Studio中执行 “生成INSTALL” 操作,然后应该就好使了。

在找上面的问题时我偶然间发现python版本的opencv的 __init__.py会加载一个相同目录下的config.py的配置文件,这个配置文件里面其实就是库的路径,默认写的是编译后Install的目录,如果你在“生成INSTALL”时没有修改生成的路径,那么默认是在编译目录下的,这时候如果你把整个文件夹拷走了,那么就会出现错误“ImportError: DLL load failed while importing cv2: 找不到指定的模块”,这时候修改一下路径就行,同时注意编译时是Debug版本的opencv,库的路径就必须指向Debug版本的路径。要不是上面的事故,这个地方我估计只有等我删了编译后的文件夹我才能发现。。。
OpenCV_14.png
OpenCV_14..png
在VSCode中,发现opencv没有自动补全,添加自动补全的额外路径即可,有pylint的波浪线也可以通过下面的配置解决。

    "python.linting.pylintArgs": ["--errors-only  --generated-members=numpy.* ,torch.* ,cv2.* , cv.*"],"python.autoComplete.extraPaths": ["D:/Python3/Lib/site-packages/cv2/python-3.8",],

本文博客地址

欢迎来我的自建博客看看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/256024.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【opencv】——钢管计数(霍夫圆变换 + 阈值 + canny)

目录 方法一:霍夫圆变换 + canny 方法二 阈值 + 寻边 对图中的钢管进行计数 方法一:霍夫圆变换 + canny

DNS域传送漏洞

0x00 相关背景介绍 Dns是整个互联网公司业务的基础&#xff0c;目前越来越多的互联网公司开始自己搭建DNS服务器做解析服务&#xff0c;同时由于DNS服务是基础性服务非常重要&#xff0c;因此很多公司会对DNS服务器进行主备配置而DNS主备之间的数据同步就会用到dns域传送&#…

封装之--通过类中公有方法访问私有成员变量

如何在ClassB中访问ClassA的私有成员变量&#xff1f;&#xff08;典型的封装案例&#xff09; 通过在ClassA中定义公有的成员方法&#xff0c;然后&#xff0c;在ClassB中通过ClassA的对象调用ClassA中的公有方法&#xff0c;来访问ClassA中的私有成员变量。 转载于:https://w…

匹配物镜放大倍数与相机像元尺寸

通常来说&#xff0c;相机内部的CCD或者CMOS传感器上都有感光阵列&#xff0c;由一个一个的感光元件构成&#xff0c;每一个感光元件负责完成光电转换的过程。简单理解&#xff0c;一个感光元件可以认为就是一个像素(pixel)或像元(pel)。像元具有一定尺寸&#xff0c;如果像的尺…

【深度学习】——非极大值抑制(nms/soft-nms)

目录 一、相关概念 1、iou 1&#xff09;理论计算 2&#xff09;Python代码&#xff08;代码参考yolov3模型util.py文件&#xff09; 2、nms 1)基本思路 2&#xff09;标准nms和soft-nms 3&#xff09;Python代码实现&#xff08;yolov3中util.py文件&#xff0c;增加了…

移动服务安全现状分析!

2019独角兽企业重金招聘Python工程师标准>>> 由于Android开源的环境&#xff0c;导致Android的整体环境都存在很多不安全的因素&#xff0c;同时用户在移动APP客户端的便捷应用&#xff0c;也给用户带来了巨大的安全隐患。未经过移动服务安全加固的APP存在被静态反编…

MyEclipse连接MySQL

在官网http://www.mysql.com/downloads/下载数据库连接驱动 本文中使用驱动版本为mysql-connector-java-5.1.40 一、创建一个java测试项目MySQLConnectorsTest 在项目下穿件一个lib文件夹用来存放MySQL驱动包。 右键驱动包build path进行add添加操作&#xff0c;打开Referenced…

在Windows系统中配置Google AddressSanitizer

Google AddressSanitizer简介 AddressSanitizer (ASan) 是 C 和 C 的内存错误检测软件&#xff0c;它可以检测&#xff1a; 释放指针后继续使用堆缓冲区溢出栈缓冲区溢出全局缓冲区溢出返回后继续使用在范围之外继续使用初始化顺序的bug内存泄漏 在 Windows 系统中&#xff…

【剑指offer】——求出一个正整数的质数因子(Python)

目录 一、题目描述 二、思路 1、短除法 2、平方根法 一、题目描述 功能:输入一个正整数&#xff0c;按照从小到大的顺序输出它的所有质因子&#xff08;重复的也要列举&#xff09;&#xff08;如180的质因子为2 2 3 3 5 &#xff09; 最后一个数后面也要有空格 输入描述…

C++ STL实现的优先队列( priority_queue )

本文参考的源码版本&#xff1a;gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)。 priority_queue 本质是容器适配器&#xff0c;它对内部容器的元素有自己的管理方式&#xff0c;而 priority_queue 实际维护的是一个二叉堆。STL中 priority_queue 的…

生成相关矩阵

U是X&#xff08;差异矩阵&#xff09;各列向量取方向后形成的矩阵&#xff0c;CU^T * U 即相关矩阵&#xff0c;即各列向量两两的夹角&#xff0c;&#xff08;夹角越小说明关联度越高&#xff09; clc avg_e66;avg_m66;avg_s76; x1[61 63 78 65 63] -avg_e; x2[53 73 61 84 5…

Java关于Properties用法的总结(一)

最近项目中有一个这样的需求&#xff0c;要做一个定时任务功能&#xff0c;定时备份数据库的操表&#xff0c;将表数据写入txt文件。因为文件的读写路径可能需要随时改动&#xff0c;所以写死或者写成静态变量都不方便&#xff0c;就考虑使用配置文件&#xff0c;这里总结些配置…

【tensorflow】——tensorboard可视化计算图以及参数曲线图loss图

参考文献&#xff1a; https://zhuanlan.zhihu.com/p/71328244 目录 1.可视化计算图 2.可视化参数 3. 远程tensorboard 4、报错 真是出来混迟早是要还的&#xff0c;之前一直拒绝学习Tensorboard&#xff0c;因为实在是有替代方案&#xff0c;直到发现到了不得不用的地步…

jQuery学习- 位置选择器

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>位置选择器</title><script src"js/jquery.js"></script><script type"text/javascript">$(function(){//获取第一个li$(&quo…

Vue3、TypeScript 实现图片数量及大小随宽度自适应调整

前言 过了这么久&#xff0c;想起自己还有个博客&#xff0c;更点内容吧&#xff01; 来&#xff0c;上需求&#xff01; 最近在做个前端界面&#xff0c;要求在一行中展示一些图片&#xff0c;展示的图片数量随着窗口宽度大小进行变化&#xff0c;除此之外还有以下要求&…

苹果Iphone/Ipad--L2T虚拟教程

1 Iphone和Ipad同为IOS&#xff0c;设置方法相同。首先进入IOS系统的“设置”程序。 2 点击“通用”进入通用设置&#xff0c;点击“”; 3 选择"添加设置 "&#xff1b; 4 选择L2TP方式&#xff0c;填写必要信息&#xff1a;描述、服务器地址 、您注册充值的账号及密…

记忆化搜索的应用

记忆化搜索的应用 一般来说&#xff0c;动态规划总要遍历所有的状态&#xff0c;而搜索可以排除一些无效状态。更重要的是搜索还可以剪枝&#xff0c;可能剪去大量不必要的状态&#xff0c;因此在空间开销上往往比动态规划要低很多。 如何协调好动态规划的高效率与高消费之间的…

Veebot-自动静脉抽血机器人

Veebot-自动静脉抽血机器人 我们可能都有过被抽血的经验。护士让你握紧拳头&#xff0c;用一根橡皮条压住你上臂的血管&#xff0c;在你的肘部内侧寻找你的静脉&#xff0c;有时还需要拍打几下&#xff0c;摸到隆起的静脉血管&#xff0c;一针下去。有时候碰到技术好的护士&…

idea 转普通项目为maven 项目

1、项目上右键 Add Framework Support。 2、选择maven&#xff0c;点击OK。 转载于:https://www.cnblogs.com/mayanze/p/8042489.html

【深度学习之ResNet】——深度残差网络—ResNet总结

目录 论文名称&#xff1a;Deep Residual Learning for Image Recognition 摘要&#xff1a; 1、引言 2、为什么会提出ResNet残差网络呢&#xff1f; 3、深度残差网络结构学习&#xff08;Deep Residual learning&#xff09; &#xff08;1&#xff09;残差单元 &#xf…