QT opencv读取视频数据,QLabel实时显示图像(定时器)

该博客介绍使用Qt结合OpenCV做实时显示视频的Demo,视频数据可来自摄像头或本地。思路是用QT做文件选择器选本地视频,用OpenCV将视频分解成帧,利用定时器定时调用显示图像接口,用QLabel显示帧图像,强调必须用定时器而非waitKey(),避免QLabel数据堵塞。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简述

使用 Qt 做一个实时显示视频的Demo,这里结合Opencv来做的。该视频可以是从摄像头实时获取的数据,也可以是本地保存的视频数据。

简述下思路:

  • 使用 QT 做一个文件选择器,选择本地视频;
  • 使用opencv读取该视频数据,将视频分解成一帧一帧的图像;
  • 利用定时器,定时的调用显示图像接口。(这里使用QLabel显示每一帧图像;定时器的时间与视频的帧率有关;);

注:这里注重说明一点,这里必须用定时器,而不可用 waitKey(),因QLabel是组件,使用waitKey()方法会使得QLabel数据堵塞,不能显示。

代码

界面展示:

1、初始化

QTimer m_timer = new QTimer(this);
VideoCapture m_cap = new VideoCapture();
//定时器信号关联 
connect(m_timer, SIGNAL(timeout()), this, SLOT(slots_catchCap()));

2、选择本地视频路径

//"选择视频"按钮点击事件
void LeakDetectionSimulator::slots_chooseVideo_Btn_Clicked()
{
	//定义文件对话框类
	QFileDialog *fileDialog = new QFileDialog(this);
	//定义文件对话框标题
	fileDialog->setWindowTitle(QStringLiteral("选择视频"));
	//设置默认文件路径
	fileDialog->setDirectory(".");
	//设置文件过滤器
	fileDialog->setNameFilter(tr("Video(*.mp4 *.avi *.mkv *.flv *.rmvb)"));
	//设置视图模式
	fileDialog->setViewMode(QFileDialog::Detail);
	//打印所选择的文件的路径
	QString fileName;
	if (fileDialog->exec())
	{
		fileName = fileDialog->selectedFiles()[0];
        //显示选择的视频路径
		ui.videoPath_LineEdit->setText(fileName);
	}
}

3、开始检测

//“开始检测”按钮点击事件
void slots_start_Btn_Clicked()
{
	if (ui.start_Btn->text().compare(QStringLiteral("停止检测")) == 0)
	{		
		//关闭定时器
		m_timer->stop();
		ui.imgShow_label->clear();
		PrintInfo("已停止检测!");
		ui.start_Btn->setText(QStringLiteral("开始检测"));
		return;
	}

	//获取全局参数
	if (ui.videoPath_LineEdit->text().compare("") == 0)
	{
		QMessageBox::about(NULL, QStringLiteral("提示"), QStringLiteral("未选择视频,请选择视频后重新操作!"));
		return;
	}

	if (ui.interval_LineEdit->text().compare("") == 0)
	{
		QMessageBox::about(NULL, QStringLiteral("提示"), QStringLiteral("未输入间隔时间,请检查!"));
		return;
	}

    //打开视频
    m_cap->open(QStr2Str(ui.videoPath_LineEdit->text()));
	if (m_cap->isOpened() == false)
    {
        PrintInfo("视频未能打开!");
		return;
    }

	//获取当前视频帧率
	double rate = m_cap->get(CV_CAP_PROP_FPS);
	//每一帧之间的延时与视频的帧率相对应
	m_delay = 1000 / rate;


	//开启定时器
	m_timer->start(m_delay);

	PrintInfo("开始检测!");

	ui.start_Btn->setText(QStringLiteral("停止检测"));
}
//QString 转 string (无中文论码)
string QStr2Str(const QString qStr)
{
	QByteArray cdata = qStr.toLocal8Bit();
	return string(cdata);
}
//获取图像(定时器关联的槽方法)
void slots_catchCap()
{
    m_cap->read(m_frame);

	if (m_frame.empty())
    {
        PrintInfo("视频读取完!");
		//关闭定时器
		m_timer->stop();
        return;
    }
	//显示图像
	ui.imgShow_label->setPixmap(QPixmap::fromImage(MatToQImage(m_frame)));
}

// Mat 转换成 QImage
QImage MatToQImage(const cv::Mat &inMat)
{
	switch (inMat.type())
	{
		case CV_8UC4:		// 8-bit, 4 channel
		{
			QImage image(inMat.data,
				inMat.cols, inMat.rows,
				static_cast<int>(inMat.step),
				QImage::Format_ARGB32);

			return image;
		}

		case CV_8UC3:		// 8-bit, 3 channel
		{
			QImage image(inMat.data,
				inMat.cols, inMat.rows,
				static_cast<int>(inMat.step),
				QImage::Format_RGB888);

			return image.rgbSwapped();
		}

	
		case CV_8UC1:// 8-bit, 1 channel
		{
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
			QImage image(inMat.data,
				inMat.cols, inMat.rows,
				static_cast<int>(inMat.step),
				QImage::Format_Grayscale8); //Format_Alpha8 and Format_Grayscale8 were added in Qt 5.5
#else
			static QVector<QRgb>  sColorTable;

			// only create our color table the first time
			if (sColorTable.isEmpty())
			{
				sColorTable.resize(256);

				for (int i = 0; i < 256; ++i)
				{
					sColorTable[i] = qRgb(i, i, i);
				}
			}

			QImage image(inMat.data,
				inMat.cols, inMat.rows,
				static_cast<int>(inMat.step),
				QImage::Format_Indexed8);

			image.setColorTable(sColorTable);
#endif
			return image;
		}

		default:
//			qWarning() << "CVS::cvMatToQImage() - cv::Mat image type not handled in switch:" << inMat.type();
			break;
	}

	return QImage();
}

因是公司项目,所以很多地方做了删减,但是大致思路都在。

<think>好的,我现在需要帮助用户解决如何使用QtOpenCV读取视频的问题。用户还要求提供示例代码和教程。首先,我得回忆一下QtOpenCV的相关知识,确保自己理解正确。 首先,Qt是一个跨平台的C++框架,常用于开发图形用户界面。而OpenCV是一个开源的计算机视觉库,提供了丰富的图像视频处理功能。用户想要结合这两者来读取视频,可能需要用到Qt的界面组件来显示视频,同时用OpenCV处理视频流。 接下来,我应该考虑如何用OpenCV读取视频OpenCV中的VideoCapture类是用来处理视频的,可以捕获摄像头输入或者读取视频文件。用户可能需要示例代码来展示如何打开视频文件,逐帧读取,并在Qt的界面中显示这些帧。 然后,Qt部分需要考虑如何显示图像。通常,QImage和QPixmap用于处理图像数据,而QLabel或自义的QWidget可以用来显示图像。可能需要将OpenCV的Mat格式转换为QImage,以便在Qt显示。 另外,视频实时显示可能需要用到定时器QTimer)来读取下一帧,保持视频流畅播放。同时,还要注意线程问题,避免界面卡顿,但可能用户暂时不需要多线程,基础示例可以先使用单线程。 现在需要检查是否有相关的引用资料。根据用户提供的引用[1]和[2],里面提到QtOpenCV结合进行图像视频操作,例如读取显示图像,捕获视频。引用[2]还提到应用举例,说明可能有示例代码可以参考。虽然具体的代码可能没有在引用中给出,但可以基于这些信息构建示例。 开始编写示例代码的结构: 1. 包含必要的头文件,比如OpenCV的core和highgui,Qt的QApplication, QLabel, QTimer等。 2. 创建VideoCapture对象,打开视频文件。 3. 检查是否成功打开视频。 4. 创建Qt的窗口和标签用于显示。 5. 使用定时器每隔一时间读取一帧,并更新标签内容。 6. 将Mat转换为QImage时需要注意颜色空间的转换,因为OpenCV默认是BGR,而Qt是RGB。 7. 处理循环,直到视频结束。 需要注意的问题:是否正确处理视频路径,转换颜色空间,释放资源,以及错误处理。例如,如果视频打不开,需要提示用户。 可能还需要说明如何配置项目,比如在.pro文件中添加OpenCV的库链接,不过用户可能已经配置好了环境,所以示例代码可能不需要这部分,但可以建议用户检查环境配置。 现在,将这些步骤转化为具体的代码。例如: 在Qt的主窗口类中,初始化VideoCapture,设置定时器,连接定时器的信号到槽函数,在槽函数中读取帧并显示。 同时,确保代码中的错误处理,比如使用isOpened()检查视频是否打开成功。 最后,测试代码是否可行,是否有内存泄漏,比如正确释放VideoCapture和Qt的资源。 总结:用户的请求是读取视频的方法和示例代码,结合QtOpenCV。需要分步骤说明,并确保代码正确,包括必要的转换和Qt的界面更新机制。同时,根据引用资料,可以引用提到的应用举例作为支持。</think>以下是如何使用QtOpenCV实现视频读取的详细步骤及示例代码: --- ### **1. 环境配置** 确保项目中已正确配置OpenCV库。在Qt的`.pro`文件中添加: ```makefile INCLUDEPATH += /path/to/opencv/include LIBS += -L/path/to/opencv/lib -lopencv_core -lopencv_videoio -lopencv_highgui ``` --- ### **2. 视频读取核心代码** 通过OpenCV的`VideoCapture`类读取视频,结合Qt的`QTimer`实现逐帧显示: ```cpp #include <QApplication> #include <QLabel> #include <QTimer> #include <opencv2/opencv.hpp> int main(int argc, char *argv[]) { QApplication app(argc, argv); // 创建视频捕获对象 cv::VideoCapture cap("input.mp4"); if (!cap.isOpened()) { qDebug() << "Error: Failed to open video!"; return -1; } // 创建Qt显示组件 QLabel label; label.setFixedSize(640, 480); label.show(); // 定时器用于触发帧更新 QTimer timer; QObject::connect(&timer, &QTimer::timeout, [&]() { cv::Mat frame; if (cap.read(frame)) { // 将BGR格式转换为RGB cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB); // 创建QImage并显示 QImage qimg(frame.data, frame.cols, frame.rows, QImage::Format_RGB888); label.setPixmap(QPixmap::fromImage(qimg.scaled(label.size()))); } else { timer.stop(); // 视频结束停止定时器 } }); timer.start(33); // 按30fps间隔触发(约33ms/帧) return app.exec(); } ``` --- ### **3. 关键步骤说明** 1. **视频捕获初始化** `VideoCapture`支持从文件(如`input.mp4`)或摄像头(参数填`0`)读取视频流,需检查`isOpened()`确认是否成功[^1]。 2. **颜色空间转换** OpenCV默认使用BGR格式,Qt的`QImage`需要RGB格式,通过`cv::cvtColor`转换。 3. **帧率控制** 使用`QTimer`以固间隔(如33ms对应30fps)触发帧读取,确保流畅播放。 4. **资源释放** QtOpenCV对象会在作用域结束时自动释放,无需手动删除。 --- ### **4. 扩展功能** - **添加播放控制**:通过按钮实现开始/暂停,动态调整`timer.start()`和`timer.stop()`。 - **实时处理**:在读取帧后添加图像处理逻辑(如边缘检测、滤镜等)。 - **多线程优化**:将视频读取和界面更新分离到不同线程,避免卡顿[^2]。 ---
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值