QT opencv(显示图片和视频)

文章目录
- 前言
- 一、使用opencv显示图片
- 二、QT opencv播放视频
- `VideoCapture` 的基本用法
- 1. **创建 `VideoCapture` 对象**
- 2. **检查是否成功打开**
- 3. **读取视频帧**
- 4. **释放资源**
- `VideoCapture` 的常用方法
- 常见用途
- `VideoCapture` 打开失败的原因
- 三、QT opencv打开摄像头
前言
本篇文章将带大家来学习使用opencv在QT中显示图片和视频等基础功能。
一、使用opencv显示图片
cv::Mat 类
cv::Mat 是 OpenCV 中用来表示图像的基本数据结构。它是一个矩阵类,可以存储图像数据、以及图像的相关信息。
主要特点
矩阵结构:cv::Mat 是一个通用的矩阵类,可以用于存储图像、特征点、深度图等数据。
数据存储:图像数据通常以矩阵的形式存储,每个像素的值可以是单通道(灰度图像)或多通道(彩色图像)。
内存管理:cv::Mat 提供了自动内存管理功能,当不再需要时会自动释放内存。
访问数据:可以通过指针、索引或迭代器来访问矩阵中的数据。
构造函数和成员函数
构造函数:cv::Mat 可以通过多种构造函数创建,如指定尺寸和数据类型的空矩阵、从图像文件加载等。
数据访问:
at<>():访问矩阵中特定位置的像素值。
data:获取矩阵数据的指针。
cv::imread 函数
cv::imread 是 OpenCV 中用来从文件读取图像并将其加载到 cv::Mat 对象中的函数。
主要参数
filename:要读取的图像文件的路径。
flags:读取图像的标志,决定图像的读取模式。
cv::IMREAD_COLOR(默认):以彩色图像的形式读取,忽略图像的透明度。
cv::IMREAD_GRAYSCALE:以灰度图像的形式读取。
cv::IMREAD_UNCHANGED:读取图像时包括图像的 alpha 通道(透明度)。
widget.cpp:
#include"widget.h"#include"ui_widget.h"#include #include #include // 将 OpenCV 的 Mat 转换为 Qt 的 QImageQImage matToQImage(constcv::Mat&mat){ switch(mat.type()){ caseCV_8UC1:returnQImage(mat.data,mat.cols,mat.rows,mat.step,QImage::Format_Grayscale8);caseCV_8UC3:returnQImage(mat.data,mat.cols,mat.rows,mat.step,QImage::Format_RGB888).rgbSwapped();default:qWarning("Unsupported image format");returnQImage();}}Widget::Widget(QWidget *parent):QWidget(parent),ui(new Ui::Widget){ ui->setupUi(this);// 创建 QLabel 和 QPushButton 实例button1 =new QPushButton("Button",this);// 创建并设置按钮的文本label.setFixedSize(640,480);// 设置 label 的固定大小// 创建水平布局并将控件添加到布局中Hlayout =new QHBoxLayout(this);Hlayout->addWidget(&label);// 将 QLabel 添加到布局中Hlayout->addWidget(button1);// 将 QPushButton 添加到布局中setLayout(Hlayout);// 将布局设置为 Widget 的布局cv::Mat image =cv::imread("H:/QT opencv/code/myopencv/icon/1.jpg");// 读取图像// 将 OpenCV 的 Mat 转换为 Qt 的 QImageQImage qImage =matToQImage(image);// 显示图像label.setPixmap(QPixmap::fromImage(qImage));}Widget::~Widget(){ delete ui;}
widget.h:
#ifndefWIDGET_H#defineWIDGET_H#include #include #include #include QT_BEGIN_NAMESPACEnamespace Ui { class Widget;}QT_END_NAMESPACEclass Widget :public QWidget{ Q_OBJECT QLabel label;QHBoxLayout*Hlayout;QPushButton*button1;public:Widget(QWidget *parent =nullptr);~Widget();private:Ui::Widget *ui;};#endif// WIDGET_H
代码思路总结
组件创建:在构造函数中,创建了 QPushButton 和 QLabel 实例,并设置了图像显示和按钮的文本。
布局管理:使用 QHBoxLayout 布局管理器将 QLabel 和 QPushButton 添加到布局中,确保它们在窗口中水平排列。
图像处理:读取图像文件,使用 matToQImage 函数将 OpenCV 的 Mat 对象转换为 Qt 的 QImage 对象,并设置为 QLabel 的显示内容。
显示效果:
二、QT opencv播放视频
VideoCapture
是 OpenCV 库中用于视频捕获和读取的类。它能够从视频文件、摄像头或其他视频流中捕获帧,并将其作为图像进行处理和显示。以下是关于 VideoCapture
的详细讲解。
VideoCapture
的基本用法
1. 创建 VideoCapture
对象
从摄像头捕获:
cv::VideoCapture cap(0);// 打开默认摄像头
- 参数
0
表示打开默认摄像头。如果有多个摄像头,可以使用1
、2
等来指定。
- 参数
从视频文件读取:
cv::VideoCapture cap("video.mp4");// 打开视频文件
- 参数是视频文件的路径。
2. 检查是否成功打开
- 成功打开摄像头或视频文件后,应该检查是否成功打开:
if(!cap.isOpened()){ std::cerr <<"Error: Could not open video file or camera"<<std::endl;return-1;}
cap.isOpened()
返回true
表示成功打开,返回false
表示打开失败。
3. 读取视频帧
- 逐帧读取:
cv::Mat frame;while(cap.read(frame)){ // 在这里处理帧,例如显示它cv::imshow("Frame",frame);// 等待 30 毫秒并检查是否按下了退出键if(cv::waitKey(30)>=0){ break;}}
cap.read(frame)
读取一帧并存储到frame
中。读取成功返回true
,否则返回false
。cv::imshow("Frame", frame)
显示当前帧。cv::waitKey(30)
等待 30 毫秒,并检测是否按下键盘。如果按下键(例如Esc
),可以退出循环。
4. 释放资源
- 当捕获或读取操作完成后,应释放资源:
cap.release();cv::destroyAllWindows();
VideoCapture
的常用方法
bool open(int device)
: 打开摄像头设备,参数为设备索引。bool open(const std::string &filename)
: 打开视频文件,参数为文件路径。bool isOpened()
: 检查视频源是否成功打开。bool read(cv::Mat &image)
: 读取当前帧并存储在image
中。void release()
: 释放视频捕获设备或文件。double get(int propId)
: 获取视频属性,例如帧宽、高、帧率等。- 例如,
cap.get(cv::CAP_PROP_FRAME_WIDTH)
返回帧的宽度。
- 例如,
bool set(int propId, double value)
: 设置视频属性,例如帧宽、高、帧率等。
常见用途
摄像头实时捕获:通过
VideoCapture
可以捕获摄像头实时视频流,并进行处理、显示或保存。视频文件读取和处理:可以读取本地或远程的视频文件,逐帧处理,如视频剪辑、帧插值、目标跟踪等。
视频属性获取和设置:可以获取和设置视频流的属性,如帧率、分辨率、亮度、对比度等。
VideoCapture
打开失败的原因
- 视频文件路径错误:检查视频文件路径是否正确,文件是否存在。
- 文件格式不支持:确保 OpenCV 支持所使用的视频文件格式。
- 缺少解码器:在某些系统上,缺少必要的视频解码器,尤其是对于某些编码格式如 H.264。
- 摄像头被占用:检查摄像头是否被其他程序占用,或者硬件是否有问题。
widget.cpp:
#include"widget.h"#include"ui_widget.h"#include #include Widget::Widget(QWidget *parent):QWidget(parent),ui(new Ui::Widget),videoLabel(new QLabel(this)),timer(new QTimer(this)){ ui->setupUi(this);// 设置 videoLabel 的尺寸videoLabel->setFixedSize(1000,1000);// 创建定时器并连接到槽函数connect(timer,&QTimer::timeout,this,&Widget::updateFrame);// 打开视频文件cap.open("H:/QT opencv/code/Test/1.mp4");if(!cap.isOpened()){ qWarning("Error: Could not open video file.");return;}// 启动定时器,每30毫秒更新一次视频帧timer->start(30);}Widget::~Widget(){ cap.release();delete ui;}QImage Widget::matToQImage(constcv::Mat&mat){ switch(mat.type()){ caseCV_8UC1:returnQImage(mat.data,mat.cols,mat.rows,mat.step,QImage::Format_Grayscale8);caseCV_8UC3:returnQImage(mat.data,mat.cols,mat.rows,mat.step,QImage::Format_RGB888).rgbSwapped();default:qWarning("Unsupported image format");returnQImage();}}voidWidget::updateFrame(){ cv::Mat frame;if(cap.read(frame)){ // 将 OpenCV 的 Mat 转换为 Qt 的 QImageQImage qImage =matToQImage(frame);// 更新 videoLabel 显示videoLabel->setPixmap(QPixmap::fromImage(qImage));}}
widget.h:
#ifndefWIDGET_H#defineWIDGET_H#include #include #include #include QT_BEGIN_NAMESPACEnamespace Ui { class Widget;}QT_END_NAMESPACEclass Widget :public QWidget{ Q_OBJECTpublic:Widget(QWidget *parent =nullptr);~Widget();private slots:voidupdateFrame();// 更新视频帧的槽函数private:Ui::Widget *ui;QLabel *videoLabel;// 显示视频的标签QTimer *timer;// 定时器用于刷新视频帧cv::VideoCapture cap;// OpenCV 视频捕获对象QImage matToQImage(constcv::Mat&mat);// 将 cv::Mat 转换为 QImage};#endif// WIDGET_H
运行效果:
三、QT opencv打开摄像头
widget.cpp:
#include"widget.h"#include"ui_widget.h"#include #include Widget::Widget(QWidget *parent):QWidget(parent),ui(new Ui::Widget),cap(1)// 打开摄像头{ ui->setupUi(this);cameraLabel =new QLabel(this);// 用于显示摄像头画面的 QLabelcameraLabel->setFixedSize(640,480);// 设置显示区域的大小if(!cap.isOpened()){ qWarning("Error: Could not open camera");return;}timer =new QTimer(this);connect(timer,&QTimer::timeout,this,&Widget::updateFrame);timer->start(30);// 每 30 毫秒更新一次画面}Widget::~Widget(){ cap.release();// 释放摄像头delete ui;}voidWidget::updateFrame(){ cv::Mat frame;cap >>frame;// 读取摄像头当前帧if(frame.empty()){ return;}QImage qImage =matToQImage(frame);// 将 OpenCV 的 Mat 转换为 QImagecameraLabel->setPixmap(QPixmap::fromImage(qImage));// 显示图像}QImage Widget::matToQImage(constcv::Mat &mat){ switch(mat.type()){ caseCV_8UC1:returnQImage(mat.data,mat.cols,mat.rows,mat.step,QImage::Format_Grayscale8);caseCV_8UC3:returnQImage(mat.data,mat.cols,mat.rows,mat.step,QImage::Format_RGB888).rgbSwapped();default:qWarning("Unsupported image format");returnQImage();}}
widget.h:
#ifndefWIDGET_H#defineWIDGET_H#include #include #include #include QT_BEGIN_NAMESPACEnamespace Ui { class Widget;}QT_END_NAMESPACEclass Widget :public QWidget{ Q_OBJECTpublic:Widget(QWidget *parent =nullptr);~Widget();private slots:voidupdateFrame();private:Ui::Widget *ui;QLabel *cameraLabel;QTimer *timer;cv::VideoCapture cap;QImage matToQImage(constcv::Mat&mat);};#endif// WIDGET_H
运行效果:
分享让更多人看到