OpenCV学习笔记--视频读写

本文介绍如何使用OpenCV库实现视频的读取与写入功能。通过示例代码展示了如何从视频文件读取帧并将其显示和写入新的视频文件。此外还介绍了VideoCapture和VideoWriter类的基本用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

视频读写程序

废话少说,先上一段代码,运行看看效果。

#include <stdio.h>
#include <opencv2/opencv.hpp>
using namespace cv;

int main(int argc, char *argv[])
{
//    VideoCapture vidCap(0); // 打开默认摄像头
    const char file_in[] = "Wildlife.wmv";
    VideoCapture vidCap(file_in); // 打开读取视频文件
    if (!vidCap.isOpened()){
//        printf("Unabled to open camera!\n");
        printf("Unabled to open %s!\n", file_in);
        return -1;
    }

    int w = vidCap.get(CAP_PROP_FRAME_WIDTH);
    int h = vidCap.get(CAP_PROP_FRAME_HEIGHT);
    const char file_out[] = "1.avi";
    double fps = vidCap.get(CAP_PROP_FPS);
//    double fps = 25;
    VideoWriter vidRec(file_out, CV_FOURCC('M','P','E','G'), fps, Size(w,h));// 打开写入视频文件
    if (!vidRec.isOpened()){
        printf("video file not opened!\n");
        return -2;
    }

    const char wnd1[] = "Capturing...";
    namedWindow(wnd1);

    Mat matCap;
    double lfFreq = getTickFrequency();
    int64 iBase = getTickCount();
    for (int iFrameCnt = 0; /*iFrameCnt < vidCap.get(CAP_PROP_FRAME_COUNT)*/; ++iFrameCnt){
        int iDelay = iFrameCnt*1000/fps - (getTickCount()-iBase)*1000/lfFreq;// 根据fps计算需要等待时间
        if (iDelay > 0){
            if (waitKey(iDelay) >= 0)// 这里通过waitKey进行延时等待,如果检测到有按键则退出
                break;
        }
        if (!vidCap.read(matCap))// 需要判断读取帧是否成功
            break;
        imshow(wnd1, matCap);
        vidRec.write(matCap);
    }

    destroyAllWindows();

    return 0;
}

我的台式电脑没有带摄像头,所以这里展示的是直接从本地视频文件读取帧然后显示、写成另一视频文件。运行效果图如下:
videoio

如果你的电脑带摄像头,可以使用VideoCapture vidCap(0); // 打开默认摄像头
然后看看效果,这就是一个简单的相机显示和录制程序了。

API讲解

OpenCV中提供了VideoCapture 与VideoWriter 两个类负责视频的读写,位于videoio模块。

VideoCapture

这个类既可以用来打开摄像头,也可以读取视频文件,通过isOpened判断是否打开成功,get方法根据提供的属性宏来获取到对应的属性值,例如上述程序中就是用了:
int w = vidCap.get(CAP_PROP_FRAME_WIDTH);
int h = vidCap.get(CAP_PROP_FRAME_HEIGHT);
获取视频帧宽高信息,此外fps是frame per second每秒的帧数。视频文件头信息中已经包含了这些信息,如果是打开摄像头捕捉帧然后写入视频文件,就需要自己设定一个fps,常见的是25和30。通过read去读取下一帧,成功返回true,失败返回false,例如读取到文件结束后就会返回false。

VideoWriter

这个类用来写视频文件,视频文件可以看成是包含了头信息和视频帧数据的文件。所以需要设定保存的格式、fps、宽高等信息。CV_FOURCC(‘M’,’P’,’E’,’G’)代表一种帧数据压缩方式,更多的可以参考VideoWriter 构造函数头文件中给出的说明。同样需要调用isOpened判断是否支持写这类文件。通过write去写入帧数据,示例中写入了1.avi文件,你可以使用播放器打开这个文件看看录制效果。

getTickCount与getTickFrequency

getTickFrequency用来获取CPU的频率,我电脑上调试返回的是3215439,即3215439/1024/1024=3.07GHZ。getTickCount获取开机到现在的时钟计数,通过如下的代码可以判断一个操作用了多少时间(单位s):
double t = (double)getTickCount();
// do something …
t = ((double)getTickCount() - t)/getTickFrequency();

示例中记录下一个基准时间点int64 iBase = getTickCount();然后通过帧数iFrameCnt 计算出当前需要等待的时间,例如第一帧是00:00:00.000从摄像头捕捉的,按照fps=25,即每隔40ms捕捉一帧,那么第二帧应该是00:00:00.040捕捉。如果当前是00:00:00.005,那么就需要延时等待35ms再捕捉。这样你从摄像头捕捉写下来的视频文件每秒的帧数就是25了。

总结

上节中我们展示了图像文件的读写、这节我们展示了视频文件的读写,这都是为了方便我们去获取到图像数据,接下来的章节就是图像处理的正菜了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ithewei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值