OpenCV入门(7):视频的读取与输出
一、视频的读取
(1)打开视频
cv::VideoCapture
类是读取视频的,cv::VideoCapture
既支持视频文件的读取,也支持从视频捕捉文件中读取视频,比如摄像头。cv::VideoCapture
类创建对象的方式如下三种:
cv::VideoCapture capture(const string& filename,);
// 第一种:从输入的文件名对应文件中读取
cv::VideoCapture capture(int device);
// 第二种:从视频捕捉设备ID中读取
cv::VideoCapture capture();
// 第三种:调用无参构造函数创建对象
-
第一种方法是从文件(AVI 和 MP4 都可以)中逐帧读取视频。对象创建后,OpenCV 将会打开文件并准备读取它。如果打开成功,将可以开始读取视频的帧,通过
cv::VideoCapture
类的成员函数isOpened()
返回True
的结果可以判断打开读取对象成功 -
第二种是从视频捕捉设备中读取视频,一般电脑配套的摄像头 ID 号是 0,外接的 USB 摄像头 ID 号为 1
-
第三种方式创建一个捕获对象,而不提供任何关于打开的信息。对象创建后通过成员函数
open()
来设定打开的信息。open()
操作也有以下两种方式cv::VideoCapture cap; cap.open("./test.mp4"); // 第一种路径方式打开视频
(2)获取视频属性
获取视频某些属性:
retval = cap.get(propId)
propId
:从 0 到 18 的数字,每个数字表示视频的属性
索引 | flags | 意义 |
---|---|---|
0 | cv2::CAP_ PROP_POS_MSEC | |
1 | cv2::CAP_PROP_POS_FRAMES | 从0开始索引帧,帧位置 |
2 | cv2::CAP_PROP_POS_AVI_RATIO | 视频文件的相对位置(0表示开始,1表示结束) |
3 | cv2::CAP_PROP_FRAME_WIDTH | 视频流的帧宽度 |
4 | cv2::CAP_PROP_FRAME_HEIGHT | 视频流的帧高度 |
5 | cv2::CAP_PROP_FPS | 帧率 |
6 | cv2::CAP_PROP_FOURCC | 编解码器四字符代码 |
7 | cv2::CAP_PROP_FRAME_COUNT | 视频文件的帧 |
(3)读取视频帧
打开之后需要将视频帧(其实就是把视频中的图像取出来)读取到 cv::Mat
矩阵中,共有两种方式,一种是 read
操作,一种是 >>
操作。示例如下:
cv::Mat frame;
cap.read(frame); // 读取方式一
cap>>frame; // 读取方式二
(4)读取视频示例
#include <QApplication>
#include <QDebug>
// 添加相关头文件和包
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 打开视频文件
VideoCapture capture("./test.mp4");
// 检查视频是否成功打开
if(!capture.isOpened())
{
qDebug() <<"Open video Failed!";
return -1;
}
// 获取视频的帧率、宽度和高度
double fps = capture.get(CAP_PROP_FPS);
int width = capture.get(CAP_PROP_FRAME_WIDTH);
int height = capture.get(CAP_PROP_FRAME_HEIGHT);
qDebug() << "fps:" << fps << "width:" << width << "height:" << height;
// 创建输出视频文件
VideoWriter writer("output.mp4", VideoWriter::fourcc('M', 'J', 'P', 'G'), fps, Size(width, height));
// 检查视频文件是否成功创建
if (!writer.isOpened())
{
qDebug() << "Create video Failed!";
return -1;
}
// 读取每一帧显示
Mat frame;
int num = capture.get(cv::CAP_PROP_FRAME_COUNT); // 获取视频帧数目
for(int i=0;i<num-1;++i)
{
// 将视频帧读取到cv::Mat矩阵
capture.read(frame);
// 显示每一帧图像
imshow("test",frame);
// 等待30ms后,按下q键即可退出播放
if(waitKey(30) == 'q')
break;
}
// 释放资源
destroyWindow("test"); // 销毁窗口
capture.release(); // 释放对象
return a.exec();
}
效果图如下所示:
二、视频的输出
(1)写入视频
cv::VideoWriter
类用于写入视频。该类较之 cv::VideoCapture
类要复杂一些。cv::VideoWrite
类的对象有两种创建方式。第一种是使用构建函数,第二种是使用 open()
函数,具体示例如下:
第一种方式:
cv::VideoWriter out(
const string& filename, // 输出文件名
int fourcc, // 编码形式,使用CV_FOURCC()宏
double fps, // 输出视频帧率
cv::Size frame_size, // 单帧图像大小
bool is_color=true // 如果是false则可传入灰度图像,true是彩色的
)
第二种方式:
cv::VideoWriter out;
out.open(
"my_video.mpg", // 输出文件名
CV_FOURCC('D','I','V','X'), // MPEG-4编码
30.0, // 输出视频帧率
cv::Size(640,480), // 单帧图像分辨率为640像素*480像素
true // 只可传入彩色图像,false为灰度图像
)
(2)编码格式
最需要注意的是 FOURCC 编码形式,操作时通常用以下 4 个字符连接起来形成一个 FOURCC 编码,形式为 cv::VideoWriter::fourcc(char c1,char c2,char c3,char c4)
。常用格式有以下几种:
代码 | 含义 |
---|---|
VideoWriter::fourcc('M', 'P', '4', 'V') |
MPEG-4编码,输出文件拓展名mp4 |
VideoWriter::fourcc( 'X' , '2' , '6' , '4' ) |
MPEG-4编码,输出文件拓展名mp4 |
VideoWriter::fourcc('P','I','M','1') |
MPEG-1编码,输出文件拓展名avi |
VideoWriter::fourcc('X','V','I','D') |
MPEG-4编码,输出文件拓展名avi |
VideoWriter::fourcc('I','4','2','0') |
YUV编码,输出文件拓展名avi |
VideoWriter::fourcc('T','H','E','O') |
ogg vorbis编码,输出文件拓展名ogv |
VideoWriter::fourcc('F',L','V','1') |
flash video编码,输出文件拓展名flv |
(3)写入视频帧
像创建的 cv::VideoWrite
对象写入图像也有两种形式,即 write()
操作以及 <<
操作。
cv::VideoWriter::write(const Mat& image); // 写入方式一
out<<frame; // 写入方式二
(4)输出视频示例
#include <QApplication>
#include <QDebug>
// 添加相关头文件和包
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 打开视频文件
Mat frame;
std::string filename="./test.mp4";
VideoCapture cap(filename);
// 配置输出视频属性
VideoWriter out;
out.open("./testOut.mp4",cv::VideoWriter::fourcc('D','I','V','X'), // MPEG-4编码
cap.get(CAP_PROP_FPS),Size(cap.get(CAP_PROP_FRAME_WIDTH), // 输出视频帧率和分辨率
cap.get(CAP_PROP_FRAME_HEIGHT)),true); // 只可传入彩色图像
if(!cap.isOpened())
{
qDebug() << "Video load failed!";
return -1;
}
// 循环遍历将视频帧写入到输出视频文件
while(1)
{
cap>>frame;
if(frame.empty())
{
qDebug() << "Video process finished!";
return 0;
}
imshow("video",frame);
if(waitKey(10) == 'q')
break;
out<<frame;
}
// 释放资源
cap.release();
/*
在使用OpenCV进行视频处理时,通常会使用cv2.VideoCapture()函数来读取视频文件或者从摄像头获取视频流。当不再需要使用视频流时,
可以通过调用cap.release()来释放资源,关闭视频流。
类似地,当使用cv2.VideoWriter()函数将处理后的视频保存为文件时,可以通过调用out.release()来释放资源,关闭视频写入器。
这些函数的调用可以确保在程序结束时,释放所有使用的资源,避免资源泄露和内存溢出等问题。
*/
return a.exec();
}
生成的输出视频如下:
参考:
OpenCv(C++)学习笔记二——视频的读取与输出_videocapture函数如何读取视频-CSDN博客