最近在学习数字图像处理这门课的时候,偶然发现我上学期的c++opencv环境无了。又花了我一下午时间配置。想必有很多小伙伴跟我一样,配置c++opencv配置很久很久。闲话少叙,接下来,我将展示配置过程。
先大体说说需要准备哪些东西:
1.编译器:注意vscode本身是一款文本编辑器,所以我们配置vscode实质上需要为它指定编译器,我这里选MinGW。
2.cmake工具:我试下来版本不是很重要。选个windows版本的,比如:cmake-3.27.0-rc2-windows-x86_64.msi
3.接下来就是opencv源码:Releases - OpenCV
笔者这里选择的是4.5.3版本,注意点击Windows,别下错了
GitHub源码对应为4.5.3
上面就是一些大致的需要的东西,先提出来,避免你们遗漏。
我认为比较好的做法是将他们先下在一个文件夹内部,方便查找。
ok,下面,我就默认你们已经准备好了这些文件。
第一步,cmake安装:
安装没什么特别的,基本就是next,最后finish。这里必须要做的是添加cmake的bin文件夹到系统环境变量中去。
具体方法是找到cmake安装目录,win + r,输入sysdm.cpl,按下enter,依次找到高级->环境变量->系统变量->Path,再在下面添上bin路径。
如果你成功了,可以win + r,输入cmd,按下enter,命令行输入 cmake --version,应该如下图
第二步:安装opencv,就是点击下下来的软件,它会自动生成一个文件夹,结构大致如下
sources是源码,我们编译要用它,build是一个编译后用的文件,build下面的x64有vc开头的文件夹,可用来给visual stdio用,但是不支持contrib
contrib解压成一个文件夹,一会儿要用。
第三步,安装MinGW,点击安装包安装,同第一步一样,要添加环境变量,同样也是将MinGW的bin加入环境变量。
注意上面几步涉及到环境变量时要看看自己环境变量是否存在多个MinGW,或者多个cmake,保留目前的就好。
第四步:利用cmake编译。我们先打开cmake的bin目录下的cmake-gui.exe,运行会出现一个界面。我们主要添加的配置是
where is source code,他的作用是找到你要编译的源码,我们这里就是opencv的source文件夹。
where is build binaries,也就是要生成到什么位置。选择一个你能记住路径的空文件夹。
接下来按下configure
像这样选:
next
c后面选mingw下面bin目录下的gcc,c++选bin目录下的g++
Finish
等它加载完毕后,你会发现红色的选项很多。这是正常的。
接下来我们需要解决一下,因为国内无法连接外网导致的部分文件没有下载的问题。打开你build的路径,此时你会发现如下结构:点击我画出的文件
#do_copy "opencv_videoio_ffmpeg.dll" "bab661341c30862fa88627130219c0a5"
docopy是想要复制这个文件,紧接着是文件下载地址红色,下载到missing后面的文件目录下,我们下载这个文件后要重命名为和missing目录下一致的名字。
"https://raw.githubusercontent.com/opencv/opencv_3rdparty/213fcd5d4897319a83207406036c4a5957fba010/ffmpeg/opencv_videoio_ffmpeg.dll" "D:/mingGw-opencv/opencv/build/x64/sad/3rdparty/ffmpeg"
#missing "D:/mingGw-opencv/opencv/build/x64/sad/3rdparty/ffmpeg/opencv_videoio_ffmpeg.dll"
#check_md5 "D:/mingGw-opencv/opencv/sources/.cache/ffmpeg/bab661341c30862fa88627130219c0a5-opencv_videoio_ffmpeg.dll"
#copy "D:/mingGw-opencv/opencv/build/x64/sad/3rdparty/ffmpeg/opencv_videoio_ffmpeg.dll" "D:/mingGw-opencv/opencv/sources/.cache/ffmpeg/bab661341c30862fa88627130219c0a5-opencv_videoio_ffmpeg.dll"
每个do_copy都要复制,我们完成上述的工作后就可以了。注意,有些是文本文件这种,此时你右键浏览器页面,选择另存为就好。
此时再次configure,红色消失。
接下来配置选项
search框检查下列字段
- 勾选
WITH_OPENGL
- 勾选
BUILD_opencv_world
(最后会集成在一个libopencv_world453.dll
的动态库中) - 勾选
ENABLE_CXX11
(如果没有,则创建一个,按圈的就出来了) - 不勾选
WITH_IPP
- 添加
opencv_contrib
路径,添加到下列字段 - 勾选
WITH_QT
- 不勾选所有
python
相关选项(因为不需要build for python
) - 不勾选所有
TEST
选项
- 不勾选
WITH_OPENCL_D3D11_NV
- 不勾选
WITH_MSMF
- 不勾选
BUILD_opencv_hdf
不勾选 BUILD_opencv_cvv
勾选了 BUILD_opencv_world,就不能勾选这个,二者选其一,都选就会报 cvv 有关的错误。
用不到这个包就不编译了不勾选 BUILD_opencv_rgbd
添加配置 OPENCV_VS_VERSIONINFO_SKIP 并勾选(同ENABLE_CXX11)Configure
- 此时又回去查看
- 将未下载的下下来。
- 再次configure
- generate
- 然后打开你的build目录,也就是上面图片,shift+右键空白位置,点击在此处打开powershell。输入下面命令mingw32-make -j8
- j后面跟的是线程数,可加快编译。
- 等待编译完成
- 100%后,输入mingw32-make install
添加opencv路径,一般是install下面的路径到环境变量
下面是vscode配置:
找到一个没有中文的路径的文件夹。用vscode打开它,vscode有以下扩展
将下面路径关于opencv和mingw改成你的路径。
c_cpp_properties.json
{
"configurations": [
{
"name": "win",
"includePath": [
"${workspaceFolder}/**",
"D:\\mingGw-opencv\\opencv\\build\\x64\\MinGW5\\install\\include",//你的生成的文件夹下的include
"D:\\mingGw-opencv\\opencv\\build\\x64\\MinGW5\\install\\include\\opencv2" 你的生成的文件夹下的include
],
"defines": [],
"compilerPath": "D:\\mingGw-opencv\\mingw64\\bin\\gcc.exe",//你的mingw路径
"cStandard": "c11",
"cppStandard": "c++11",
"intelliSenseMode": "${default}"
}
],
"version": 4
}
launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "opencv4.5.3 debuge",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}\\Debugger\\${fileBasenameNoExtension}.exe",
"args": [],
"stopAtEntry": false, //这里如果为 false,则说明调试直接运行。(反之则停止)
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": true, //是否调用外部cmd
"MIMode": "gdb",
"miDebuggerPath": "D:\\mingGw-opencv\\mingw64\\bin\\gdb.exe",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": false
}
],
"preLaunchTask": "opencv4.5.3 compile task"
}
]
}
tasks.json
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "opencv4.5.3 compile task",
"command": "D:\\mingGw-opencv\\mingw64\\bin\\g++.exe",
"args": [
"-fdiagnostics-color=always",
"-g", // 生成和调试有关的信息
"${file}", //当前文件名
"-o", // 指定输出文件名,不加该参数则默认输出a.exe,Linux下默认a.out
"${fileDirname}\\Debugger\\${fileBasenameNoExtension}.exe",
"-m64", // 不知为何有时会生成16位应用而无法运行,加上此条可强制生成64位的
"-Wall", // 开启额外警告
"-static-libgcc", // 静态链接libgcc,一般都会加上
"-finput-charset=UTF-8",
"-fexec-charset=GBK", // 生成的程序使用GBK编码,不加这条会导致Win下输出中文乱码;繁体系统改成BIG5
"-std=c++11", //
// 下面三个路径改为自己对应的opencv编译路径
"-I","D:\\mingGw-opencv\\opencv\\build\\x64\\MinGW5\\install\\include",
"-I","D:\\mingGw-opencv\\opencv\\build\\x64\\MinGW5\\install\\include\\opencv2",
"-L", "D:\\mingGw-opencv\\opencv\\build\\x64\\MinGW5\\install\\x64\\mingw\\bin",
"-l","libopencv_world453"
],
"options": {
"cwd": "${workspaceFolder}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
#include <opencv2/opencv.hpp>
//测试代码
using namespace cv;
// 全局变量
cv::Point2f srcPoints[4]; // 用于存储源图像中的四个角
cv::Point2f dstPoints[4]; // 用于存储目标图像中的四个角
bool dragging = false; // 标志位,表示是否正在拖动鼠标
void demo(Mat &src,Mat &dst, Point2f * dstPoints)
{
// 定义四个点,分别为源图像中的四个角
//Point2f srcPoints[4] = { Point2f(0, 0), Point2f(src.cols, 0), Point2f(src.cols, src.rows), Point2f(0, src.rows) };
// 定义目标图像中对应的四个点
//Point2f dstPoints[4] = { points[0], points[1], points[2], points[3] };
// 计算透视变换矩阵
Mat M = getPerspectiveTransform(srcPoints, dstPoints);
// 进行透视变换
warpPerspective(src, dst, M, dst.size());
for (int i = 0; i < 4; i++) {
cv::circle(dst, dstPoints[i], 5, cv::Scalar(0, 255, 0), -1);
}
}
void onMouse(int event, int x, int y, int flags, void* userdata) {
if (event == cv::EVENT_LBUTTONDOWN) {
for (int i = 0; i < 4; i++) {
if (cv::norm(dstPoints[i] - cv::Point2f(x, y)) < 10) {
dragging = true;
break;
}
}
}
else if (event == cv::EVENT_LBUTTONUP) {
dragging = false;
}
if (dragging) {
for (int i = 0; i < 4; i++) {
if (cv::norm(dstPoints[i] - cv::Point2f(x, y)) < 10) {
dstPoints[i] = cv::Point2f(x, y);
break;
}
}
}
}
int main() {
cv::Mat image = cv::imread("1.jpg", cv::IMREAD_COLOR);
if (image.empty()) {
std::cout << "无法读取图像文件\n";
return -1;
}
cv::namedWindow("Image", WINDOW_FREERATIO);
cv::setMouseCallback("Image", onMouse, NULL);
int width = image.cols;
int height = image.rows;
// 设置初始的源图像四个角
srcPoints[0] = cv::Point2f(0, 0);
srcPoints[1] = cv::Point2f(width, 0);
srcPoints[2] = cv::Point2f(width, height);
srcPoints[3] = cv::Point2f(0, height);
dstPoints[0] = cv::Point2f(0, 0);
dstPoints[1] = cv::Point2f(width, 0);
dstPoints[2] = cv::Point2f(width, height);
dstPoints[3] = cv::Point2f(0, height);
//namedWindow("Image", WINDOW_NORMAL);
while (true) {
cv::Mat copy = image.clone();
// 绘制源图像四个角
//cv::Mat copy = image.clone();
demo(image, copy, dstPoints);
cv::imshow("Image", copy);
if (cv::waitKey(10) == 27) {
break;
}
}
return 0;
}