欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > 实战OpenCV之视频处理

实战OpenCV之视频处理

2024/10/25 22:26:20 来源:https://blog.csdn.net/hope_wisdom/article/details/142801196  浏览:    关键词:实战OpenCV之视频处理

基础入门

        视频是由一系列连续的图像帧组成的,这些帧按照一定的速率连续播放,从而形成动态画面。与视频相关的主要参数有:分辨率、帧率、码率、编解码器、帧类型、文件格式等,下面分别进行介绍。

        1、帧率。表示每秒显示的图像帧数,该参数决定视频流畅度,更高的帧率意味着更平滑的动作。常见的帧率有:24fps(电影)、30fps(电视标准)、60fps(流畅的游戏体验)等。

        2、分辨率。表示视频每一帧图像的宽度和高度,通常以像素为单位,该参数决定视频的清晰度和细节程度。常见的分辨率有:720p(1280 x 720)、1080p(1920 x 1080)、4K(3840 x 2160)等。

        3、码率。也叫比特率,指每秒传送的数据量,通常以kbps (千比特/秒) 或 Mbps (兆比特/秒) 表示。该参数影响视频的质量和文件大小,高比特率意味着更好的视频质量,但文件也更大。码率可以是恒定的(CBR, Constant Bitrate),也可以是可变的(VBR, Variable Bitrate)。

        4、编解码器。即Codec,是编码器和解码器的组合词,用于压缩和解压视频数据。该参数影响视频质量和文件大小,常见的编解码算法有:H.264/AVC、H.265/HEVC、MJPEG、VP9等。

        5、帧类型。在H.264、H.265编码算法中,使用了不同的帧类型来提高压缩效率,主要包括I帧、P帧和B帧。

        (1)I帧:也称为帧内编码帧,是一个完整的图像帧,它包含了该帧所有的图像信息,类似于一张静态图片。I帧不需要参考其他任何帧来解码,因此可以在视频的任何点开始播放。但是,由于包含完整信息,所以占用的空间较大。通常用于视频的开头或场景变化较大的地方,因为这些位置不适合使用预测编码。

        (2)P帧:也称为前向预测帧,只包含相对于前一帧变化的部分信息。P帧会参考前一个I帧或P帧来进行解码,通过对前一帧的预测,P帧只需要记录变化的内容,这样就能大大减少所需的存储空间。P帧在视频中占大多数,用于高效地表示场景中变化不大的部分。

        (3)B帧:也称为双向预测帧,会同时向前和向后参考相邻的I帧或P帧。B帧进一步提高了压缩效率,但增加了解码复杂度。

        6、文件格式。用于存储视频数据的标准或容器,不同的视频文件格式有着不同的特性和用途。常见的视频文件格式有:MP4、AVI、MOV、FLV、MPEG、WMV等。

API接口

        cv::VideoCapture是OpenCV中用于处理视频输入的核心类之一,它可以用来从摄像头设备或视频文件中捕获视频帧。cv::VideoCapture类构造函数的原型如下。

VideoCapture();
VideoCapture(int device_index);
VideoCapture(const String& filename);

        各个参数的含义如下。

        device_index:整数,表示设备索引,通常0表示第一个摄像头。

        filename:视频文件的路径。

        cv::VideoCapture类提供了很多实用性的方法来控制视频流,其导出的主要方法如下。

        open用于打开摄像头或者视频文件,成功打开设备或文件返回true,失败返回false。其参数的含义与上面完全相同,故这里不再赘述。

bool open(int device_index);
bool open(const String& filename);

        read用于读取一帧视频数据,成功读取帧返回true,失败返回false。参数image为一个OutputArray,通常是一个cv::Mat对象,用于接收读取到的帧。

bool read(OutputArray image);

        grab会提前获取下一帧的数据,但并不立即填充到image中。如果成功获取下一帧,grab方法返回true。如果没有更多的帧可获取,或者发生错误,grab方法返回false。

bool grab();

        retrieve将先前通过grab方法获取的帧数据填充到image中。如果成功填充了一帧,retrieve方法返回true,并且image将包含这一帧的数据。如果没有通过grab方法获取帧,或者发生错误,retrieve方法返回false。grab和retrieve方法通常一起使用,先通过grab获取下一帧,再通过retrieve获取该帧的数据。这种分离的设计使得处理视频流时更为灵活,可以在获取下一帧之前处理当前帧,或者处理多路视频流。

bool retrieve(OutputArray image, int stream = 0);

        各个参数的含义如下。

        image:一个OutputArray,通常是一个cv::Mat对象,用于接收读取的帧。

        stream:整数,指定要从中检索帧的流。对于单流设备,默认为0。

        isOpened用于判断视频设备或文件是否打开,如果已成功打开,则返回true,否则返回false。

bool isOpened() const;

        release用于释放VideoCapture对象所使用的资源。

void release();

实战解析

        在下面的实战代码中,我们首先定义了一个预处理宏VIDEO_PROCESSING_MODE,用于控制程序是打开一个视频文件还是打开默认摄像头。在主函数中,根据该宏的取值,程序尝试打开视频文件,或启动默认摄像头。如果无法打开视频文件或摄像头,程序会输出错误信息并终止。

        接下里,我们创建了一个名为"Video Processing"的窗口,并设置了窗口的大小。程序随后进入一个无限循环,在每次循环中读取一帧视频,并显示该帧。如果无法读取更多帧,则跳出循环。另外,程序还监听键盘输入,如果用户按下了'q'键,则退出循环。最后,我们释放了VideoCapture对象使用的资源,并销毁所有窗口。

#include <opencv2/opencv.hpp>
using namespace cv;#include <iostream>
using namespace std;#define VIDEO_PROCESSING_MODE           0int main()
{
#if VIDEO_PROCESSING_MODE == 0// 打开视频文件VideoCapture cap("DigitalHuman.mp4");if (!cap.isOpened()){cout << "Can not open or find the video file" << endl;return -1;}
#else// 打开摄像头VideoCapture cap(0);if (!cap.isOpened()){cout << "Can not open or find the camera" << endl;return -1;}
#endifnamedWindow("Video Processing", WINDOW_NORMAL);resizeWindow("Video Processing", 640, 360);Mat frame;// 获取视频的帧率int nFPS = (int)cap.get(CAP_PROP_FPS);while (true){// 读取一帧if (!cap.read(frame)){// 如果无法读取更多帧,跳出循环break;}// 显示当前帧imshow("Video Processing", frame);// 按q键可以退出if (waitKey(1000 / nFPS) == 'q'){break;}}// 释放资源cap.release();destroyAllWindows();return 0;
}

        执行上面的代码,运行效果可参考下图。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com