cmake + opencv + vs2019 学习笔记 1

cmake + opencv + vs2019 学习笔记 1 (TODO)

目录

  • cmake + opencv + vs2019 学习笔记 1 (TODO)
    • project 1
      • 1. 准备(编译 OpenCV,一个 OpenCV示例程序)
      • 2. 编写`CMakeLists.txt`文件
      • 3. 使用 cmake 用外部编译(out-of-source)方式构建项目
      • 4. Visual Studio 生成项目(Debug + Release,x64)
      • 5. 执行 .exe 文件(Debug + Release)
      • 6. cmake 命令学习
    • project 2 (TODO)
    • 参考

project 1

由于项目需要,这段时间要进行 opencv+cpp 的开发。对比 python 开发中利用 Anaconda 维护不同的开发环境,并用 conda 或 pip 管理各个环境中的包和依赖项1,c++的项目就要复杂的多了。在 python 要安装 opencv-python 只是一行命令的事 pip install opencv-python,换到 cpp+vs 下就是各种折腾,首先编译 OpenCV 库(可以参考官网教程),然后就是最麻烦的步骤:用 cmake 构建工程。说麻烦,主要是对 cmake 命令不熟悉,不知道如何编写 CMakeLists.txt,同时在网上收集到的不少资料提供的解决办法都很具体,换一个方式可能就又出问题了。忙乎了几天,终于找到了几个教程资料234,现在要做的就是抓紧时间学一学。

1. 准备(编译 OpenCV,一个 OpenCV示例程序)

准备1:编译完 OpenCV 后找到 OpenCVConfig.cmake 所在路径,我的系统中的路径为 C:\OpenCV\opencv\build\x64\vc15\lib

准备2:一个 OpenCV 相机抓取示例程序video_capture.cpp(源码为官方示例,名称自己命名的),可以到官网下载

#include 
#include 
#include 
#include 
#include 

using namespace cv;
using namespace std;

int main(int, char**)
{
    Mat frame;
    //--- INITIALIZE VIDEOCAPTURE
    VideoCapture cap;
    // open the default camera using default API
    // cap.open(0);
    // OR advance usage: select any API backend
    int deviceID = 0;             // 0 = open default camera
    int apiID = cv::CAP_ANY;      // 0 = autodetect default API
    // open selected camera using selected API
    cap.open(deviceID + apiID);
    // check if we succeeded
    if (!cap.isOpened()) {
        cerr << "ERROR! Unable to open camera\n";
        return -1;
    }

    //--- GRAB AND WRITE LOOP
    cout << "Start grabbing" << endl
        << "Press any key to terminate" << endl;
    for (;;)
    {
        // wait for a new frame from camera and store it into 'frame'
        cap.read(frame);
        // check if we succeeded
        if (frame.empty()) {
            cerr << "ERROR! blank frame grabbed\n";
            break;
        }
        // show live and wait for a key with timeout long enough to show images
        imshow("Live", frame);
        if (waitKey(5) >= 0)
            break;
    }
    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}

project 1 项目的树状结构如图,其包含在info.txt文件中,是在命令行中使用tree /f > info.txt生成的5

D:.
│  CMakeLists.txt
│  info.txt
│  video_capture.cpp
│  
└─build

2. 编写CMakeLists.txt文件

# requirement of cmake version
cmake_minimum_required(VERSION 3.10)

# project name
set(name opencv_test)
PROJECT(${name})
message(STATUS "project name: ${name}")

# find required opencv
set(OpenCV_DIR "C:\\OpenCV\\opencv\\build\\x64\\vc15\\lib")
# set(OpenCV_DIR "C:\\OpenCV\\opencv\\build\\")  # 这两个目录中都包含 OpenCVConfig.cmake 文件,两种设置都可以构建项目

find_package(OpenCV REQUIRED)

message(STATUS "OpenCV library status:")
message(STATUS "	config: ${OpenCV_DIR}")
message(STATUS "	version: ${OpenCV_VERSION}")
message(STATUS "	libraries: ${OpenCV_LIBS}")
message(STATUS "	include path: ${OpenCV_INCLUDE_DIRS}")

# directory of opencv headers
include_directories(${OpenCV_INCLUDE_DIRS})
message(STATUS "OpenCV_INCLUDE_DIRS: ${OpenCV_INCLUDE_DIRS}")

# name of executable file and path of source file
set(SRC_LIST video_capture.cpp)
message(STATUS "SRC_LIST: ${SRC_LIST}")
add_executable(${name} ${SRC_LIST})

# opencv libraries
target_link_libraries(${name} ${OpenCV_LIBS})
message(STATUS "OpenCV_LIBS: ${OpenCV_LIBS}")

注:关于 OpenCV_DIR 的值是 “C:\OpenCV\opencv\build\x64\vc15\lib” 还是 “C:\OpenCV\opencv\build\”
两个路径都可以成功构建 OpenCV 项目,但是在使用 BeyondCompare 软件对比 cmake 构建信息后发现有些不同:
左图为 “C:\OpenCV\opencv\build\x64\vc15\lib” 的输出结果
右图为 “C:\OpenCV\opencv\build\” 的输出结果
cmake + opencv + vs2019 学习笔记 1_第1张图片
“C:\OpenCV\opencv\build\” 目录包含文件如下
cmake + opencv + vs2019 学习笔记 1_第2张图片

3. 使用 cmake 用外部编译(out-of-source)方式构建项目

打开命令行进入建立的\build目录,并执行cmake ..

D:\P_project_SRS_cpp\project_1\build>cmake ..
-- Building for: Visual Studio 16 2019
-- Selecting Windows SDK version 10.0.17763.0 to target Windows 10.0.18363.
-- The C compiler identification is MSVC 19.24.28314.0
-- The CXX compiler identification is MSVC 19.24.28314.0
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.24.28314/bin/Hostx64/x64/cl.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- project name: opencv_test
-- Found OpenCV: C:/OpenCV/opencv/build (found version "4.1.0")
-- OpenCV library status:
--      config: C:\OpenCV\opencv\build\x64\vc15\lib
--      version: 4.1.0
--      libraries: opencv_calib3d;opencv_core;opencv_dnn;opencv_features2d;opencv_flann;opencv_gapi;opencv_highgui;opencv_imgcodecs;opencv_imgproc;opencv_ml;opencv_objdetect;opencv_photo;opencv_stitching;opencv_video;opencv_videoio;opencv_world
--      include path: C:/OpenCV/opencv/build/include
-- OpenCV_INCLUDE_DIRS: C:/OpenCV/opencv/build/include
-- SRC_LIST: video_capture.cpp
-- OpenCV_LIBS: opencv_calib3d;opencv_core;opencv_dnn;opencv_features2d;opencv_flann;opencv_gapi;opencv_highgui;opencv_imgcodecs;opencv_imgproc;opencv_ml;opencv_objdetect;opencv_photo;opencv_stitching;opencv_video;opencv_videoio;opencv_world
-- Configuring done
-- Generating done
-- Build files have been written to: D:/P_project_SRS_cpp/project_1/build

进入\build目录,可以看见 cmake 构建的工程文件
cmake + opencv + vs2019 学习笔记 1_第3张图片

4. Visual Studio 生成项目(Debug + Release,x64)

通过visual studio打开opencv_test.sln文件,在这里我准备分别生成 64 位的 DebugRelease版本的可执行文件(如下图Debug版本生成,Release版本在红框中下拉列表中选择)
cmake + opencv + vs2019 学习笔记 1_第4张图片
再次进入\build目录,可以看见刚刚生成的\Debug\Release目录,可以进入这两个目录中查看生成的文件(如下图)
cmake + opencv + vs2019 学习笔记 1_第5张图片
\Debug目录中的文件
cmake + opencv + vs2019 学习笔记 1_第6张图片
\Release目录中的文件
cmake + opencv + vs2019 学习笔记 1_第7张图片

5. 执行 .exe 文件(Debug + Release)

现在可以双击可执行文件打开相机了(双目相机由于去掉了红外滤光片,图像会偏红)
Debug模式的执行文件运行结果
cmake + opencv + vs2019 学习笔记 1_第8张图片
Release模式的执行文件运行结果
cmake + opencv + vs2019 学习笔记 1_第9张图片

6. cmake 命令学习

1. 首先需要确定 cmake 的最低版本号,这个命令不是强制性的。
cmake 的命令大小写无关,比如命令find_package等价于FIND_PACKAGE,但是在写CMakeLists.txt 文件时尽量保证一致性。

cmake_minimum_required(VERSION 3.10)

2. 然后需要设置项目名称

set(name opencv_test)
PROJECT(${name})
message(STATUS “project name: ${name}”)

这里使用set命令语法为,它可以显示地定义变量2。用 set 将变量 name 赋值 opencv_test

SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])

接下来使用project命令(格式如下)将项目名称通过引用变量${name}将项目名设定为 opencv_test。(name:变量;${name}:引用 name 变量)4。 这个指令隐式的定义了两个 cmake 变量:_BINARY_DIR 以及_SOURCE_DIR,这里OPENCV_TEST。同时 cmake 系统也帮助我们预定义了 PROJECT_BINARY_DIRPROJECT_SOURCE_DIR变量,他们的值分别跟 OPENCV_TEST_BINARY_DIROPENCV_TEST_SOURCE_DIR 一致,为了统一起见,建议以后直接使用 PROJECT_BINARY_DIR,PROJECT_SOURCE_DIR,即使修改了工程名称,也不会影响这两个变量。4

PROJECT(projectname [CXX] [C] [Java])

-- OPENCV_TEST_BINARY_DIR D:/P_project_SRS_cpp/project_1/build
-- OPENCV_TEST_SOURCE_DIR D:/P_project_SRS_cpp/project_1/build
-- PROJECT_BINARY_DIR D:/P_project_SRS_cpp/project_1/build
-- PROJECT_SOURCE_DIR D:/P_project_SRS_cpp/project_1/build

message的语法。这个指令用于向终端输出用户定义的信息,包含了三种类型:
SEND_ERROR,产生错误,生成过程被跳过。
SATUS,输出前缀为—的信息。
FATAL_ERROR,立即终止所有 cmake 过程.

MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] “message to display”…)

3. 接下来搜索编译的 OpenCV 包
使用find_package命令从外部项目中搜寻并载入配置 ,_FOUND变量将会被设置如果目标包被找到。

set(OpenCV_DIR “C:\OpenCV\opencv\build\x64\vc15\lib”)
find_package(OpenCV REQUIRED)

为了找到(find_package) OpenCV 包,我们需要设置(set) OpenCV_DIR 变量,它的值为包含 OpenCVConfig.cmake 文件的目录的绝对值,如准备1中所说的,我的 OpenCVConfig.cmake 文件路径为:

C:\OpenCV\opencv\build\x64\vc15\lib
cmake + opencv + vs2019 学习笔记 1_第10张图片
find_package命令用来调用预定义在 CMAKE_MODULE_PATH 下的 Find.cmake 模块,你也可以自己定义 Find 模块,通过 SET(CMAKE_MODULE_PATH dir) 将其放入工程的某个目录中供工程使用2

如果包找到以后,一些变量将会被定义,比如(见 OpenCVConfig.cmake 文件中内容):

#    find_package(OpenCV REQUIRED core OPTIONAL_COMPONENTS viz)
#
#    If the module is found then OPENCV__FOUND is set to TRUE.
#
#    This file will define the following variables:
#      - OpenCV_LIBS                     : The list of all imported targets for OpenCV modules. (OpenCV 模块的所有导入目标的列表,.lib 文件)
#      - OpenCV_INCLUDE_DIRS             : The OpenCV include directories. (OpenCV 的包含目录,.h/.hpp 文件)
#      - OpenCV_COMPUTE_CAPABILITIES     : The version of compute capability.
#      - OpenCV_ANDROID_NATIVE_API_LEVEL : Minimum required level of Android API.
#      - OpenCV_VERSION                  : The version of this OpenCV build: "4.1.0"
#      - OpenCV_VERSION_MAJOR            : Major version part of OpenCV_VERSION: "4"
#      - OpenCV_VERSION_MINOR            : Minor version part of OpenCV_VERSION: "1"
#      - OpenCV_VERSION_PATCH            : Patch version part of OpenCV_VERSION: "0"
#      - OpenCV_VERSION_STATUS           : Development status of this build: ""
#
#    Advanced variables:
#      - OpenCV_SHARED                   : Use OpenCV as shared library
#      - OpenCV_INSTALL_PATH             : OpenCV location
#      - OpenCV_LIB_COMPONENTS           : Present OpenCV modules list
#      - OpenCV_USE_MANGLED_PATHS        : Mangled OpenCV path flag
#
#    Deprecated variables:
#      - OpenCV_VERSION_TWEAK            : Always "0"

OpenCV 中的目录解释6
包含目录(include directory)[OpenCV_INCLUDE_DIRS]:包含 .h 或 .hpp 文件的搜索目录
库目录(library directory)[OpenCV_LIBS]:包含 .lib 文件的搜索目录

在我的配置中,这两个变量的值为:

– OpenCV_INCLUDE_DIRS: C:/OpenCV/opencv/build/include
– OpenCV_LIBS: opencv_calib3d;opencv_core;opencv_dnn;opencv_features2d;opencv_flann;opencv_gapi;opencv_highgui;opencv_imgcodecs;opencv_imgproc;opencv_ml;opencv_objdetect;opencv_photo;opencv_stitching;opencv_video;opencv_videoio;opencv_world

包含目录中的文件如下:
cmake + opencv + vs2019 学习笔记 1_第11张图片

4. 引入头文件搜索,使工程找到 OpenCV 的 .h.hpp 文件

# directory of opencv headers
include_directories(${OpenCV_INCLUDE_DIRS})
message(STATUS "OpenCV_INCLUDE_DIRS: ${OpenCV_INCLUDE_DIRS}")

为了让我们的工程能够找到 OpenCV 包中的 .h.hpp 头文件,我们需要引入一个新的指令INCLUDE_DIRECTORIES,这条指令可以用来向工程添加多个特定的头文件搜索路径2,在此项目中,dir的值为${OpenCV_INCLUDE_DIRS}C:/OpenCV/opencv/build/include,其完整语法为:

INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 …)

5. 为项目添加 OpenCV 的共享库(.lib)

# opencv libraries
target_link_libraries(${name} ${OpenCV_LIBS})
message(STATUS "OpenCV_LIBS: ${OpenCV_LIBS}")

使用target_link_libraries命令为项目可执行文件添加需要链接的共享库,${name}opencv_text.exe ${OpenCV_LIBS} 的值参见上文。TARGET_LINK_LIBRARIES 的全部语法是:

TARGET_LINK_LIBRARIES(target library1
library2
…)

6. 让工程生成一个可执行文件 .exe

# name of executable file and path of source file
set(SRC_LIST video_capture.cpp)
message(STATUS "SRC_LIST: ${SRC_LIST}")
add_executable(${name} ${SRC_LIST})

定义了这个工程会生成一个文件名为 hello 的可执行文件,相关的源文件是 SRC_LIST 中定义的源文件列表,在这个项目中 SRC_LIST 只有一个源文件,即video_capture.cpp

project 2 (TODO)

参考


  1. Anaconda介绍、安装及使用教程:https://zhuanlan.zhihu.com/p/32925500 ↩︎

  2. Cmake 实践(pdf):http://file.ncnynl.com/ros/CMake Practice.pdf ↩︎ ↩︎ ↩︎ ↩︎

  3. cmake 学习笔记(一):https://blog.csdn.net/dbzhang800/article/details/6314073 ↩︎

  4. 調整 CMakeLists.txt for OpenCV 4.1.0(已安裝多版本opencv@2, opencv@3…):https://davistseng.blogspot.com/2019/06/cmakeliststxt-for-opencv-410opencv2.html ↩︎ ↩︎ ↩︎

  5. 命令行tree命令生成文件树:https://kingganzeng.github.io/命令行tree命令生成文件树/ ↩︎

  6. 包含目录、库目录、附加包含目录、附加库目录、附加依赖项之详解:https://blog.csdn.net/u012043391/article/details/54972127 ↩︎

你可能感兴趣的:(opencv,cmake)