0%

OpenCV-C++学习笔记其三:用opencv打开视频文件或者摄像头

先前我们学会了如何使用opencv打开一张图片,下一步自然是如何打开一个视频,然后再到如何借助摄像头获取实时的视频(以后做视频小车用的上)。

原理也很简单,我们知道视频是由很多图片逐帧播放形成的,打开使能其实就是在一个while循环里按照视频帧率播放图片,如以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include"opencv2/opencv.hpp"
#include "iostream"

using namespace cv;
using namespace std;

int main(){
VideoCapture video;
video.open("C://Users//12743//Desktop//学习笔记//1.mp4");

if(!video.isOpened()){
cout << "加载视频失败" << endl;
}

double fps = video.get(CAP_PROP_FPS); // 通过get函数获取帧率
double width = video.get(CAP_PROP_FRAME_WIDTH); // 获取视频宽度

cout << "帧率:" << video.get(CAP_PROP_FPS) << endl; // 经过实验,MOV格式的视频获取不了帧率等信息
cout << "宽度:" << video.get(CAP_PROP_FRAME_WIDTH) << endl;

while(1){
Mat frame; //定义一帧画面
video >> frame; // 从视频中获取一帧

if(frame.empty()){
break; // 如果没画面了,跳出循环
}

namedWindow("video", WINDOW_NORMAL); //省略创建窗口也可以,但为了方遍调整窗口大小,得用WINDOW_NORMAL参数
imshow("video" , frame);
uchar key = waitKey(1000/fps); // 1000/帧率就是每帧画面间隔时间

if(key == 'q'){
break; // 如果按键值为q,退出循环
}
}

}

参考代码中的注释能够大致上了解整个流程,这里着重介绍的就是Videocapture类中的get()函数,通过get()可以获取视频的各种信息:

参数 作用
CAP_PROP_POS_MSEC 视频文件的当前位置(播放)以毫秒为单位
CAP_PROP_POS_FRAMES 基于以0开始的被捕获或解码的帧索引
CAP_PROP_POS_AVI_RATIO 视频文件的相对位置(播放):0=电影开始,1=影片的结尾
CAP_PROP_FRAME_WIDTH 在视频流的帧的宽度
CAP_PROP_FRAME_HEIGHT 在视频流的帧的高度
CAP_PROP_FPS 帧速率
CAP_PROP_FRAME_COUNT 视频文件中的帧数
CAP_PROP_FORMAT 返回对象的格式

如果要打开摄像头,需要将open()中的参数改成相机的索引值,相机的索引值可能是0 或 1,也有可能是其他数字

1
video.open(0);

摄像头录制

有时候我们需要使用摄像头录制,这会儿需要借助VideoWriter(),参考如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;

int main()
{
Mat img;
VideoCapture video(1);

if (!video.isOpened()) {
cout << "摄像头打开失败" << endl;
return -1;
}

video >> img; //获取图像
//检测是否成功获取图像
if (img.empty())
{
cout << "获取图像失败" << endl;
return -1;
}

bool isColor = (img.type() == CV_8UC3); //判断视频是否为彩色

VideoWriter w1; // 创建保存视频的对象
int encode_type = VideoWriter::fourcc('M', 'J', 'P', 'G'); //选择编码格式

double fps = 25.0; //设置视频帧率
string filename = "test_save.avi";
w1.open(filename, encode_type, fps, img.size(), isColor); //创建保存视频文件的视频流 img.size()为保存的视频图像的尺寸

if (!w1.isOpened()) { //判断视频流是否创建成功
cout << "视频打开失败" << endl;
}


while (1) {
Mat frame;
video >> frame;
if (frame.empty()) { //判断读取图像是否成功
break;
}

w1.write(frame); //或者写为w1 << img;


//或者设置为0时候可以随意通过鼠标拖拽控制展示窗口的大小
namedWindow("video_test", WINDOW_NORMAL);
imshow("video_test", frame);

char c = waitKey(50);
if (c == 27) //按ESC案件退出视频保存
{
break;
}

}

video.release(); //这两句是在退出程序后关闭视频流,不写的话系统也会自动关闭
w1.release();
return 0;
}

这里涉及的视频编码格式有点麻烦:

20230829181456

更具体可参考以下这个文章:https://blog.csdn.net/weixin_37637612/article/details/119396516