返回顶部
首页 > 资讯 > 精选 >如何进行OpenCV2中的视频流读取与处理
  • 896
分享到

如何进行OpenCV2中的视频流读取与处理

2023-06-26 04:06:52 896人浏览 安东尼
摘要

这篇文章跟大家分析一下“如何进行OpenCV2中的视频流读取与处理”。内容详细易懂,对“如何进行OpenCV2中的视频流读取与处理”感兴趣的朋友可以跟着小编的思路慢慢深入来阅读一下,希望阅读后能够对大家有所帮助。下面跟着小编一起深入学习“如

这篇文章跟大家分析一下“如何进行OpenCV2中的视频流读取与处理”。内容详细易懂,对“如何进行OpenCV2中的视频流读取与处理”感兴趣的朋友可以跟着小编的思路慢慢深入来阅读一下,希望阅读后能够对大家有所帮助。下面跟着小编一起深入学习“如何进行OpenCV2中的视频流读取与处理”的知识吧。

前言

由于项目需要,计划实现九路视频拼接,因此必须熟悉OpenCV对视频序列的处理。视频信号处理是图像处理的一个延伸,所谓的视频序列是由按一定顺序进行排放的图像组成,即帧(Frame)。在这里,主要记录下如何使用Qt+OpenCV读取视频中的每一帧,之后,在这基础上将一些图像处理的算法运用到每一帧上(如使用Canny算子检测视频中的边缘)。

一. 读取视频序列

OpenCV提供了一个简便易用的框架以提取视频文件和USB摄像头中的图像帧,如果只是单单想读取某个视频,你只需要创建一个cv::VideoCapture实例,然后在循环中提取每一帧。新建一个Qt控制台项目,直接在main函数添加:

#include <QCoreApplication>#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/highgui/highgui.hpp>#include <QDebug>int main(int arGC, char *argv[]){    QCoreApplication a(argc, argv);    // 读取视频流    cv::VideoCapture capture("e:/BrokeGirls.mkv");    // 检测视频是否读取成功    if (!capture.isOpened())    {        qDebug() << "No Input Image";        return 1;    }    // 获取图像帧率    double rate= capture.get(CV_CAP_PROP_FPS);    bool stop(false);    cv::Mat frame; // 当前视频帧    cv::namedWindow("Extracted Frame");    // 每一帧之间的延迟    int delay= 1000/rate;    // 遍历每一帧    while (!stop)    {        // 尝试读取下一帧        if (!capture.read(frame))            break;        cv::imshow("Extracted Frame",frame);        // 引入延迟        if (cv::waiTKEy(delay)>=0)                stop= true;    }        return a.exec();}

(注意:要正确打开视频文件,计算机中必须安装有对应的解码器,否则cv::VideoCapture无法理解视频格式!)运行后,将出现一个窗口,播放选定的视频(需要在创建cv::VideoCapture对象时指定视频的文件名)。

如何进行OpenCV2中的视频流读取与处理

二. 处理视频帧

为了对视频的每一帧进行处理,这里创建自己的类VideoProcessor,其中封装了OpenCV的视频获取框架,该类允许我们指定每帧调用的处理函数。

首先,我们希望指定一个回调处理函数,每一帧中都将调用它。该函数接受一个cv::Mat对象,并输出处理后的cv::Mat对象,其函数签名如下:

void processFrame(cv::Mat& img, cv::Mat& out);

作为这样一个处理函数的例子,以下的Canny函数计算图像的边缘,使用时直接添加在mian文件中即可:

    // 对视频的每帧做Canny算子边缘检测void canny(cv::Mat& img, cv::Mat& out) {    // 先要把每帧图像转化为灰度图    cv::cvtColor(img,out,CV_BGR2GRAY);    // 调用Canny函数    cv::Canny(out,out,100,200);    // 对像素进行翻转    cv::threshold(out,out,128,255,cv::THRESH_BINARY_INV);}

现在我们需要创建一个VideoProcessor类,用来部署视频处理模块。而在此之前,需要先另外创建一个类,即VideoProcessor内部使用的帧处理类。这是因为在面向对象的上下文中,更适合使用帧处理类而不是一个帧处理函数,而使用类可以给程序员在涉及算法方面有更多的灵活度(书上介绍的)。将这个内部帧处理类命名为FrameProcessor,其定义如下:

#ifndef FRAMEPROCESSOR_H#define FRAMEPROCESSOR_H#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>class FrameProcessor{public:    virtual void process(cv:: Mat &input, cv:: Mat &output)= 0;};#endif // FRAMEPROCESSOR_H

现在可以开始定义VideoProcessor类了,以下为videoprocessor.h中的内容:

#ifndef VIDEOPROCESSOR_H#define VIDEOPROCESSOR_H#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/highgui/highgui.hpp>#include <QDebug>#include "frameprocessor.h"class VideoProcessor{  private:      // 创建视频捕获对象      cv::VideoCapture capture;      // 每帧调用的回调函数      void (*process)(cv::Mat&, cv::Mat&);      // FrameProcessor接口      FrameProcessor *frameProcessor;      // 确定是否调用回调函数的bool信号      bool callIt;      // 输入窗口的名称      std::string windowNameInput;      // 输出窗口的名称      std::string windowNameOutput;      // 延迟      int delay;      // 已处理的帧数      long fnumber;      // 在该帧停止      long frameToStop;      // 是否停止处理      bool stop;      // 当输入图像序列存储在不同文件中时,可使用以下设置      // 把图像文件名的数组作为输入      std::vector<std::string> images;      // 图像向量的迭加器      std::vector<std::string>::const_iterator itImg;      // 得到下一帧      // 可能来自:视频文件或摄像头      bool readNextFrame(cv::Mat &frame)      {          if (images.size()==0)              return capture.read(frame);          else {              if (itImg != images.end())              {                  frame= cv::imread(*itImg);                  itImg++;                  return frame.data != 0;              }          }      }public:      // 默认设置 digits(0), frameToStop(-1),      VideoProcessor() : callIt(false), delay(-1),          fnumber(0), stop(false),          process(0), frameProcessor(0) {}      // 创建输入窗口      void displayInput(std::string wt);      // 创建输出窗口      void displayOutput(std::string wn);      // 不再显示处理后的帧      void dontDisplay();      // 以下三个函数设置输入的图像向量      bool setInput(std::string filename);      // 若输入为摄像头,设置ID      bool setInput(int id);      // 若输入为一组图像序列时,应用该函数      bool setInput(const std::vector<std::string>& imgs);      // 设置帧之间的延迟      // 0意味着在每一帧都等待按键响应      // 负数意味着没有延迟      void setDelay(int d);      // 返回图像的帧率      double getFrameRate();      // 需要调用回调函数      void callProcess();      // 不需要调用回调函数      void dontCallProcess();      // 设置FrameProcessor实例      void setFrameProcessor(FrameProcessor* frameProcessorPtr);      // 设置回调函数      void setFrameProcessor(void (*frameProcessingCallback)(cv::Mat&, cv::Mat&));      // 停止运行      void stopIt();      // 判断是否已经停止      bool isStopped();      // 是否开始了捕获设备?      bool isOpened();      // 返回下一帧的帧数      long getFrameNumber();      // 该函数获取并处理视频帧      void run();};#endif // VIDEOPROCESSOR_H

然后,在videoprocessor.cpp中定义各个函数的功能:

#include "videoprocessor.h"// 创建输入窗口void VideoProcessor::displayInput(std::string wt){    windowNameInput= wt;    cv::namedWindow(windowNameInput);}// 创建输出窗口void VideoProcessor::displayOutput(std::string wn){    windowNameOutput= wn;    cv::namedWindow(windowNameOutput);}// 不再显示处理后的帧void VideoProcessor::dontDisplay(){    cv::destroyWindow(windowNameInput);    cv::destroyWindow(windowNameOutput);    windowNameInput.clear();    windowNameOutput.clear();}// 设置输入的图像向量bool VideoProcessor::setInput(std::string filename){  fnumber= 0;  // 释放之前打开过的视频资源  capture.release();  images.clear();  // 打开视频  return capture.open(filename);}// 若输入为摄像头,设置IDbool VideoProcessor::setInput(int id){  fnumber= 0;  // 释放之前打开过的视频资源  capture.release();  images.clear();  // 打开视频文件  return capture.open(id);}// 若输入为一组图像序列时,应用该函数bool VideoProcessor::setInput(const std::vector<std::string>& imgs){  fnumber= 0;  // 释放之前打开过的视频资源  capture.release();  // 输入将是该图像的向量  images= imgs;  itImg= images.begin();  return true;}// 设置帧之间的延迟// 0意味着在每一帧都等待按键响应// 负数意味着没有延迟void VideoProcessor::setDelay(int d){    delay= d;}// 返回图像的帧率double VideoProcessor::getFrameRate(){    if (images.size()!=0) return 0;    double r= capture.get(CV_CAP_PROP_FPS);    return r;}// 需要调用回调函数void VideoProcessor::callProcess(){    callIt= true;}// 不需要调用回调函数void VideoProcessor::dontCallProcess(){    callIt= false;}// 设置FrameProcessor实例void VideoProcessor::setFrameProcessor(FrameProcessor* frameProcessorPtr){    // 使回调函数无效化    process= 0;    // 重新设置FrameProcessor实例    frameProcessor= frameProcessorPtr;    callProcess();}// 设置回调函数void VideoProcessor::setFrameProcessor(void (*frameProcessingCallback)(cv::Mat&, cv::Mat&)){    // 使FrameProcessor实例无效化    frameProcessor= 0;    // 重新设置回调函数    process= frameProcessingCallback;    callProcess();}// 以下函数表示视频的读取状态// 停止运行void VideoProcessor::stopIt(){    stop= true;}// 判断是否已经停止bool VideoProcessor::isStopped(){    return stop;}// 是否开始了捕获设备?bool VideoProcessor::isOpened(){    return capture.isOpened() || !images.empty();}// 返回下一帧的帧数long VideoProcessor::getFrameNumber(){  if (images.size()==0)  {      // 得到捕获设备的信息      long f= static_cast<long>(capture.get(CV_CAP_PROP_POS_FRAMES));      return f;  }  else // 当输入来自一组图像序列时的情况  {      return static_cast<long>(itImg-images.begin());  }}// 该函数获取并处理视频帧void VideoProcessor::run(){    // 当前帧    cv::Mat frame;    // 输出帧    cv::Mat output;    // 打开失败时    if (!isOpened())    {        qDebug() << "Error!";        return;    }    stop= false;    while (!isStopped())    {        // 读取下一帧        if (!readNextFrame(frame))            break;        // 显示输出帧        if (windowNameInput.length()!=0)            cv::imshow(windowNameInput,frame);        // 调用处理函数        if (callIt)        {          // 处理当前帧          if (process)              process(frame, output);          else if (frameProcessor)              frameProcessor->process(frame,output);          // 增加帧数          fnumber++;        }        else        {          output= frame;        }        // 显示输出帧        if (windowNameOutput.length()!=0)            cv::imshow(windowNameOutput,output);        // 引入延迟        if (delay>=0 && cv::waitKey(delay)>=0)          stopIt();        // 检查是否需要停止运行        if (frameToStop>=0 && getFrameNumber()==frameToStop)            stopIt();    }}

定义好视频处理类,它将与一个回调函数相关联。使用该类,可以创建一个实例,指定输入的视频文件,绑定回调函数,然后开始对每一帧进行处理,要调用这个视频处理类,只需在main函数中添加:

    // 定义一个视频处理类处理视频帧    // 首先创建实例    VideoProcessor processor;    // 打开视频文件    processor.setInput("e:/BrokeGirls.mkv");    // 声明显示窗口    // 分别为输入和输出视频    processor.displayInput("Input Video");    processor.displayOutput("Output Video");    // 以原始帧率播放视频    processor.setDelay(1000./processor.getFrameRate());    // 设置处理回调函数    processor.setFrameProcessor(canny);    // 开始帧处理过程    processor.run();    cv::waitKey();

效果:

