1. 参考博客:
1.1. https://blog.csdn.net/yangSHU21/article/details/130237669( 利用OpenCV把一幅彩色图像转换成灰度图 )( vs2022_cmake_test.cpp 中的代码用的此博客的,就改了下图片文件路径而已 )
2. 检查 Visual Studio 2022是否支持 cmake:
打开 Visual Studio installer:
已安装--》修改:
工作负荷--》使用C++的桌面开发--》可选--》如果 "用于 windows的 C++ cmake工具" 勾选了,即表示你的 Visual Studio 2022 支持 cmake:
3. 操作步骤:
打开 Visual Studio 2022 --》创建新项目--》搜索 cmake--》选择 "cmake 项目( 生成不依赖于 .sln 或 .vcxproj 文件的新式跨平台 C++ 应用。 )"--》点击下一步--》 设置项目名称、位置--》点击创建,默认生成的 vs2022_cmake_test_02.cpp 文件内容如下:
#include "vs2022_cmake_test_02.h"
using namespace std;int main()
{cout << "Hello CMake." << endl;return 0;
}
默认生成的 CMakeLists.txt内容如下:
cmake_minimum_required (VERSION 3.8)# 如果支持,请为 MSVC 编译器启用热重载。
if (POLICY CMP0141)cmake_policy(SET CMP0141 NEW)set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
endif()project ("vs2022_cmake_test_02")# 将源代码添加到此项目的可执行文件。
add_executable (vs2022_cmake_test_02 "vs2022_cmake_test_02.cpp" "vs2022_cmake_test_02.h")if (CMAKE_VERSION VERSION_GREATER 3.12)set_property(TARGET vs2022_cmake_test_02 PROPERTY CXX_STANDARD 20)
endif()
将 vs2022_cmake_test.cpp 的内容修改为如下所示:
#include "vs2022_cmake_test_02.h"
#include <opencv2\opencv.hpp>using namespace cv;
using namespace std;void opencv_test();
void ConvertRGB2GRAY(const Mat& image, Mat& imageGray);void opencv_test() {Mat src = imread("D:/素材/图片/壁纸/0001.jpg");Mat src0 = imread("D:/素材/图片/壁纸/0001.jpg", 0);Mat grayImage;Mat cvt_gray_image;//读入的彩色图namedWindow("origin_image", WINDOW_NORMAL);imshow("origin_image", src);//opencv使用imread函数读入彩色图,设置第二个参数为0得到的灰度图namedWindow("opencv_image", WINDOW_NORMAL);imshow("opencv_image", src0);//使用公式GRAY=0.299*R+0.587*G+0.114*BConvertRGB2GRAY(src, grayImage);namedWindow("my_gray_image", WINDOW_NORMAL);imshow("my_gray_image", grayImage);//先读入彩色图,然后使用cvtColor函数进行灰度转化cvtColor(src, cvt_gray_image, COLOR_BGR2GRAY);namedWindow("cvt_gray_image", WINDOW_NORMAL);imshow("cvt_gray_image", cvt_gray_image);waitKey(0);
}void ConvertRGB2GRAY(const Mat& image, Mat& imageGray)
{if (!image.data || image.channels() != 3){return;}//创建一张单通道的灰度图像imageGray = Mat::zeros(image.size(), CV_8UC1);//取出存储图像像素的数组的指针uchar* pointImage = image.data;uchar* pointImageGray = imageGray.data;//取出图像每行所占的字节数size_t stepImage = image.step;size_t stepImageGray = imageGray.step;for (int i = 0; i < imageGray.rows; i++){for (int j = 0; j < imageGray.cols; j++){//opencv的通道顺序是BGR,而不是我们常说的RGB顺序pointImageGray[i * stepImageGray + j] =(uchar)(0.114 * pointImage[i * stepImage + 3 * j] +0.587 * pointImage[i * stepImage + 3 * j + 1] +0.299 * pointImage[i * stepImage + 3 * j + 2]);}}
}int main()
{cout << "Hello CMake." << endl;opencv_test();return 0;
}
此时 vs2022 报错 "找不到opencv 的头文件":
找到 opencv2 的位置如下所示:
可以直接将 "D:\install\opencv\opencv\build\include" 加入进来,即在 CMakeLists.txt 中加入 如下指令:
include_directories( "D:/install/opencv/opencv/build/include" )
但是这样不太优雅,优雅的做法是加入如下指令:
find_package(OpenCV REQUIRED)
其作用是查找 OpenCV 包,找到以后就可以直接使用内置变量 OpenCV_INCLUDE_DIRS 和 OpenCV_LIBS 了( 分别表示 opencv 的 头文件的目录位置和 链接库的目录位置 ),但是 cmake 是从哪里去找 opencv 呢?可能它内置的有一些策略吧,不放心的话或者电脑装了多个版本的 opencv,其实可以手动指定查找位置,即使用如下指令:
set(OpenCV_DIR "D:/install/opencv/opencv/build")
这里指定 "D:/install/opencv/opencv/build" 的依据是什么呢?到底是 opencv 的根目录还是头文件目录还是链接库目录呢?其实应该写 opencv 编译目录中
OpenCVConfig.cmake
文件所在的目录,例如我电脑中 OpenCVConfig.cmake 所在位置如下所示:
所以我指定的是 D:/install/opencv/opencv/build( ps:windows中 CMakeLists.txt 中的路径最好写正斜线,不能写反斜线!!!不知道双反斜线可不可以?没试过 )
修改后的最终完整的 CMakeLists.txt 如下所示:
cmake_minimum_required (VERSION 3.8)# 如果支持,请为 MSVC 编译器启用热重载。
if (POLICY CMP0141)cmake_policy(SET CMP0141 NEW)set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
endif()project ("vs2022_cmake_test_02")set(OpenCV_DIR "D:/install/opencv/opencv/build")
# 查找OpenCV包
find_package(OpenCV REQUIRED)# include_directories( "D:/install/opencv/opencv/build/include" )
# set(CMAKE_LIBRARY_PATH "D:/install/opencv/opencv/build/x64/vc16/bin" "D:/install/opencv/opencv/build/x64/vc16/lib" )# 如果OpenCV被找到,包含其头文件目录和库
message( "--------------------------------------------------" )
message( "--------------------------------------------------" )
message( "--------------------------------------------------" )
message( "OpenCV_INCLUDE_DIRS = ${OpenCV_INCLUDE_DIRS}" )
message( "OpenCV_LIBS = ${OpenCV_LIBS}" )
message( "OpenCV_FOUND = ${OpenCV_FOUND}" )if(OpenCV_FOUND)message( "OpenCV founded" )include_directories(${OpenCV_INCLUDE_DIRS})
endif()# 将源代码添加到此项目的可执行文件。
add_executable (vs2022_cmake_test_02 "vs2022_cmake_test_02.cpp" "vs2022_cmake_test_02.h")if(OpenCV_FOUND)message( "OpenCV founded" )target_link_libraries(vs2022_cmake_test_02 ${OpenCV_LIBS})
endif()message( "------------------------------------------------" )
message( "-----------------------------------------------" )
message( "--------------------------------------------------" )if (CMAKE_VERSION VERSION_GREATER 3.12)set_property(TARGET vs2022_cmake_test_02 PROPERTY CXX_STANDARD 20)
endif()
这时候编译就成功了,部分输出信息如下:
1> 工作目录: D:/code/c_code/cpp_study_demo/vs2022/vs2022_cmake_test_02/out/build/x64-debug
1> [CMake] -- OpenCV ARCH: x64
1> [CMake] -- OpenCV RUNTIME: vc16
1> [CMake] -- OpenCV STATIC: OFF
1> [CMake] -- Found OpenCV 4.10.0 in D:/install/opencv/opencv/build/x64/vc16/lib
1> [CMake] -- You might need to add D:\install\opencv\opencv\build\x64\vc16\bin to your PATH to be able to run your applications.
1> [CMake] --------------------------------------------------
1> [CMake] --------------------------------------------------
1> [CMake] --------------------------------------------------
1> [CMake] OpenCV_INCLUDE_DIRS = D:/install/opencv/opencv/build/include
1> [CMake] 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
1> [CMake] OpenCV_FOUND = 1
1> [CMake] OpenCV founded
1> [CMake] OpenCV founded
1> [CMake] ------------------------------------------------
1> [CMake] -----------------------------------------------
1> [CMake] --------------------------------------------------
1> [CMake] -- Configuring done (0.0s)
1> [CMake] -- Generating done (0.0s)
1> [CMake] -- Build files have been written to: D:/code/c_code/cpp_study_demo/vs2022/vs2022_cmake_test_02/out/build/x64-debug
1> 已提取 CMake 变量。
1> 已提取源文件和标头。
1> 已提取代码模型。
1> 已提取工具链配置。
1> 已提取包含路径。
1> CMake 生成完毕。
可以看到 :
OpenCV_INCLUDE_DIRS = D:/install/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
这时候运行 vs2022_cmake_test_02.exe报错:
使用 Everything 搜索下 opencv_world4100.dll:
应该把 D:\install\opencv\opencv\build\x64\vc16\bin 加入环境变量,其实刚才 cmake 的输入信息中已经建议这样做了:
1> [CMake] -- Found OpenCV 4.10.0 in D:/install/opencv/opencv/build/x64/vc16/lib
1> [CMake] -- You might need to add D:\install\opencv\opencv\build\x64\vc16\bin to your PATH to be able to run your applications.
1> [CMake] --------------------------------------------------
1> [CMake] --------------------------------------------
加入环境变量:
这时候就运行成功了:
记得打开新的 cmd 测试,如果是在 vs2022中测试也需要关闭工程重新打开进行测试。
4. CMakeLists.txt 中直接使用的变量 OpenCV_INCLUDE_DIRS、OpenCV_LIBS、OpenCV_FOUND 是在哪里定义的?
打开 D:\install\opencv\opencv\build 下面的 OpenCVConfig.cmake,找到如下内容:
# This file will define the following variables:
# - OpenCV_LIBS : The list of libraries to link against.
# - OpenCV_INCLUDE_DIRS : The OpenCV include directories.
# - OpenCV_COMPUTE_CAPABILITIES : The version of compute capability
# - OpenCV_VERSION : The version of this OpenCV build: "4.10.0"
# - OpenCV_VERSION_MAJOR : Major version part of OpenCV_VERSION: "4"
# - OpenCV_VERSION_MINOR : Minor version part of OpenCV_VERSION: "10"
# - OpenCV_VERSION_PATCH : Patch version part of OpenCV_VERSION: "0"
# - OpenCV_VERSION_STATUS : Development status of this build: ""
说此文件定义了这几个变量,但是这只是注释,此文件并没有直接有声明比如 set( OpenCV_INCLUDE_DIRS ... ) 的地方,可能是 该文件引用的其他文件声明了,在该文件中找到了如下内容:
function(check_one_config RES)set(${RES} "" PARENT_SCOPE)if(NOT OpenCV_RUNTIME OR NOT OpenCV_ARCH)return()endif()set(candidates)if(OpenCV_STATIC)list(APPEND candidates "${OpenCV_ARCH}/${OpenCV_RUNTIME}/staticlib")endif()if(OpenCV_CUDA)list(APPEND candidates "gpu/${OpenCV_ARCH}/${OpenCV_RUNTIME}/lib")endif()if(OpenCV_CUDA AND OpenCV_STATIC)list(APPEND candidates "gpu/${OpenCV_ARCH}/${OpenCV_RUNTIME}/staticlib")endif()list(APPEND candidates "${OpenCV_ARCH}/${OpenCV_RUNTIME}/lib")foreach(c ${candidates})set(p "${OpenCV_CONFIG_PATH}/${c}")if(EXISTS "${p}/OpenCVConfig.cmake")set(${RES} "${p}" PARENT_SCOPE)return()endif()endforeach()
endfunction()
定义了一个集合变量 candidates,如下一行:
list(APPEND candidates "${OpenCV_ARCH}/${OpenCV_RUNTIME}/lib")
应该是往集合 candidates 中追加一个路径类型的元素,其中路径中的 OpenCV_ARCH 应该对应我电脑环境的 x64,OpenCV_RUNTIME 应该对应 vc16,果然在 D:\install\opencv\opencv\build\x64\vc16\lib 下面找到了 OpenCVConfig.cmake:
打开此文件,发现了定了定义变量 OpenCV_INCLUDE_DIRS 的地方: