1. Windows系统下OpenCV及第三方库文件的使用与下载
如果没有特殊要求,在Windows系统下可以直接使用OpenCV的预编译版本。在github的opencv项目release中选择相应release版本即可。然而,由于版权原因,预编译的opencv并没有包含诸多第三方工具,因此,如果要使用一些第三方工具,或者要在linux系统下使用openCV的话,还需要自己从源码进行编译。
1.1 OpenCV下载与安装
OpenCV可以从官网下载,本文使用openCV 4.50版本。下载完成后点击安装,该安装包实际上是指打包的压缩文件,选择路径解压即可,本文将opencv解压安装到D:\lib路径下,解压后的opencv所在目录为D:\lib\opencv。在opencv目录下,source为源文件的文件夹,build为编译文件的文件夹,包括了VC14和VC15的预编译文件。如果要直接使用编译好的opencv,引用build目录下的文件即可。本文在opencv目录下新建一个rebuild目录,用来保存自行编译后的文件。
1.2 OpenCV_Contrib库下载与安装
要安装第三方工具,需要从github上下载相应的opencv_contrib版本,这里从opencv-contrib仓库的release版本中下载opencv_contrib-4.5.0版本.将解压后的opencv_contrib-4.5.0文件夹直接放到opencv的source目录下,以备后续编译使用。
1.3 OpenCV_3rdParty库下载与安装
在OpenCV的编译过程中,还需要一些第三方库支持,这些库文件包含在opencv_3rdparty库中,该库不同的分支(branch)文件对应了编译过程中可能需要的ippicv、ffmpeg以及dnn等第三方库,如果要安装对应的工具,则需要下载对应的库文件。需要注意的是,第三方库文件的下载过程已经写在opencv的编译文件中了,但是由于国内网络环境的原因,直接下载通常很难成功,这也是编译失败的主要原因之一。要使用预先下载的第三方库文件代替直接下载。
从github上下载的opencv_3rdparty库,默认的readme分支仅包含简单的说明文档,可以使用git branch命令查看不同分支,并使用git checkout <分支名>切换到不同分支,以便将对应文件复制出来。在opencv/source/3rdparty文件夹下可以看到第三方工具文件夹,在各文件夹下有对应的编译文件,例如ffmpeg文件夹下的编译文件ffmpeg.cmake,在ffmpeg.cmake文件中,可以找到需要下载的文件版本例如ffmpeg/master_20200908。在opencv_3rdparty库中checkout相应的分支即可找到对应文件。
OpenCV编译过程中下载的临时文件位于opencv目录下的.cache目录中,可以在opencv目录下新建.cache目录,针对不同模块新建包括ffmpeg、ippicv、xfeatures2d等目录,将上一步中3rdparty库对应分支的文件复制到对应的文件夹下即可。需要注意的是,OpenCV在缓存文件时并不是按照原始的文件名缓存在,而是在前面加上了md5校验字符串,因此在复制文件时要将文件重命名。例如在ffmpeg.cmake文件中有以下内容:
...ocv_update(FFMPEG_FILE_HASH_BIN64 "cf5dba83edf8619f57ccff4edb989c62")
那么就需要将原始的opencv_videoio_ffmpeg_64.dll文件重命名为cf5dba83edf8619f57ccff4edb989c62-opencv_videoio_ffmpeg_64.dll。典型的文件夹结构如下图。如果在编译过程中出现下载错误,可以检查对应安装包的编译文件,看看是否与所需要的文件版本内容一致。
另一个选择是将下载的第三方文件放在特定文件夹中,并找到每个CMakelist.txt文件,将其中https://raw.githubusercontent.com....目录修改为存放对应文件的位置如file:///D:/lib/3rdparty...。
2.编译环境和工具安装
2.1 安装MinGW-W64的msys32发行版
MinGW-w64 是一个Windows系统下支持GCC编译器的工具,它支持64位和32位操作系统。使用MinGW-W64,可以替代微软的VC编译器来编译c和c++项目。MSYS2是一个集成了pacman和MinGW-w64的Cygwin升级版的工具,用于在Windows系统下提供接近原生的Linux工具链。通过msys2集成的pacman包管理工具,可以方便的安装和管理包,如果你熟悉Arch Linux,使用Pacman工具会感到格外方便。
由于网络环境的原因,MinGW-w64在国内使用很不方便,经常出现无法更新软件的情况,因此这里使用包含了MinGW-w64的msys2发行版。
从清华大学开源网站msys2下载地址下载msys2后采用默认设置安装,安装在C:\msys64目录下。安装完成后,打开C:\msys64\etc\pacman.d目录并修改以下三个文件,以将msys2的软件源配置为清华镜像,加快下载速度。
#编辑 /etc/pacman.d/mirrorlist.mingw32 ,在文件开头添加:Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/i686#编辑 /etc/pacman.d/mirrorlist.mingw64 ,在文件开头添加:Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/x86_64#编辑 /etc/pacman.d/mirrorlist.msys ,在文件开头添加:Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/msys/$arch
打开C:\msys64\mingw64.exe,输入以下命令以安装完整的64位工具链,也可以按照toolchain下面的命令,单独安装gcc,g++和gdb三个工具,如果要安装32位工具,则使用mingw32.exe和对应的mingw32与对应的i686相关工具。本文安装64位工具链,安装完成后,在mingw64.exe的命令行下输入gcc --version、g++ --version或者gdb --version可以看到相应版本。
#安装64位工具和make工具pacman -S mingw64/mingw-w64-x86_64-toolchainpacman -S mingw64/mingw-w64-x86_64-make#上述命令包含了以下3个包,因此下面3个不需要再另外安装pacman -S mingw64/mingw-w64-x86_64-gccpacman -S mingw64/mingw-w64-x86_64-g++pacman -S mingw64/mingw-w64-x86_64-gdb#安装32位工具pacman -S mingw32/mingw-w64-i686-toolchainpacman -S mingw32/mingw-w64-i686-makepacman -S mingw32/mingw-w64-i686-gccpacman -S mingw32/mingw-w64-i686-g++pacman -S mingw32/mingw-w64-i686-gdb#pacman常用的操作指令pacman -Sy #更新软件包数据pacman -R package-name #删除软件包pacman -S package-name #安装软件包pacman -Syu #更新所有pacman -Ss xx #查询软件xx的信息
要在系统命令行中使用gcc等命令,还需要将minGW-W64添加到windows的环境变量中。在windows控制面板—>系统—>高级系统设置—>环境变量下,双击path参数并新建环境变量,将以下路径添加到环境变量中(如果要使用32位的msys2,路径也要相应地修改为32位的目录)。环境变量配置完成后,在windows命令行或者powershell中输入,输入gcc --version、g++ --version或者gdb --version可以看到相应版本。
注意:如果配置环境变量时命令行已经在运行,需要关掉命令行并重新打开,才能使配置生效。
C:\msys64C:\msys64\mingw64\binC:\msys64\mingw64\x86_64-w64-mingw32\bin
2.2 安装CMAKE工具
CMake 是一个开源的跨平台工具系列,旨在构建、测试和打包软件。在CMaje官网下载对应的编译工具进行安装,并将安装路径写入环境变量。在命令行输入cmake --version可以看到cmake版本信息。安装完成后,也可以通过CMake自带的图形界面Cmake GUI进行文件编译。相比命令行而言,操作更简单。
2.3 安装python2.7
OpenCV编译需要python的numpy工具包,如果要编译OpenCV的python接口,同样需要安装python,虽然目前python已经停止对python2的支持,但和大多数历史遗留项目一样,opencv仍然需要安装python2版本。在python官网下载python2的最新发行版python2.7.18并进行安装,安装时选中最后一条“将python写入环境变量”,否则在安装完成后需要手动将python以及python的script目录添加的环境变量中。安装完成后在命令行输入python -V可以看到python的版本信息。
修改pip镜像为清华开源站,在命令行输入以下两行,更换python安装库位置,以提高包下载速度,更换完成后通过pip命令安装numpy包。在编译OpenCV的过程中,可能还需要python的debug文件,在python官网下载对应的debug info文件并解压复制到python安装目录的DLLs目录下。如果不需要编译python相关内容,可以跳过该步骤。
pip install pip -Upip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple#安装numpypip install numpy
如果安装了msys2,那么在安装python2.7之前,输入python -V,是会显示python3的版本信息的,这是因为minGW64的bin目录中已经有了python3的文件,但是这个python没有安装pip,是不完整的,如果要为minGW64安装pip,需要在该目录下运行
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py #下载pip安装脚本.\pip3.8.exe install pip #安装pip
注意,由于系统路径中python已经指定为2.7版本,要使用该python3,需要使用完整的路径加程序名称。
2.4 安装JDK和Ant
如果要编译Java环境相关内容,还需要安装和配置JDK和Apache-ant,下载JDK的windows版本并使用默认设置安装,下载ant的可执行文件binary版本,并解压缩,本文解压缩到D:\lib\apache-ant-1.10.9目录下,并将该目录和bin子目录添加到环境变量中。在命令行中输入java和ant可以看到java命令行帮助和ant编译出错(因为没有xml文件)信息,即说明安装完成。如果不需要安装Java相关内容,则不需要安装上述工具。
3. OpenCV编译
打开CMake(cmake-gui),输入路径(where is the source code)选择opencv的源代码路径D:\lib\opencv\sources,输出路径(where to build the binary)选择第一步新建的rebuild目录D:\lib\opencv\rebuild。
点击左下角Configure,在编译器选项中选择MinGW Makefiles,下面选择Specify native compilers,以使用MinGW64进行编译,如果电脑安装有Visual Studio也可以选择相应的Visual Studio编译器进行编译。
在下一步的compiles中,c语言选择C:/msys64/mingw64/bin/gcc.exe,c++选择C:/msys64/mingw64/bin/g++.exe。点击确定后,系统会开始尝试进行配置,第一次配置完成后,往往会出现很多红色错误,需要一一解决。在该步骤还可能出现找不到项目文件或编译器的错误,可以检查配置过程输入文件,往往是文件路径错误,或者未安装make工具等情况造成的。在这里需要调整部分参数配置,或者添加、修改参数。
Add Entry按钮可以添加编译参数,添加参数时选择参数类型,布尔量通过打勾选择有或无,字符串和路径分别输入对应值。Search框可以输入参数的一部分来过滤和搜索变量,以便于修改
需要调整的配置包括:
OPENCV_ENABLE_ALLOCATOR_STATS,取消选择,否则可能出现vs_version.rc.obj错误BUILD_opencv_world选项可以打开,该选项将opencv编译成一个包OPENCV_ENABLE_NONFREE选项打开,以安装contrib文件包内容OPENCV_EXTRA_MODULES_PATH选项输入contrib包的modules目录D:\lib\opencv\sources\opencv_contrib-4.5.0\modules。- 修改
CMAKE_INSTALL_PREFIX参数为D:/lib/opencv/rebuild/mingw64以更改安装目录 - 取消
BUILD_TESTS和BUILD_Opencv_python_tests。
配置完成后再点击Configure按钮,然后点击Generate按钮。
注意:从命令行进入D:\lib\opencv\rebuild目录,输入mingw32-make install -j16进行编译。注意j后面的数字表示编译线程数,一般为4且不能超过计算机支持的最大线程数。在多线程编译的情况下,有时错误信息会被覆盖掉,从而无法及时找到编译出错的信息,这种时候可以通过mingw32-make install -j1将编译线程数改为1,以便在编译出错时及时停止编译,以处理出错信息。
4. 在Visual Studio中使用OpenCV
在Visual Studio中使用OpenCV,可以直接使用预编译版本下的VC14、VC15版本,也可以参照上述步骤重新编译。部分Visual Studio与Visual C++版本对应关系如下表,在实践中,VC15的编译版本也可以在Visual Studio 2019中使用:
| Visual Studio 版本 | Visual C++ 版本 |
|---|---|
| VS 6.0 | VC 6.0 |
| VS 2013 | VC 12 |
| VS 2015 | VC 14 |
| VS 2017 | VC 15 |
| VS 2019 | VC 16 |
- 将编译文件的
bin目录D:\lib\opencv\build\x64\vc15\bin添加到环境变量中。 - 新建
Visual Studio空项目。在Resource Files上右键单击Add添加New Item,创建一个main.cpp文件。
#include <iostream>#include <opencv2/opencv.hpp>using namespace std;using namespace cv;int main(int argc, char* argv[]) {const char* imagename = "D:\\Pictures\\Camera Roll\\digitalmeter1.jpg";//此处为你自己的图片路径//从文件中读入图像Mat img = imread(imagename, 1);//如果读入图像失败if (img.empty()) {fprintf(stderr, "Can not load image %s\n", imagename);return -1;}//显示图像imshow("image", img);//此函数等待按键,按键盘任意键就返回waitKey();return 0;}
- 在项目资源上右键->属性,在
VC++目录(VC++ Directory)的包含目录(include Directories)中添加D:\lib\opencv\build\include和D:\lib\opencv\build\include\opencv2。 - 在
库目录(Library Directories)中添加D:\lib\opencv\build\x64\lib。 - 在链接器(Linker)的输入(Input)中,添加
D:\lib\opencv\build\x64\lib下的opencv_world450d.lib,对应编译文件的debug模式,如果要编译release版本,则需要选择不带d的opencv_world450.lib文件。
编译并运行项目,如果没有错误,则可以显示图像内容。
5. 在VS Code中使用OpenCV
要在VS Code中使用OpenCV,需要安装VScode的c/c++语言扩展插件,然后在项目文件夹下新建main.cpp文件,文件内容可与前节相同,根目录下新建.vscode文件夹(也可以按照官方文档指引,通过Terminal->Config Default Building Task命令新建该文件夹并在其中生成tasks.json文件),然后在其中新建tasksjson、lauch.json和c_cpp_properties.json三个文件。选择Windows系统的VC编译工具cl.exe和mingw64进行编译时,编译选项略有不同。两种不同编译工具下的文件内容分别如下:
5.1 VC编译器
c_cpp_properties.json
{"configurations": [{"name": "win","includePath": ["${workspaceFolder}/**","C:\\lib\\opencv\\build\\include","C:\\lib\\opencv\\build\\include\\opencv2" ],"defines": ["_DEBUG"],"compilerPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\VC\\Tools\\MSVC\\14.16.27023\bin\\Hostx64\\x64\\cl.exe","cStandard": "c11","cppStandard": "c++17","intelliSenseMode": "msvc-x64"}],"version": 4}
tasksjson
{// See https://go.microsoft.com/fwlink/?LinkId=733558// for the documentation about the tasks.json format"version": "2.0.0","tasks": [{"type": "shell","label": "cl.exe build active file","command": "cl.exe","args": ["/Zi","/EHsc","/utf-8","/Fe:","${fileDirname}\\${fileBasenameNoExtension}.exe","${file}","/DYNAMICBASE","C:\\lib\\opencv\\build\\x64\\vc15\\lib\\opencv_world450.lib"],"problemMatcher": ["$msCompile"],"group": {"kind": "build","isDefault": true}}]}
lauch.json
{"version": "0.2.0","configurations": [{"name": "cl.exe build and debug active file","type": "cppvsdbg","request": "launch","program": "${fileDirname}\\${fileBasenameNoExtension}.exe","args": [],"stopAtEntry": false,"cwd": "${workspaceFolder}","environment": [],"externalConsole": false,"preLaunchTask": "cl.exe build active file"},]}
5.2 mingw64编译器
c_cpp_properties.json
{"configurations": [{"name": "win","includePath": ["${workspaceFolder}/**","D:\\lib\\opencv\\rebuild\\install\\include","D:\\lib\\opencv\\rebuild\\install\\include\\opencv2" ],"defines": ["_DEBUG", "UNICODE", "_UNICODE"],"compilerPath": "C:\\msys64\\mingw64\\bin\\gcc.exe","cStandard": "c11","cppStandard": "c++17","intelliSenseMode": "clang-x64"}],"version": 4}
tasksjson
{// See https://go.microsoft.com/fwlink/?LinkId=733558// for the documentation about the tasks.json format"version": "2.0.0","tasks": [{"type": "shell","label": "g++.exe build active file","command": "C:\\msys64\\mingw64\\bin\\g++.exe","args": ["-g","-std=c++11","${file}","-o","${fileDirname}\\${fileBasenameNoExtension}.exe","-I", "D:\\lib\\opencv\\rebuild\\install\\include","-I", "D:\\lib\\opencv\\rebuild\\install\\include\\opencv2","-L", "D:\\lib\\opencv\\rebuild\\install\\x64\\mingw\\lib","-l", "libopencv_core450","-l", "libopencv_imgproc450","-l", "libopencv_imgcodecs450","-l", "libopencv_video450","-l", "libopencv_ml450","-l", "libopencv_highgui450","-l", "libopencv_objdetect450","-l", "libopencv_flann450","-l", "libopencv_video450","-l", "libopencv_photo450","-l", "libopencv_videoio450"],"options": {"cwd": "C:\\msys64\\mingw64\\bin"},"problemMatcher": ["$gcc"],"group": {"kind": "build","isDefault": true}}]}
lauch.json
{"version": "0.2.0","configurations": [{"name": "(gdb) Launch","type": "cppdbg","request": "launch","program": "${fileDirname}\\${fileBasenameNoExtension}.exe","args": [],"stopAtEntry": true,"cwd": "${workspaceFolder}","environment": [],"externalConsole": true,"MIMode": "gdb","miDebuggerPath": "C:\\msys64\\mingw64\\bin\\gdb.exe","preLaunchTask": "g++.exe build active file","setupCommands": [{"description": "Enable pretty-printing for gdb","text": "-enable-pretty-printing","ignoreFailures": true}]},]}