如何进行OpenCV2中的视频流读取与处理

OpenCV:打开摄像头获取视频流 

#include#includeusing namespace cv;using namespace std;int main(){//【1】从摄像头读入视频    VideoCapture capture(1);    if (!capture.isOpened()){cout<< "open camera fail ..." << endl;        return -1;    }capture.set(CAP_PROP_FRAME_WIDTH, 640);    capture.set(CAP_PROP_FRAME_HEIGHT, 480);    char filename[200];    int count =0;    //【2】循环显示每一帧    Mat frame;  //定义一个Mat变量,用于存储每一帧的图像    char key;    while (true){//读入图像        capture>> frame;  //读取当前帧        key = waitKey(20);        if(key ==27)//esc键退出            break;        if(key ==32)//空格键保存图像        {sprintf(filename, "Picture_%d.png", ++count);            imwrite(filename, frame);//            namedWindow("[frame]", WINDOW_NORMAL);            imshow("[frame]",frame);        }imshow("image", frame);  //显示当前帧    }return 0;}

关于如何进行OpenCV2中的视频流读取与处理就分享到这里啦,希望上述内容能够让大家有所提升。如果想要学习更多知识,请大家多多留意小编的更新。谢谢大家关注一下编程网网站!

--结束END--

本文标题: 如何进行OpenCV2中的视频流读取与处理

