计算机视觉全系列实战教程 (十五):使用opencv对视频进行基本处理

发布于:2024-06-30 ⋅ 阅读:(17) ⋅ 点赞:(0)

1、基本概述

(1)opencv中视频处理的两个基础类

初学者使用opencv对视频进行处理时,应该首先关注两个类:VideoCapture类和VideoWriter类

  • VideoCapture类:用于视频的读操作
  • VideoWriter类:用于视频的写操作

(2)视频的属性:获取属性和设置属性

  • 视频文件的当前播放位置:以毫秒为单位 -----------------------属性id:propId = 0
  • 帧索引:视频序列中帧的索引(以0为起始索引)-------------属性id:propId = 1
  • 帧宽度/高度:像素为单位--------------------------------------------属性id:propId = 3 / 4
  • 帧率:每一秒的所放映的帧数 --------------------------------------属性id:propId = 5
  • 帧数:视频文件的帧数(总数)------------------------------------属性id:propId = 7
  • 图像的亮度:仅适用于相机------------------------------------------属性id:propId = 10
  • 图像的对比度:仅适用于相机---------------------------------------属性id:propId = 11
  • 图像的饱和度:仅适用于相机---------------------------------------属性id:propId = 12
  • 图像的色调:仅适用于相机------------------------------------------属性id:propId = 13
  • 图像的增益:仅适用于相机------------------------------------------属性id:propId = 14
  • 图像的曝光:仅适用于相机------------------------------------------属性id:propId = 15

A.获取视频的属性:

double dRes = vidObj.get(propId);

B.设置视频的属性:

int propId = 4;
double dValue =100;
vidObj.set(propId, dValue);

2、VideoCapture的介绍

(1)Why( VideoCapture类的作用)

获取视频文件或摄像头视频

(2)How( 如何使用VideoCapture)

A.播放视频文件函数

视频播放函数如下(可直接使用):

/*@author @还下着雨ZG
* @brief 播放指定的视频文件
* @param[in] strVideo, 视频文件所在路径
* @return int, 正表示播放成功,负数表示播放视频文件失败
*/
int VideoPlay(const std::string& strVideo)
{
    //创建VideoCapture对象
    cv::VideoCapture capture;
    //打开视频文件
    capture.open(strVideo);
    //判断是否打开成功
    if (!capture.isOpened())
    {
        std::cerr << "Failed to open video!" << std::endl;
        return -1;
    } 
    //获取视频的帧率FPS
    double rate = capture.get(cv::CAP_PROP_FPS);
    //播放视频
    cv::Mat frame;
    while (1)
    {
        capture >> frame;
        if (frame.empty())
        {
        	std::cout<<"播放完毕!"<<std::endl;
            break;
        }
        cv::imshow("Playing video...", frame);
        cv::waitKey(rate);
    }
}

B.播放视频文件并实现暂停和继续

视频播放和暂停函数如下(可直接使用):

/*@author @还下着雨ZG
* @brief 播放指定的视频文件并实现了暂停和继续
* @param[in] strVideo, 视频文件所在路径
* @return int, 正表示播放成功,负数表示播放视频文件失败
*/
int VideoPlayAndStop(const std::string& strVideo)
{
	//读取视频文件
    cv::VideoCapture capture(strVideo, cv::CAP_ANY);
    if (!capture.isOpened())
    {
        std::cerr << "Failed to open video file!" << std::endl;
        return -1;
    }
    //显示每一帧(视频自带帧率)
    cv::Mat imFrame;
    double dRate = capture.get(cv::CAP_PROP_FPS);
    int iDelay = 1000 / dRate;
    bool bStop = false;
    while (!bStop)
 	{
	     capture >> imFrame;
	     if (imFrame.empty()) 
	     {
	         bStop = true;
	         return 0;
	     }
	     else
	     {
	         imshow("MyFrame", imFrame);
	     }
	     int iKeyInput = cv::waitKey(iDelay);
	     if (char(iKeyInput) == 27 )
	     {
	         bStop = true;
	     }
	     if (iKeyInput >= 0)
	     {
	         cv::waitKey(0);
	     }
 	}
	capture.release();
	return 1;
}

3、VideoWriter类的介绍

(1)Why(VideoWriter类的作用)

保存修改后的视频文件、保存摄像头获取的视频序列、对待保存的视频格式进行设置等

(2)How(如何使用VideoWriter保存视频)

视频保存,该函数一般是用于对视频文件编辑之后的视频进行保存,或保存摄像头获取的视频序列(可根据实际需求做少量更改后使用):

int VideoSave(const std::string& strVideoSrc, const std::string& strVideoDst)
{
	//获取视频
    cv::VideoCapture capture;
    capture.open(strVideoSrc, cv::CAP_ANY);
    if (!capture.isOpened())
    {
        std::cerr << "Failed to open video file!" << std::endl;
        return -1;
    }
    //创建视频录制对象
    cv::VideoWriter writer;
    int iFourcc = writer.fourcc('M','J','P','G'); //视频编码格式
    double dFps = 25.0;
    cv::Mat imFrame;
    capture >> imFrame;
    if(imFrame.empty()) return -2;
    cv::Size SzFrame = imFrame.size();
    bool bIsColor = true; //彩色视频(false表示灰色视频)
    writer.open(strVideoDst,iFourcc, dFps, SzFrame, bIsColor);
    writer.write(imFrame);//将第一帧写入到writer对象中
    int iRate = 1000/capture.get(cv::CAP_PROP_FPS); //获取原始视频的帧率
    //遍历每一帧图像
    while(1)
    {
    	if(!capture.read(imFrame)) break;
    	writer.write(imFrame);
    	cv::imshow("Frame", imFrame);
    	if(cv::waitKey(iRate)>=0) break;
	}
	writer.release();
	capture.release();
	return 1;
}

注意:如果是需要保存摄像头的视频序列,应将该函数的第一个参数转换为摄像头的索引(0,1, …),函数内部做一定的修改即可

4、总结

  • VideoCapture类的基本介绍:该类的作用、视频属性、对视频每一帧进行处理、视频播放和暂停等
  • VideoWriter类的基本介绍:该类的作用、保存处理后的视频序列、保存相机获取的视频序列等