使用visual studio或msys2(mingw64)与VS Code编译并使用openCV

使用visual studio或msys2(mingw64)与VS Code编译并使用openCV

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-toolchain
pacman -S mingw64/mingw-w64-x86_64-make
#上述命令包含了以下3个包,因此下面3个不需要再另外安装
pacman -S mingw64/mingw-w64-x86_64-gcc
pacman -S mingw64/mingw-w64-x86_64-g++
pacman -S mingw64/mingw-w64-x86_64-gdb

#安装32位工具
pacman -S mingw32/mingw-w64-i686-toolchain
pacman -S mingw32/mingw-w64-i686-make
pacman -S mingw32/mingw-w64-i686-gcc
pacman -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:\msys64
C:\msys64\mingw64\bin
C:\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 -U
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

#安装numpy
pip 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.0VC 6.0VS 2013VC 12VS 2015VC 14VS 2017VC 15VS 2019VC 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
                }
            ]
        },
    ]
}

6. OpenCV编译中遇到的几个问题及解决办法

  • 使用MSVC编译时可以选择BUILD_opencv_world选项,但是使用mingw64编译时,选择BUILD_opencv_world总会失败,因此在使用mingw64的时候取消该选项。
  • 选择WITH_QT选项,将OPENCV与QT6一起编译的时候可能会出错,提示找不到QRegExp,这是因为从QT5到QT6时QRegExp库修改为了QRegularExpression,所以会提示找不到该库。在github的opencv_contrib仓库中有一个pr分支解决该问题,目前该分支还没有被合并到主分支中,可能需要checkout 4.x的debunch分支进行编译,可以正常通过。
  • 编译过程中遇到cannot convert char* to….某类型的错误,这是由于编码类型不同导致的错误,搜到很多将Unicode编码修改为utf-8的方法,但是都未解决该问题,最后将出错的无法转换的char*字符串转换为Text(“字符串”)或L”字符串“可以顺利通过编译,解决该问题。
  • 在使用Visual Studio编译的过程中,还出现过一个由于源文件有日语导致无法编译的错误,通过Visual Studio的高级保存选项将该文件保存为GB2312编码解决该问题。显示Visual Studio的高级保存选项参考以下参考文件。

参考文献

作者
魏智勇(John)
加入讨论

此站点使用 Akismet 来减少垃圾评论。了解我们如何处理您的评论数据

魏智勇(John)

站长,80后,创业者,擅长工业自动化与信息化技术,熟悉各种PLC,组态软件,熟悉计算机技术,熟悉LabVIEW、C,C#,JavaScript程序设计技术。

%d 博主赞过: