最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

OpenCV2學(xué)習(xí)筆記之視頻流讀取與處理

 更新時(shí)間:2022年01月09日 09:34:27   作者:Herbert_Zero  
為OpenCV是搞計(jì)算機(jī)視覺(jué)必須要掌握的基礎(chǔ),這篇文章主要給大家介紹了關(guān)于OpenCV2學(xué)習(xí)筆記之視頻流讀取與處理的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

由于項(xiàng)目需要,計(jì)劃實(shí)現(xiàn)九路視頻拼接,因此必須熟悉OpenCV對(duì)視頻序列的處理。視頻信號(hào)處理是圖像處理的一個(gè)延伸,所謂的視頻序列是由按一定順序進(jìn)行排放的圖像組成,即幀(Frame)。在這里,主要記錄下如何使用Qt+OpenCV讀取視頻中的每一幀,之后,在這基礎(chǔ)上將一些圖像處理的算法運(yùn)用到每一幀上(如使用Canny算子檢測(cè)視頻中的邊緣)。

一. 讀取視頻序列

OpenCV提供了一個(gè)簡(jiǎn)便易用的框架以提取視頻文件和USB攝像頭中的圖像幀,如果只是單單想讀取某個(gè)視頻,你只需要?jiǎng)?chuàng)建一個(gè)cv::VideoCapture實(shí)例,然后在循環(huán)中提取每一幀。新建一個(gè)Qt控制臺(tái)項(xiàng)目,直接在main函數(shù)添加:

#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");
    // 檢測(cè)視頻是否讀取成功
    if (!capture.isOpened())
    {
        qDebug() << "No Input Image";
        return 1;
    }

    // 獲取圖像幀率
    double rate= capture.get(CV_CAP_PROP_FPS);
    bool stop(false);
    cv::Mat frame; // 當(dāng)前視頻幀
    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();
}

(注意:要正確打開(kāi)視頻文件,計(jì)算機(jī)中必須安裝有對(duì)應(yīng)的解碼器,否則cv::VideoCapture無(wú)法理解視頻格式?。┻\(yùn)行后,將出現(xiàn)一個(gè)窗口,播放選定的視頻(需要在創(chuàng)建cv::VideoCapture對(duì)象時(shí)指定視頻的文件名)。

這里寫(xiě)圖片描述

二. 處理視頻幀

為了對(duì)視頻的每一幀進(jìn)行處理,這里創(chuàng)建自己的類VideoProcessor,其中封裝了OpenCV的視頻獲取框架,該類允許我們指定每幀調(diào)用的處理函數(shù)。

首先,我們希望指定一個(gè)回調(diào)處理函數(shù),每一幀中都將調(diào)用它。該函數(shù)接受一個(gè)cv::Mat對(duì)象,并輸出處理后的cv::Mat對(duì)象,其函數(shù)簽名如下:

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

作為這樣一個(gè)處理函數(shù)的例子,以下的Canny函數(shù)計(jì)算圖像的邊緣,使用時(shí)直接添加在mian文件中即可:

    // 對(duì)視頻的每幀做Canny算子邊緣檢測(cè)
void canny(cv::Mat& img, cv::Mat& out) 
{
    // 先要把每幀圖像轉(zhuǎn)化為灰度圖
    cv::cvtColor(img,out,CV_BGR2GRAY);
    // 調(diào)用Canny函數(shù)
    cv::Canny(out,out,100,200);
    // 對(duì)像素進(jìn)行翻轉(zhuǎn)
    cv::threshold(out,out,128,255,cv::THRESH_BINARY_INV);
}

現(xiàn)在我們需要?jiǎng)?chuàng)建一個(gè)VideoProcessor類,用來(lái)部署視頻處理模塊。而在此之前,需要先另外創(chuàng)建一個(gè)類,即VideoProcessor內(nèi)部使用的幀處理類。這是因?yàn)樵诿嫦驅(qū)ο蟮纳舷挛闹校m合使用幀處理類而不是一個(gè)幀處理函數(shù),而使用類可以給程序員在涉及算法方面有更多的靈活度(書(shū)上介紹的)。將這個(gè)內(nèi)部幀處理類命名為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

現(xiàn)在可以開(kāi)始定義VideoProcessor類了,以下為videoprocessor.h中的內(nèi)容:

