OpenCV 无法像 FFmepg 库一样,可以播放视频的声音,并且它显示视频的方式也是从视频文件提取图像帧显示到窗口上。来看例子:
播放视频文件
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, const char * argv[]) {
// 打开视频文件.
VideoCapture cap("/Users/xxx/Pictures/chengdu.mp4");
if (!cap.isOpened()) {
cout << "视频打开失败" << endl;
cin.get();
return -1;
}
// VideoCapture 属性设置
//cap.set(CAP_PROP_POS_MSEC, 5000);
// 获取视频帧率
double fps = cap.get(CAP_PROP_FPS);
cout << "帧率: " << fps << endl;
String window_name = "Video Frame";
namedWindow(window_name);
while (true) {
// 视频帧图像
Mat frame;
bool ret = cap.read(frame);
if (!ret)
{
cout << "视频播放完成." << endl;
break;
}
// 显示视频帧图像.
imshow(window_name, frame);
if (waitKey(10) == 27)
{
cout << "按下 ESC 键停止播放." << endl;
break;
}
}
return 0;
}
你只需要将上面的视频路径更改为你的播放路径,将会看到如下的效果。
代码解释
- 头文件导入
使用 OpenCV 时必须导入,命名空间是为了更方便的使用 OpenCV 提供的类
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
- VideoCapture cap("/Users/xxx/Pictures/chengdu.mp4");
初始化 VideoCapture, 读取指定路径的视频文件。在它的析构函数中会释放打开视频文件的内存,无需显示释放内存。
- cap.isOpened()
if (!cap.isOpened()) {
cout << "视频打开失败" << endl;
cin.get();
return -1;
}
当 VideoCapture 创建成功后,isOpened() 返回 true, 否则返回 false。
- cap.set(CAP_PROP_POS_MSEC, 5000)
VideoCapture 属性设置,设置成功会返回 true, 否则返回 false, 它有两个参数:
propID: VideoCapture 属性,有两个常量使用
- CAP_PROP_POS_MSEC: 设置视频播放位置,单位为毫秒,例如: 100ms
- CAP_PROP_POS_FRAMES: 视频播放帧相对于起始帧0, 例如: 1、2、3,...
- double fps = cap.get(CAP_PROP_FPS);
获取当前视频的帧率,如果不支持属性将会返回 0
propld: VideoCapture 属性,有如下常用的几个属性
- CAP_PROP_POS_MSEC: 获取当前播放了多少毫秒
- CAP_PROP_POS_FRAMES: 获取当前播放的视频帧,相对起始帧 0
- CAP_PROP_FRAME_WIDTH: 获取视频帧的宽
- CAP_PROP_FRAME_HEIGHT: 获取视频帧的高
- CAP_PROP_FPS: 获取视频帧率
- CAP_PROP_FOURCC: 编码器字符编码
- CAP_PROP_FRAME_COUNT: 视频总帧数
- namedWindow(window_name);
void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE);
函数创建一个窗口,用作图像和图像的占位符,创建的窗口由其名称引用。
1. winname: 窗口名称,标示一个窗口
2. flags: 决定窗口的大小,在上面的例子中采用默认的方式,即为图像的尺寸。保存在枚举常量 cv::WindowFlags 中
* WINDOW_AUTOSIZE: 用户不能调整窗口大小
* WINDOW_NORMAL: 用户可以调整窗口大小
...
- bool ret = cap.read(frame);
读取视频帧保存到 frame 中, 读取完毕返回 false
- imshow(window_name, frame);
void imshow(const String& winname, InputArray mat);
在指定窗口中显示图像,如果窗口是用 WINDOW_AUTOSIZE 标志创建的,图像以原始大小显示,否则图像会根据窗口大小进行缩放显示。如果未通过 namedWindow() 函数创建窗口,imshow 函数会默认创建 WINDOW_AUTOSIZE 标志的窗口。
此函数调用之后应加上 waitKey(int) 函数调用,以便为指定的连续时间(以毫秒为单位)提供足够的时间在窗口中绘制和显示图像。如果不调用 waitKey(int) 函数, 图像不会显示在窗口中。
1. winname: 窗口名称,通过 namedWindow() 函数创建
2. mat: 图像的 Mat 对象
- waitKey(10) == 27
等待 10 毫秒,如果没有 ESC 按下,则继续播放下一帧,知道播放完。
从相机获取图像播放
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, const char * argv[]) {
// 打开后置摄像头,捕捉视频帧.
VideoCapture cap(0);
if (!cap.isOpened())
{
cout << "打开相机失败." << endl;
cin.get();
return -1;
}
double width = cap.get(CAP_PROP_FRAME_WIDTH);
double height = cap.get(CAP_PROP_FRAME_HEIGHT);
cout << "视频帧分辨率: " << width << " x " << height << endl;
while (true) {
Mat frame;
bool ret = cap.read(frame);
if (!ret)
{
cout << "相机断开." << endl;
cin.get();
break;
}
imshow("My Camera Feed", frame);
if (waitKey(10) == 27)
{
cout << "按下 ESC 停止播放视频." << endl;
break;
}
}
return 0;
}
代码解释:
- VideoCapture cap(0);
打开后置摄像头,传递的参数为 0 将打开默认的摄像头( 默认后置摄像头),可根据计算机设备的相机数来调整这个索引。
- double width = cap.get(CAP_PROP_FRAME_WIDTH); double height = cap.get(CAP_PROP_FRAME_HEIGHT);
获取相机捕捉图像的分辨率,即宽 * 高