读取视频序列 - sumpig/OpenCV GitHub Wiki


cv::VideoCapture


  1. 只需指定视频文件名即可打开视频
cv::VideoCapture capture("bike.avi");

  1. 如果对象已经创建,可以使用它的 open 方法
capture.open("bike.avi");

  1. 成功打开后,可以使用 isOpened 方法验证
capture.isOpened();

  1. 可以使用 get 方法并采用正确的标志来查询视频文件的有关信息,CV_CAP_PROP_FPS 可以获得帧速率,该方法总会返回一个 double 类型的数值
double r = capture.get(CV_CAP_PROP_FPS);

  1. 获取视频文件总帧数 CV_CAP_PROP_FRAME_COUNT
long t = static_cast<long>(capture.get(CV_CAP_PROP_FRAME_COUNT));

  1. set 方法,可以用 CV_CAP_PROP_POS_FRAMES 标志让视频跳到指定的帧
// 跳到第 100 帧
double position = 100.0;
capture.set(CV_CAP_PROP_POS_FRAMES, position);

  1. CV_CAP_PROP_POS_MSEC 以毫秒为单位指定位置
  2. CV_CAP_PROP_POS_AVI_RATIO 指定视频内部的想定位置 (0.0 - 1.0)

  1. read 方法可以按顺序访问每一帧,也可以调用重载运算符 >>
cv::Mat frame;
capture.read(frame);
capture >> frame;

  1. grab 方法从视频文件或捕获设备中抓取下一个帧,假如调用成功返回true
capture.grab();

  1. retrieve 方法解码并且返回刚刚抓取的视频帧,假如没有视频帧被捕获(相机没有连接或者视频文件中没有更多的帧)将返回false
capture.retrieve(frame);

  1. release 方法关闭视频文件,不是必须的,因为在 cv::VideoCapture 的析构函数中也会调用 release

  1. 读取摄像机,只需在 open 方法中指定一个 ID 取代原来的文件名即可,ID 为 0 表示打开默认摄像机
  2. 也可以装载 Web 上的视频,需要提供一个正确的网址
cv::VideoCapture capture("http://www.laganiere.name/bike.avi");

下面这个基本函数显示了视频序列中的帧:

int main() {

    cv::VideoCapture capture("bike.avi");
    if (!capture.isOpened()) return 1;

    double rate = capture.get(CV_CAP_PROP_FPS);
    int delay = 1000/rate; // 根据帧速率计算帧之间的等待时间,单位为 ms

    cv::Mat frame;
    cv::namedWindow("Frame");

    bool stop(false);
    while(!stop) {

        if (!capture.read(frame)) break;

        cv::imshow("Frame", frame);

        if (cv::waitKey(delay) >= 0) // 通过按键可以停止,cv::waitKey() 默认返回-1,按键则返回大于0的相应的 ASCII 码
            stop = true;
    }

    capture.release();
    return 0;
}
  
⚠️ **GitHub.com Fallback** ⚠️