Visual Studio 配置C++opencv

C++opencv安装

OpenCV是一个包含丰富计算机视觉和图像处理功能的库,核心功能可以归纳为五个主要模块:图像处理、视频分析、2D特征框架、3D几何框架以及机器学习工具。图像处理部分包括图像的读取、显示、存储、转换以及滤波等基础操作;视频分析部分则关注于运动检测、背景减除、对象跟踪等功能;2D特征框架提供了从图像中提取关键点和描述符的算子,例如SIFT、SURF和ORB;3D几何框架涵盖了相机标定、三维重建等;机器学习工具则包括了一些基础的算法实现,如支持向量机、k近邻算法、决策树等。

'opencv_contrib'包提供了OpenCV主库之外的额外模块,可以访问于GitHub - opencv/opencv_contrib: Repository for OpenCV's extra modules · GitHub

(1)

官网只需要安装opencv本体,只需要去官网下载并安装即可官网

然后再vs项目的属性中,vc++目录包含目录中添加include文件夹目录和opencv2文件夹目录,库目录中添加lib文件夹目录,在链接器的输入选项中添加附加依赖项(opencv_worldxxx.lib静态库)

然后把动态库(opencv_worldxxx.dll库)复制在同级文件夹下即可(或者添加到环境变量)

(2)

如需要opencv+contrib,可以用vcpkg自动下载并安装

安装vcpkg后在终端使用C:\vcpkg\vcpkg.exe integrate install

即可自动集成, 作用:

  • 自动处理 库文件链接(.lib 文件)

  • 自动处理 DLL 依赖

  • 无需手动配置 AdditionalLibraryDirectories 和 AdditionalDependencies

vcpkg install opencv4[contrib]:x64-windows

由于:OpenCV 4 的头文件在 opencv4/opencv2/ 子目录下,需要单独配置 .vcxproj

<!-- Directory.Build.props 内容 -->

<AdditionalIncludeDirectories>

C:\vcpkg\installed\x64-windows\include\opencv4

</AdditionalIncludeDirectories>

然后复制 DLL 到项目C:\vcpkg\installed\x64-windows\bin\opencv*.dll

或者添加到系统 PATH(永久)# 系统属性 → 环境变量 → PATH → 新建
C:\vcpkg\installed\x64-windows\bin

opencv代码编写测试

Visual Studio创建新的QT项目(我使用的是QT6.8.3_msvc2022_64),随便取名字QtWidgetsApplication2

会自动创建main.cpp(主文件)、QtWidgetsApplication2.h和QtWidgetsApplication2.cpp

cpp 复制代码
main
#include "QtWidgetsApplication2.h"
// 引入Qt应用程序类的头文件
#include <QtWidgets/QApplication>

// argc: 命令行参数的个数
// argv: 命令行参数的字符串数组
int main(int argc, char *argv[])
{
    // 创建QApplication应用程序实例,管理GUI程序的控制流和主要设置
    QApplication app(argc, argv);
    // 创建主窗口对象
    QtWidgetsApplication2 window;
    // 显示主窗口,默认窗口是隐藏的,需要调用show()才能显示
    window.show();
    // 进入Qt事件循环,程序会一直运行直到窗口被关闭
    // exec()会返回应用程序的退出码
    return app.exec();
}

main函数不变,简单写一个摄像头录制视频的代码测试案例

QtWidgetsApplication2.h

cpp 复制代码
// 使用#pragma once确保头文件只被编译一次,防止重复包含
#pragma once

// 引入Qt主窗口类的头文件
#include <QtWidgets/QMainWindow>
// 引入UI界面的头文件(由.ui文件自动生成)
#include "ui_QtWidgetsApplication2.h"

// 引入OpenCV相关头文件
#include <opencv2/opencv.hpp>

// 引入Qt定时器头文件,用于定时刷新视频画面
#include <QTimer>

// QtWidgetsApplication2类:主窗口类,继承自QMainWindow
class QtWidgetsApplication2 : public QMainWindow
{
    // Q_OBJECT宏是Qt的元对象系统必需的,必须放在类定义的开始处
    // 它启发了信号与槽机制、运行时类型信息、动态属性系统等功能
    Q_OBJECT

public:
    // 构造函数:创建窗口对象时调用
    // parent: 父窗口指针,nullptr表示没有父窗口(顶级窗口)
    QtWidgetsApplication2(QWidget *parent = nullptr);

    // 析构函数:销毁窗口对象时调用,用于释放资源
    ~QtWidgetsApplication2();

private slots:
    // 槽函数:开始录制按钮被点击时调用
    void onStartRecording();

    // 槽函数:停止录制按钮被点击时调用
    void onStopRecording();

    // 槽函数:保存录制按钮被点击时调用
    void onSaveRecording();

    // 槽函数:定时器触发时调用,用于更新视频画面
    void updateFrame();

private:
    // UI界面对象,包含所有在.ui文件中定义的控件
    Ui::QtWidgetsApplication2Class ui;