#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:
      // 創(chuàng)建視頻捕獲對(duì)象
      cv::VideoCapture capture;
      // 每幀調(diào)用的回調(diào)函數(shù)
      void (*process)(cv::Mat&, cv::Mat&);
      // FrameProcessor接口
      FrameProcessor *frameProcessor;
      // 確定是否調(diào)用回調(diào)函數(shù)的bool信號(hào)
      bool callIt;
      // 輸入窗口的名稱
      std::string windowNameInput;
      // 輸出窗口的名稱
      std::string windowNameOutput;
      // 延遲
      int delay;
      // 已處理的幀數(shù)
      long fnumber;
      // 在該幀停止
      long frameToStop;
      // 是否停止處理
      bool stop;

      // 當(dāng)輸入圖像序列存儲(chǔ)在不同文件中時(shí),可使用以下設(shè)置
      // 把圖像文件名的數(shù)組作為輸入
      std::vector<std::string> images;
      // 圖像向量的迭加器
      std::vector<std::string>::const_iterator itImg;

      // 得到下一幀
      // 可能來(lái)自:視頻文件或攝像頭
      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:

      // 默認(rèn)設(shè)置 digits(0), frameToStop(-1),
      VideoProcessor() : callIt(false), delay(-1),
          fnumber(0), stop(false),
          process(0), frameProcessor(0) {}

      // 創(chuàng)建輸入窗口
      void displayInput(std::string wt);
      // 創(chuàng)建輸出窗口
      void displayOutput(std::string wn);
      // 不再顯示處理后的幀
      void dontDisplay();

      // 以下三個(gè)函數(shù)設(shè)置輸入的圖像向量
      bool setInput(std::string filename);
      // 若輸入為攝像頭,設(shè)置ID
      bool setInput(int id);
      // 若輸入為一組圖像序列時(shí),應(yīng)用該函數(shù)
      bool setInput(const std::vector<std::string>& imgs);

      // 設(shè)置幀之間的延遲
      // 0意味著在每一幀都等待按鍵響應(yīng)
      // 負(fù)數(shù)意味著沒(méi)有延遲
      void setDelay(int d);

      // 返回圖像的幀率
      double getFrameRate();

      // 需要調(diào)用回調(diào)函數(shù)
      void callProcess();

      // 不需要調(diào)用回調(diào)函數(shù)
      void dontCallProcess();

      // 設(shè)置FrameProcessor實(shí)例
      void setFrameProcessor(FrameProcessor* frameProcessorPtr);

      // 設(shè)置回調(diào)函數(shù)
      void setFrameProcessor(void (*frameProcessingCallback)(cv::Mat&, cv::Mat&));

      // 停止運(yùn)行
      void stopIt();

      // 判斷是否已經(jīng)停止
      bool isStopped();

      // 是否開(kāi)始了捕獲設(shè)備?
      bool isOpened();

      // 返回下一幀的幀數(shù)
      long getFrameNumber();

      // 該函數(shù)獲取并處理視頻幀
      void run();

};

#endif // VIDEOPROCESSOR_H

然后,在videoprocessor.cpp中定義各個(gè)函數(shù)的功能:

#include "videoprocessor.h"

// 創(chuàng)建輸入窗口
void VideoProcessor::displayInput(std::string wt)
{
    windowNameInput= wt;
    cv::namedWindow(windowNameInput);
}

// 創(chuàng)建輸出窗口
void VideoProcessor::displayOutput(std::string wn)
{
    windowNameOutput= wn;
    cv::namedWindow(windowNameOutput);
}

// 不再顯示處理后的幀
void VideoProcessor::dontDisplay()
{
    cv::destroyWindow(windowNameInput);
    cv::destroyWindow(windowNameOutput);
    windowNameInput.clear();
    windowNameOutput.clear();
}

// 設(shè)置輸入的圖像向量
bool VideoProcessor::setInput(std::string filename)
{
  fnumber= 0;
  // 釋放之前打開(kāi)過(guò)的視頻資源
  capture.release();
  images.clear();

  // 打開(kāi)視頻
  return capture.open(filename);
}

// 若輸入為攝像頭,設(shè)置ID
bool VideoProcessor::setInput(int id)
{
  fnumber= 0;
  // 釋放之前打開(kāi)過(guò)的視頻資源
  capture.release();
  images.clear();

  // 打開(kāi)視頻文件
  return capture.open(id);
}

// 若輸入為一組圖像序列時(shí),應(yīng)用該函數(shù)
bool VideoProcessor::setInput(const std::vector<std::string>& imgs)
{
  fnumber= 0;
  // 釋放之前打開(kāi)過(guò)的視頻資源
  capture.release();

  // 輸入將是該圖像的向量
  images= imgs;
  itImg= images.begin();

  return true;
}

// 設(shè)置幀之間的延遲
// 0意味著在每一幀都等待按鍵響應(yīng)
// 負(fù)數(shù)意味著沒(méi)有延遲
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;
}

