当前位置: 首页 > news >正文

使用OpenCV的VideoCapture播放视频文件示例

OpenCV计算机视觉开发实践:基于Qt C++ - 商品搜索 - 京东

构造VideoCapture对象

类VideoCapture既支持从视频文件(.avi 、*.mp4、.mpg等格式)读取,也支持直接从摄像机(比如计算机自带的摄像头)中读取。要想获取视频,需要先创建一个VideoCapture对象。VideoCapture对象的创建方式有以下3种:

(1)从视频文件中读取视频。如果是从文件(.mpg或.avi格式)中读取视频,则在定义对象的时候,可以把视频文件的路径作为参数传给构造函数。对象创建以后,OpenCV将会打开该视频文件并做好准备读取它,并且VideoCapture提供了成员函数isOpened来判断文件是否打开成功,如果成功将返回true(建议在打开视频或摄像头时都使用该成员函数判断是否打开成功)。用于读取视频文件的构造函数如下:

VideoCapture (const String &filename, int apiPreference=CAP_ANY);

其中参数filename是视频文件的文件名(可以包含路径),如果不包含路径,则在当前路径下打开文件; apiPreference表示首选使用的后端捕获API,默认是使用任意捕获API,用宏CAP_ANY来表示。比如我们定义一个VideoCapture对象并打开D盘上的test.avi文件:

cv::VideoCapture capture("D:/test.avi");  // 从视频文件读取

(2)从摄像机中读取视频。如果是从摄像机中读取视频,这种情况下,构造函数会给出一个整型索引参数,用于表示想要访问的摄像机。对于摄像机而言,这个索引参数就是一个标志数字,如果只有1个摄像机,那么索引参数就是0;如果系统中有多个摄像机,那么只要将其值向上增加即可。读取摄像头中的视频的构造函数如下:

VideoCapture (int index, int apiPreference=CAP_ANY);

其中参数index表示要打开的视频捕获设备(摄像头)的ID,如果使用默认后端的默认摄像头,只需传递0;apiPreference表示首选使用的后端捕获API,默认是使用任意捕获API,用宏CAP_ANY来表示,多数情况下,由于我们只有一个摄像机,因此没必要指定摄像机的域,此时使用cv::CAP_ANY是一种高效的方式。参数apiPreference表示摄像机的类型,这个域值可以是下面任意一个预定义常量:

CAP_ANY:自动选择APICAP_DSHOW:通过视频输入,例如,摄像头输入CAP_FFMPEG:使用FFMPEG库CAP_IMAGES:打开一个图像序列(例如,img_%02d.jpg)

(3)不带参数构造一个VideoCapture对象。使用类VideoCapture的不带参数的构造函数来创建一个VideoCapture对象,然后用成员函数open打开一个视频文件或摄像头。open函数声明如下:

virtual bool open (const String &filename, int apiPreference=CAP_ANY);virtual bool open (int index, int apiPreference=CAP_ANY);

两个open函数的参数和前面两个构造函数的参数含义一样,这里不再赘述。

判断视频是否打开成功

当我们打开一个视频文件或摄像头视频后,可以用成员函数isOpened来判断是否打开成功。该函数声明如下:

virtual bool isOpened() const;

若打开成功,则返回true,否则返回false。

比如:

VideoCapture capture;capture.open(0, CAP_DSHOW);    // 打开摄像头if (!capture.isOpened())    // 判断打开是否成功puts("open failed");

12.5  读取视频帧

要播放视频,肯定要把每一帧视频图像都读出来,然后显示出来。读取方式有两种,一种是用运算符>>,直接输出视频帧到Mat对象中。>>是一个重载运算符,定义如下:

virtual VideoCapture& operator >> (CV_OUT Mat& image);

例如:

Mat frame;VideoCapture capture("test.mp4");while (1) {capture >> frame;           // 输出一帧到Mat对象中if (frame.empty()) {       // 播放完就退出printf("播放完成\n");break;}imshow("读取视频", frame);   // 显示帧waitKey(20);}

当输出完一帧后,下次就会输出下一帧。

另外一种方式是通过成员函数read,该函数声明如下:

virtual bool read(OutputArray image);

参数image用来存放读取到的当前视频帧。若读取成功,则返回true,否则返回false。例如:

Mat frame;VideoCapture capture(0, CAP_DSHOW);while (capture.read(frame)){imshow("video-demo", frame);char c = waitKey(66);if (c == 27)  break;}

播放视频文件

播放视频文件的基本步骤就是先构造VideoCapture对象,再打开视频文件,接着用一个循环逐帧读取并显示读取到的视频帧,然后间隔一段时间读取下一个视频帧并显示,依次循环,直到全部视频帧读取完毕。

【例12.1】播放MP4视频文件

   新建一个控制台工程,工程名是conplay。

   打开main.cpp,并输入如下代码:

#include <opencv2/opencv.hpp>
using namespace cv;
#include <QDebug>void play(const char *filename)
{Mat frame;int i=0;VideoCapture capture(filename);if (!capture.isOpened()){printf("open %s failed",filename);return;}// 获取整个视频帧数long  totalFrameNumber = capture.get(CAP_PROP_FRAME_COUNT);qDebug()<<"整个视频帧数:"<<totalFrameNumber;while (i<totalFrameNumber) {capture >> frame;if (frame.empty()) break; 	// 播放结束就跳出循环imshow("read video", frame);	// 显示帧waitKey(1);i++;}qDebug()<<"播放完成\n";
}
int main() {play("/root/hd.mp4");
}

在上述代码中,我们首先定义了一个VideoCapture对象capture,并传入视频文件的文件名;然后利用成员函数get获取视频的帧数,这样在后面的while循环中可以控制播放的帧数。当frame为空时,说明视频帧没有了,也就是播放完毕了,此时跳出循环。每一帧其实就是一幅图片,可以用imshow函数把图片显示出来。当显示速度很快时,多个图片连续显示,看起来就是视频了。这里我们设置每个帧的显示间隔时间是1毫秒。

   保存工程并运行,结果如图12-2所示。

图12-2

播放摄像头视频的主要流程与之类似,只不过在调用open的时候,需要修改一下传入的整型数据。读者可以准备一个USB接口的计算机摄像头,然后把USB口插入计算机的USB插槽中,通常是不需要安装驱动程序的。

http://www.xdnf.cn/news/321769.html

相关文章:

  • 偏导数和梯度
  • shell-sed
  • MCP 规范新版本特性全景解析与落地实践
  • 图片文件转base64存储在数据库
  • redis端口漏洞未授权访问漏洞
  • Rust 中 Arc 的深度分析:从原理到性能优化实践
  • 2020年NCA CCF-C,改进灰狼算法RSMGWO+大规模函数优化,深度解析+性能实测
  • 鸿蒙开发——4.ArkTS快速入门指南
  • 我的世界云端服务器具体是指什么?
  • Laravel 12 实现验证码功能
  • 代码随想录算法训练营第三十四天
  • WordPress个人博客搭建(三):WordPress网站优化
  • RabbitMq学习(第一天)
  • 5.7 react 路由
  • Go语言八股之并发详解
  • 管家婆实用贴-如何在Excel中清除空格
  • Go语言——error、panic
  • 解决0x0000011b共享打印机无法连接!
  • 泛型设计模式实践
  • 初始图形学(7)
  • 2025-05-07-FFmpeg视频裁剪(尺寸调整,画面比例不变)
  • 系统思考:教育焦虑恶性循环分析
  • C语言初阶:数组
  • DeepSeek全域智能革命:从量子纠缠到星际文明的认知跃迁引言:认知边界的坍缩与重构
  • 解决leetcode第3537题填充特殊网格
  • CSS详细学习笔记
  • eclipse常用快捷键
  • Jmeter进行http接口测试
  • 使用VSCode在Windows 11上编译运行项目
  • 005 权限的理解