    // OpenCV视频捕获对象,用于从摄像头读取视频
    cv::VideoCapture camera;

    // OpenCV视频写入对象,用于保存录制的视频
    cv::VideoWriter videoWriter;

    // Qt定时器,用于定时触发画面更新
    QTimer* timer;

    // 标记当前是否正在录制
    bool isRecording;

    // 存储录制的视频帧(内存缓冲区)
    std::vector<cv::Mat> recordedFrames;

    // 标记当前视频是否已保存
    bool isSaved;
};

QtWidgetsApplication2.cpp

// 引入当前类的头文件

#include "QtWidgetsApplication2.h"

// 引入QDateTime类头文件,用于获取当前时间生成文件名

#include <QDateTime>

// 引入QMessageBox类头文件,用于显示消息对话框

#include <QMessageBox>

// 构造函数实现

// 使用初始化列表调用基类QMainWindow的构造函数

QtWidgetsApplication2::QtWidgetsApplication2(QWidget *parent)

: QMainWindow(parent), isRecording(false), isSaved(true)

{

// 设置UI界面,会加载.ui文件中定义的所有控件和布局

ui.setupUi(this);

// 创建定时器对象,用于定时更新视频画面

timer = new QTimer(this);

// 将定时器的timeout信号连接到updateFrame槽函数

// 当定时器超时时,会自动调用updateFrame()更新视频画面

connect(timer, &QTimer::timeout, this, &QtWidgetsApplication2::updateFrame);

// 打开默认摄像头(索引为0)

// 0表示第一个摄像头设备,如果有多个摄像头可以使用1、2等

camera.open(0);

// 检查摄像头是否成功打开

if (!camera.isOpened())

{

// 如果打开失败,显示错误消息框

ui.videoLabel->setText("无法打开摄像头!");

return;

}

// 设置摄像头分辨率为640x480

camera.set(cv::CAP_PROP_FRAME_WIDTH, 640);

camera.set(cv::CAP_PROP_FRAME_HEIGHT, 480);

// 启动定时器,每33毫秒触发一次(约30帧每秒)

timer->start(33);

// 连接开始录制按钮的点击信号到对应的槽函数

connect(ui.startButton, &QPushButton::clicked, this, &QtWidgetsApplication2::onStartRecording);

// 连接停止录制按钮的点击信号到对应的槽函数

connect(ui.stopButton, &QPushButton::clicked, this, &QtWidgetsApplication2::onStopRecording);

// 连接保存录制按钮的点击信号到对应的槽函数

connect(ui.saveButton, &QPushButton::clicked, this, &QtWidgetsApplication2::onSaveRecording);

// 初始状态下禁用停止和保存按钮

ui.stopButton->setEnabled(false);

ui.saveButton->setEnabled(false);

}

// 析构函数实现

QtWidgetsApplication2::~QtWidgetsApplication2()

{

// 如果定时器还在运行,先停止它

if (timer->isActive())

{

timer->stop();

}

// 释放摄像头资源

if (camera.isOpened())

{

camera.release();

}

// 释放视频写入器资源

if (videoWriter.isOpened())

{

videoWriter.release();

}

}

// 开始录制按钮的槽函数实现

void QtWidgetsApplication2::onStartRecording()

{

// 如果已经在录制,直接返回

if (isRecording)

{

return;

}

// 清空之前录制的帧

recordedFrames.clear();

// 设置录制状态为true

isRecording = true;

// 标记视频未保存

isSaved = false;

// 更新按钮状态:开始按钮禁用,停止按钮启用,保存按钮禁用

ui.startButton->setEnabled(false);

ui.stopButton->setEnabled(true);

ui.saveButton->setEnabled(false);

// 在状态栏显示录制状态

ui.statusBar->showMessage("正在录制...");

}

// 停止录制按钮的槽函数实现

void QtWidgetsApplication2::onStopRecording()

{

// 如果没有在录制,直接返回

if (!isRecording)

{

return;

}

// 设置录制状态为false

isRecording = false;

// 更新按钮状态:开始按钮启用,停止按钮禁用,保存按钮启用

ui.startButton->setEnabled(true);

ui.stopButton->setEnabled(false);

ui.saveButton->setEnabled(true);

// 在状态栏显示停止录制信息和录制的帧数

ui.statusBar->showMessage(QString("录制已停止,共录制 %1 帧").arg(recordedFrames.size()));

}

// 保存录制按钮的槽函数实现

void QtWidgetsApplication2::onSaveRecording()