本文链接: https://lsjlt.com/news/306699.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何进行OpenCV2中的视频流读取与处理
    这篇文章跟大家分析一下“如何进行OpenCV2中的视频流读取与处理”。内容详细易懂,对“如何进行OpenCV2中的视频流读取与处理”感兴趣的朋友可以跟着小编的思路慢慢深入来阅读一下,希望阅读后能够对大家有所帮助。下面跟着小编一起深入学习“如...
    99+
    2023-06-26
  • OpenCV2学习笔记之视频流读取与处理
    目录前言一. 读取视频序列二. 处理视频帧OpenCV:打开摄像头获取视频流 总结 前言 由于项目需要,计划实现九路视频拼接,因此必须熟悉OpenCV对视频序列的...
    99+
    2024-04-02
  • 如何在PHP中进行视频处理?
    在当今日益数字化的时代,视频处理已成为人们日常工作和生活中不可或缺的一部分。而在PHP开发领域,如何进行视频处理也是一个很重要的问题。本文将介绍PHP中常用的视频处理方式及其实现方法。一、视频格式介绍在进行视频处理之前,我们需要首先了解一些...
    99+
    2023-05-14
    PHP 视频处理 处理视频
  • 如何使用PHP进行视频处理?
    随着网络技术的飞速发展,视频已经成为人们日常生活中不可或缺的一部分。在这个数字时代,如何使用PHP进行视频处理已经成为了一个热门话题,本文将介绍PHP的一些基本功能和工具,以帮助大家更好地处理视频。一、认识PHPPHP是一种高级程序设计语言...
    99+
    2023-05-22
    PHP 视频处理 多媒体应用
  • 如何使用PHP进行视频文件处理?
    视频文件处理是现代网络应用程序中必不可少的一部分,它包括裁剪、压缩、转码、添加水印和合并等操作。PHP 作为一种流行的服务器端编程语言,可以用于处理这些要求。在本文中,我们将介绍如何使用 PHP 处理视频文件。安装 FFMPEG 库FFMP...
    99+
    2023-05-14
    PHP 视频文件处理 处理技巧
  • javaCV视频处理之如何提取人像视频
    这篇文章主要为大家展示了“javaCV视频处理之如何提取人像视频”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“javaCV视频处理之如何提取人像视频”这篇文章吧。效果图对比左侧的为原视频,右侧为...
    99+
    2023-06-22
  • 如何使用 JavaScript object URLs进行图像音频和视频的处理
    本篇文章为大家展示了如何使用 JavaScript object URLs进行图像音频和视频的处理,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。许多Web应用程序需...
    99+
    2024-04-02
  • Golang与FFmpeg: 利用命令行工具进行音视频处理
    Golang是一种编程语言,而FFmpeg是一个开源的音视频处理工具。在Golang中,我们可以利用命令行工具来调用FFmpeg进行...
    99+
    2023-10-08
    Golang
  • 使用Python进行网站数据爬取和视频处理
    导语 在互联网时代,我们经常需要从网站上获取数据并进行分析或处理。有时候,我们还需要对视频数据进行一些操作,比如剪辑、转码、合成等。Python是一门非常适合做数据分析和视频处理的编程语言,它有很多...
    99+
    2023-09-04
    python 网络爬虫 requests 爬虫代理 视频处理 moviepy 数据爬取
  • Java如何添加、读取PPT幻灯片中的视频、音频
    小编给大家分享一下Java如何添加、读取PPT幻灯片中的视频、音频,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!使用工具:Free Spire.Presentation for Java (免费版)Jar文件获取及导入:方...
    99+
    2023-06-02
  • python用moviepy对视频进行简单的处理
    目录楔子moviepy的简单使用一个小栗子那么moviepy是如何工作的呢?视频属性视频合成1.多个视频按照先后顺序拼接起来。比如一个一分钟和一个两分钟的视频组合起来,变成三分钟。2...
    99+
    2024-04-02
  • C/C++中的OpenCV读取视频与调用摄像头
    目录OpenCV读取视频与调用摄像头读取视频播放视频调用摄像头这是读取文件然后进行播放下面是打开摄像头的代码Opencv读取视频以及打开摄像头以及视频读取失败原因1、打开摄像头2、视...
    99+
    2022-11-13
    C++ OpenCV OpenCV读取视频 调用摄像头
  • 怎么在python中使用moviepy对视频进行处理
    本篇文章为大家展示了怎么在python中使用moviepy对视频进行处理,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Python主要用来做什么Python主要应用于:1、Web开发;2、数据科学研...
    99+
    2023-06-08
  • Golang与FFmpeg: 实现实时视频流转发与处理的技术
    Golang与FFmpeg可以一起使用来实现实时视频流转发和处理的技术。Golang是一种高效的编程语言,而FFmpeg是一个强大的...
    99+
    2023-10-08
    Golang
  • Java如何读取Numpy文件并进行自然语言处理?
    随着自然语言处理技术的不断发展,越来越多的开发者开始关注如何使用Java进行自然语言处理。其中,读取Numpy文件是自然语言处理中的一项重要工作。本文将介绍如何使用Java读取Numpy文件并进行自然语言处理。 一、什么是Numpy文件 ...
    99+
    2023-11-08
    文件 numpy 自然语言处理
  • PHP中如何进行智能音乐和音频处理?
    随着音乐产业的不断发展和普及,音乐制作和音频处理的需求也日益增多。而PHP作为一种高度可扩展的编程语言,已经不仅仅局限于Web开发领域,还能用于音乐和音频的处理。本文将介绍如何使用PHP进行智能音乐和音频处理。一、智能音乐处理智能音乐处理是...
    99+
    2023-05-22
    PHP 音频处理 智能音乐
  • 如何在JAVA中使用ffmepg处理视频
    如何在JAVA中使用ffmepg处理视频?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。FFmepg安装路径:然后在使用的类中生命一个全局变量就好 pr...
    99+
    2023-06-15
  • PHP中如何进行数据爬取和爬取后的处理?
    随着互联网的蓬勃发展,数据在我们的日常生活和工作中变得越来越重要。而网络上的数据也越来越多,获取这些数据变得越来越重要。因此,数据爬取在现代网络应用开发中变得越来越流行。PHP是广泛使用的服务器端编程语言之一,也可以用于数据爬取和处理。在本...
    99+
    2023-05-20
    PHP 数据处理 数据爬取
  • 如何使用使用python+opencv解析视频并处理视频中的水印
    本篇内容主要讲解“如何使用使用python+opencv解析视频并处理视频中的水印”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何使用使用python+opencv解析视频并处理视频中的水印”...
    99+
    2023-06-02
  • 如何进行ITL与事务处理
    如何进行ITL与事务处理,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。 一、ITL与事务的关系 ITL(interested tran...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作