// 需要調(diào)用回調(diào)函數(shù)
void VideoProcessor::callProcess()
{
    callIt= true;
}

// 不需要調(diào)用回調(diào)函數(shù)
void VideoProcessor::dontCallProcess()
{
    callIt= false;
}

// 設(shè)置FrameProcessor實(shí)例
void VideoProcessor::setFrameProcessor(FrameProcessor* frameProcessorPtr)
{
    // 使回調(diào)函數(shù)無(wú)效化
    process= 0;
    // 重新設(shè)置FrameProcessor實(shí)例
    frameProcessor= frameProcessorPtr;
    callProcess();
}

// 設(shè)置回調(diào)函數(shù)
void VideoProcessor::setFrameProcessor(void (*frameProcessingCallback)(cv::Mat&, cv::Mat&))
{
    // 使FrameProcessor實(shí)例無(wú)效化
    frameProcessor= 0;
    // 重新設(shè)置回調(diào)函數(shù)
    process= frameProcessingCallback;
    callProcess();
}

// 以下函數(shù)表示視頻的讀取狀態(tài)
// 停止運(yùn)行
void VideoProcessor::stopIt()
{
    stop= true;
}

// 判斷是否已經(jīng)停止
bool VideoProcessor::isStopped()
{
    return stop;
}

// 是否開(kāi)始了捕獲設(shè)備?
bool VideoProcessor::isOpened()
{
    return capture.isOpened() || !images.empty();
}

// 返回下一幀的幀數(shù)
long VideoProcessor::getFrameNumber()
{
  if (images.size()==0)
  {
      // 得到捕獲設(shè)備的信息
      long f= static_cast<long>(capture.get(CV_CAP_PROP_POS_FRAMES));
      return f;

  }
  else // 當(dāng)輸入來(lái)自一組圖像序列時(shí)的情況
  {
      return static_cast<long>(itImg-images.begin());
  }
}

// 該函數(shù)獲取并處理視頻幀
void VideoProcessor::run()
{
    // 當(dāng)前幀
    cv::Mat frame;
    // 輸出幀
    cv::Mat output;

    // 打開(kāi)失敗時(shí)
    if (!isOpened())
    {
        qDebug() << "Error!";
        return;
    }
    stop= false;
    while (!isStopped())
    {
        // 讀取下一幀
        if (!readNextFrame(frame))
            break;
        // 顯示輸出幀
        if (windowNameInput.length()!=0)
            cv::imshow(windowNameInput,frame);
        // 調(diào)用處理函數(shù)
        if (callIt)
        {
          // 處理當(dāng)前幀
          if (process)
              process(frame, output);
          else if (frameProcessor)
              frameProcessor->process(frame,output);
          // 增加幀數(shù)
          fnumber++;
        }
        else
        {
          output= frame;
        }
        // 顯示輸出幀
        if (windowNameOutput.length()!=0)
            cv::imshow(windowNameOutput,output);
        // 引入延遲
        if (delay>=0 && cv::waitKey(delay)>=0)
          stopIt();
        // 檢查是否需要停止運(yùn)行
        if (frameToStop>=0 && getFrameNumber()==frameToStop)
            stopIt();
    }
}

定義好視頻處理類,它將與一個(gè)回調(diào)函數(shù)相關(guān)聯(lián)。使用該類,可以創(chuàng)建一個(gè)實(shí)例,指定輸入的視頻文件,綁定回調(diào)函數(shù),然后開(kāi)始對(duì)每一幀進(jìn)行處理,要調(diào)用這個(gè)視頻處理類,只需在main函數(shù)中添加:

    // 定義一個(gè)視頻處理類處理視頻幀
    // 首先創(chuàng)建實(shí)例
    VideoProcessor processor;
    // 打開(kāi)視頻文件
    processor.setInput("e:/BrokeGirls.mkv");
    // 聲明顯示窗口
    // 分別為輸入和輸出視頻
    processor.displayInput("Input Video");
    processor.displayOutput("Output Video");
    // 以原始幀率播放視頻
    processor.setDelay(1000./processor.getFrameRate());
    // 設(shè)置處理回調(diào)函數(shù)
    processor.setFrameProcessor(canny);
    // 開(kāi)始幀處理過(guò)程
    processor.run();
    cv::waitKey();

效果:

這里寫(xiě)圖片描述

OpenCV:打開(kāi)攝像頭獲取視頻流 

#include

#include

using 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】循環(huán)顯示每一幀

    Mat frame;  //定義一個(gè)Mat變量,用于存儲(chǔ)每一幀的圖像

    char key;

    while (true)

{

//讀入圖像

        capture>> frame;  //讀取當(dāng)前幀

        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);  //顯示當(dāng)前幀

    }

return 0;

}

總結(jié) 

到此這篇關(guān)于OpenCV2學(xué)習(xí)筆記之視頻流讀取與處理的文章就介紹到這了,更多相關(guān)OpenCV視頻流讀取與處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • django之導(dǎo)入并執(zhí)行自定義的函數(shù)模塊圖解

    django之導(dǎo)入并執(zhí)行自定義的函數(shù)模塊圖解

    這篇文章主要介紹了django之導(dǎo)入并執(zhí)行自定義的函數(shù)模塊圖解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-04-04
  • 使用Python一鍵提取PDF中的表格到Excel的方法詳解

    使用Python一鍵提取PDF中的表格到Excel的方法詳解

    從PDF文件獲取表格中的數(shù)據(jù),也是日常辦公容易涉及到的一項(xiàng)工作,一個(gè)一個(gè)復(fù)制吧,效率確實(shí)太低了,用Python從PDF文檔中提取表格數(shù)據(jù),并寫(xiě)入Excel文件,灰常灰常高效,本文就給大家介紹一下如何使用Python一鍵提取PDF中的表格到Excel,需要的朋友可以參考下
    2023-08-08
  • matlab繪制局部放大圖圖文教程

    matlab繪制局部放大圖圖文教程

    這篇文章主要給大家介紹了關(guān)于matlab繪制局部放大圖的相關(guān)資料,所謂局部放大即呈現(xiàn)子圖,以顯示局部細(xì)節(jié),需要的朋友可以參考下
    2023-07-07
  • Python第三方包之DingDingBot釘釘機(jī)器人

    Python第三方包之DingDingBot釘釘機(jī)器人

    這篇文章主要介紹了Python第三方包之DingDingBot釘釘機(jī)器人,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • Python?if?判斷語(yǔ)句詳解

    Python?if?判斷語(yǔ)句詳解

    這篇文章主要介紹了Python?if?判斷語(yǔ)句,包括流程控制,順序結(jié)構(gòu)和分支結(jié)構(gòu),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-11-11
  • Python+Qt身體特征識(shí)別人數(shù)統(tǒng)計(jì)源碼窗體程序(使用步驟)

    Python+Qt身體特征識(shí)別人數(shù)統(tǒng)計(jì)源碼窗體程序(使用步驟)

    這篇文章主要介紹了Python+Qt身體特征識(shí)別人數(shù)統(tǒng)計(jì)源碼窗體程序(使用步驟),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • python解析多層json操作示例

    python解析多層json操作示例

    這篇文章主要介紹了python解析多層json操作,結(jié)合實(shí)例形式分析了Python針對(duì)多層json文件的讀取、解析、修改、保存等相關(guān)操作技巧,需要的朋友可以參考下
    2019-12-12
  • 關(guān)于Python的異常捕獲和處理

    關(guān)于Python的異常捕獲和處理

    程序在運(yùn)行過(guò)程當(dāng)中,不可避免的會(huì)出現(xiàn)一些錯(cuò)誤,比如:使用了沒(méi)有賦值過(guò)的變量,使用了不存在的索引,一個(gè)數(shù)字除以0,這些錯(cuò)誤在程序中,我們稱其為異常,那么如何處理這些異常呢,今天我們就來(lái)看一看
    2023-04-04
  • matplotlib繪制多子圖共享鼠標(biāo)光標(biāo)的方法示例

    matplotlib繪制多子圖共享鼠標(biāo)光標(biāo)的方法示例

    這篇文章主要介紹了matplotlib繪制多子圖共享鼠標(biāo)光標(biāo)的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • python3安裝crypto出錯(cuò)及解決方法

    python3安裝crypto出錯(cuò)及解決方法

    這篇文章主要介紹了python3安裝crypto出錯(cuò)及解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07

最新評(píng)論

南郑县| 盐边县| 阜阳市| 盐源县| 阿克陶县| 北流市| 顺平县| 象山县| 周宁县| 永吉县| 华池县| 秦安县| 秦皇岛市| 汶川县| 桓仁| 登封市| 微山县| 扎赉特旗| 云和县| 昌图县| 惠来县| 台湾省| 苏尼特右旗| 印江| 桃园市| 上林县| 和田市| 将乐县| 布拖县| 阿瓦提县| 枣阳市| 五家渠市| 海盐县| 武乡县| 都昌县| 安化县| 开封市| 靖江市| 南雄市| 乌鲁木齐市| 梁河县|