{

// 如果没有录制任何帧或已经保存过,直接返回

if (recordedFrames.empty() || isSaved)

{

return;

}

// 获取第一帧的尺寸作为视频尺寸

cv::Size frameSize = recordedFrames[0].size();

// 获取摄像头的帧率

double fps = camera.get(cv::CAP_PROP_FPS);

if (fps == 0) fps = 30.0; // 如果获取失败,使用默认值30fps

// 生成文件名:使用当前时间戳

QString fileName = QString("recorded_video_%1.avi")

.arg(QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss"));

// 创建视频写入器,尝试多种编码器

// 首先尝试 MJPEG 编码器(OpenCV 内置,兼容性最好)

videoWriter.open(fileName.toStdString(), cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), fps, frameSize);

// 如果 MJPEG 失败,尝试默认编码器

if (!videoWriter.isOpened())

{

videoWriter.open(fileName.toStdString(), 0, fps, frameSize);

}

// 检查视频写入器是否成功创建

if (!videoWriter.isOpened())

{

// 如果创建失败,显示详细的错误消息

QString errorMsg = QString("无法创建视频文件!\n文件名:%1\n尺寸:%2x%3\n帧率:%4")

.arg(fileName)

.arg(frameSize.width)

.arg(frameSize.height)

.arg(fps);

QMessageBox::warning(this, "错误", errorMsg);

return;

}

// 遍历所有录制的帧,写入视频文件

for (const auto& frame : recordedFrames)

{

videoWriter.write(frame);

}

// 释放视频写入器

videoWriter.release();

// 标记视频已保存

isSaved = true;

// 更新按钮状态:保存按钮禁用

ui.saveButton->setEnabled(false);

// 在状态栏显示保存成功信息

ui.statusBar->showMessage(QString("视频已保存:%1").arg(fileName), 5000);

}

// 更新视频画面的槽函数实现(由定时器定时调用)

void QtWidgetsApplication2::updateFrame()

{

// 声明一个Mat对象用于存储摄像头捕获的帧

cv::Mat frame;

// 从摄像头读取一帧画面

// camera.read()会自动捕获最新的一帧

camera.read(frame);

// 检查是否成功读取到帧

if (frame.empty())

{

// 如果读取失败,直接返回

return;

}

// 左右翻转画面(镜像效果)

// flipCode=1表示水平翻转(左右翻转)

cv::flip(frame, frame, 1);

// 如果正在录制,将当前帧添加到录制帧缓冲区

if (isRecording)

{

// 克隆当前帧并添加到向量中

// 必须克隆,因为Mat是引用计数,不克隆会导致所有帧都指向同一块内存

recordedFrames.push_back(frame.clone());

}

// 将OpenCV的BGR格式转换为RGB格式

// OpenCV默认使用BGR格式,Qt使用RGB格式

cv::Mat rgbFrame;

cv::cvtColor(frame, rgbFrame, cv::COLOR_BGR2RGB);

// 创建QImage对象从OpenCV Mat数据

// 参数说明:数据指针、宽度、高度、格式(RGB888)

QImage qImage(rgbFrame.data, rgbFrame.cols, rgbFrame.rows, rgbFrame.step, QImage::Format_RGB888);

// 将QImage转换为QPixmap并缩放到标签大小

// scaled()方法会按比例缩放图像以适应标签大小

// Qt::KeepAspectRatio表示保持宽高比

QPixmap pixmap = QPixmap::fromImage(qImage).scaled(ui.videoLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);

// 在videoLabel标签上显示视频画面

ui.videoLabel->setPixmap(pixmap);

}

Release打包

项目编译运行打包即可,需加入QT支持

打包目录结构

Release/

├── QtWidgetsApplication2.exe ← 主程序

├── Qt6Core.dll ← Qt核心

├── Qt6Gui.dll ← Qt GUI

├── Qt6Widgets.dll ← Qt控件

├── opencv_core4.dll ← OpenCV核心

├── opencv_videoio4.dll ← OpenCV视频IO

├── ... (其他58个DLL)

└── platforms/ ← Qt平台插件

└── qwindows.dll

相关推荐
迷途之人不知返1 天前
List的学习
数据结构·c++·学习·list
6Hzlia1 天前
【Hot 100 刷题计划】 LeetCode 23. 合并 K 个升序链表 | C++ 顺序合并
c++·leetcode·链表
今夕资源网1 天前
Visual C++运行库合集 V104.0 一个github免费开源的项目VisualCppRedist AIO
开发语言·c++·dll修复工具·dll修复·运行库·修复软件
syagain_zsx1 天前
剖析“继承”,清晰易懂
开发语言·c++
Season4501 天前
C++中论在类中成员变量定义顺序的重要性
开发语言·c++
拳里剑气1 天前
C++算法:前缀和
开发语言·c++·算法·前缀和
三克的油1 天前
YOLOV5数据学习
人工智能·学习·yolo
zhangrelay1 天前
复盘《用智能大模型复盘课程博客停更案例》
笔记·学习
sjsjsbbsbsn1 天前
RAG 基础学习总结
java·数据库·学习
啊我不会诶1 天前
Codeforces Round 1091 (Div. 2) and CodeCraft 26
c++·算法