OpenCV2學(xué)習(xí)筆記之視頻流讀取與處理_第1頁
OpenCV2學(xué)習(xí)筆記之視頻流讀取與處理_第2頁
OpenCV2學(xué)習(xí)筆記之視頻流讀取與處理_第3頁
OpenCV2學(xué)習(xí)筆記之視頻流讀取與處理_第4頁
OpenCV2學(xué)習(xí)筆記之視頻流讀取與處理_第5頁
已閱讀5頁,還剩9頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第OpenCV2學(xué)習(xí)筆記之視頻流讀取與處理目錄前言一.讀取視頻序列二.處理視頻幀OpenCV:打開攝像頭獲取視頻流總結(jié)

前言

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

一.讀取視頻序列

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

#includeQCoreApplication

#includeopencv2/core/core.hpp

#includeopencv2/imgproc/imgproc.hpp

#includeopencv2/highgui/highgui.hpp

#includeQDebug

intmain(intargc,char*argv[])

QCoreApplicationa(argc,argv);

//讀取視頻流

cv::VideoCapturecapture("e:/BrokeGirls.mkv");

//檢測視頻是否讀取成功

if(!capture.isOpened())

qDebug()"NoInputImage";

return1;

//獲取圖像幀率

doublerate=capture.get(CV_CAP_PROP_FPS);

boolstop(false);

cv::Matframe;//當(dāng)前視頻幀

cv::namedWindow("ExtractedFrame");

//每一幀之間的延遲

intdelay=1000/rate;

//遍歷每一幀

while(!stop)

//嘗試讀取下一幀

if(!capture.read(frame))

break;

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

//引入延遲

if(cv::waitKey(delay)=0)

stop=true;

returna.exec();

}

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

二.處理視頻幀

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

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

voidprocessFrame(cv::Matimg,cv::Matout);

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

//對視頻的每幀做Canny算子邊緣檢測

voidcanny(cv::Matimg,cv::Matout)

//先要把每幀圖像轉(zhuǎn)化為灰度圖

cv::cvtColor(img,out,CV_BGR2GRAY);

//調(diào)用Canny函數(shù)

cv::Canny(out,out,100,200);

//對像素進(jìn)行翻轉(zhuǎn)

cv::threshold(out,out,128,255,cv::THRESH_BINARY_INV);

}

現(xiàn)在我們需要創(chuàng)建一個VideoProcessor類,用來部署視頻處理模塊。而在此之前,需要先另外創(chuàng)建一個類,即VideoProcessor內(nèi)部使用的幀處理類。這是因為在面向?qū)ο蟮纳舷挛闹?,更適合使用幀處理類而不是一個幀處理函數(shù),而使用類可以給程序員在涉及算法方面有更多的靈活度(書上介紹的)。將這個內(nèi)部幀處理類命名為FrameProcessor,其定義如下:

#ifndefFRAMEPROCESSOR_H

#defineFRAMEPROCESSOR_H

#includeopencv2/core/core.hpp

#includeopencv2/highgui/highgui.hpp

classFrameProcessor

public:

virtualvoidprocess(cv::Matinput,cv::Matoutput)=0;

#endif//FRAMEPROCESSOR_H

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

#ifndefVIDEOPROCESSOR_H

#defineVIDEOPROCESSOR_H

#includeopencv2/core/core.hpp

#includeopencv2/imgproc/imgproc.hpp

#includeopencv2/highgui/highgui.hpp

#includeQDebug

#include"frameprocessor.h"

classVideoProcessor

private:

//創(chuàng)建視頻捕獲對象

cv::VideoCapturecapture;

//每幀調(diào)用的回調(diào)函數(shù)

void(*process)(cv::Mat,cv::Mat

//FrameProcessor接口

FrameProcessor*frameProcessor;

//確定是否調(diào)用回調(diào)函數(shù)的bool信號

boolcallIt;

//輸入窗口的名稱

std::stringwindowNameInput;

//輸出窗口的名稱

std::stringwindowNameOutput;

//延遲

intdelay;

//已處理的幀數(shù)

longfnumber;

//在該幀停止

longframeToStop;

//是否停止處理

boolstop;

//當(dāng)輸入圖像序列存儲在不同文件中時,可使用以下設(shè)置

//把圖像文件名的數(shù)組作為輸入

std::vectorstd::stringimages;

//圖像向量的迭加器

std::vectorstd::string::const_iteratoritImg;

//得到下一幀

//可能來自:視頻文件或攝像頭

boolreadNextFrame(cv::Matframe)

if(images.size()==0)

returncapture.read(frame);

else{

if(itImg!=images.end())

frame=cv::imread(*itImg);

itImg++;

returnframe.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)建輸入窗口

voiddisplayInput(std::stringwt);

//創(chuàng)建輸出窗口

voiddisplayOutput(std::stringwn);

//不再顯示處理后的幀

voiddontDisplay();

//以下三個函數(shù)設(shè)置輸入的圖像向量

boolsetInput(std::stringfilename);

//若輸入為攝像頭,設(shè)置ID

boolsetInput(intid);

//若輸入為一組圖像序列時,應(yīng)用該函數(shù)

boolsetInput(conststd::vectorstd::stringimgs);

//設(shè)置幀之間的延遲

//0意味著在每一幀都等待按鍵響應(yīng)

//負(fù)數(shù)意味著沒有延遲

voidsetDelay(intd);

//返回圖像的幀率

doublegetFrameRate();

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

voidcallProcess();

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

voiddontCallProcess();

//設(shè)置FrameProcessor實例

voidsetFrameProcessor(FrameProcessor*frameProcessorPtr);

//設(shè)置回調(diào)函數(shù)

voidsetFrameProcessor(void(*frameProcessingCallback)(cv::Mat,cv::Mat

//停止運行

voidstopIt();

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

boolisStopped();

//是否開始了捕獲設(shè)備?

boolisOpened();

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

longgetFrameNumber();

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

voidrun();

#endif//VIDEOPROCESSOR_H

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

#include"videoprocessor.h"

//創(chuàng)建輸入窗口

voidVideoProcessor::displayInput(std::stringwt)

windowNameInput=wt;

cv::namedWindow(windowNameInput);

//創(chuàng)建輸出窗口

voidVideoProcessor::displayOutput(std::stringwn)

windowNameOutput=wn;

cv::namedWindow(windowNameOutput);

//不再顯示處理后的幀

voidVideoProcessor::dontDisplay()

cv::destroyWindow(windowNameInput);

cv::destroyWindow(windowNameOutput);

windowNameInput.clear();

windowNameOutput.clear();

//設(shè)置輸入的圖像向量

boolVideoProcessor::setInput(std::stringfilename)

fnumber=0;

//釋放之前打開過的視頻資源

capture.release();

images.clear();

//打開視頻

returncapture.open(filename);

//若輸入為攝像頭,設(shè)置ID

boolVideoProcessor::setInput(intid)

fnumber=0;

//釋放之前打開過的視頻資源

capture.release();

images.clear();

//打開視頻文件

returncapture.open(id);

//若輸入為一組圖像序列時,應(yīng)用該函數(shù)

boolVideoProcessor::setInput(conststd::vectorstd::stringimgs)

fnumber=0;

//釋放之前打開過的視頻資源

capture.release();

//輸入將是該圖像的向量

images=imgs;

itImg=images.begin();

returntrue;

//設(shè)置幀之間的延遲

//0意味著在每一幀都等待按鍵響應(yīng)

//負(fù)數(shù)意味著沒有延遲

voidVideoProcessor::setDelay(intd)

delay=d;

//返回圖像的幀率

doubleVideoProcessor::getFrameRate()

if(images.size()!=0)return0;

doubler=capture.get(CV_CAP_PROP_FPS);

returnr;

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

voidVideoProcessor::callProcess()

callIt=true;

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

voidVideoProcessor::dontCallProcess()

callIt=false;

//設(shè)置FrameProcessor實例

voidVideoProcessor::setFrameProcessor(FrameProcessor*frameProcessorPtr)

//使回調(diào)函數(shù)無效化

process=0;

//重新設(shè)置FrameProcessor實例

frameProcessor=frameProcessorPtr;

callProcess();

//設(shè)置回調(diào)函數(shù)

voidVideoProcessor::setFrameProcessor(void(*frameProcessingCallback)(cv::Mat,cv::Mat))

//使FrameProcessor實例無效化

frameProcessor=0;

//重新設(shè)置回調(diào)函數(shù)

process=frameProcessingCallback;

callProcess();

//以下函數(shù)表示視頻的讀取狀態(tài)

//停止運行

voidVideoProcessor::stopIt()

stop=true;

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

boolVideoProcessor::isStopped()

returnstop;

//是否開始了捕獲設(shè)備?

boolVideoProcessor::isOpened()

returncapture.isOpened()||!images.empty();

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

longVideoProcessor::getFrameNumber()

if(images.size()==0)

//得到捕獲設(shè)備的信息

longf=static_castlong(capture.get(CV_CAP_PROP_POS_FRAMES));

returnf;

else//當(dāng)輸入來自一組圖像序列時的情況

returnstatic_castlong(itImg-images.begin());

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

voidVideoProcessor::run()

//當(dāng)前幀

cv::Matframe;

//輸出幀

cv::Matoutput;

//打開失敗時

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);

elseif(frameProcessor)

frameProcessor-process(frame,output);

//增加幀數(shù)

fnumber++;

else

output=frame;

//顯示輸出幀

if(windowNameOutput.length()!=0)

cv::imshow(windowNameOutput,output);

//引入延遲

if(delay=0cv::waitKey(delay)=0)

stopIt();

//檢查是否需要停止運行

if(frameToStop=0getFrameNumber()==frameToStop)

stopIt();

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

//定義一個視頻處理類處理視頻幀

//首先創(chuàng)建實例

VideoProcessorprocessor;

//打開視頻文件

processor.setInput("e:/BrokeGirls.mkv");

//聲明顯示窗口

//分別為輸入和輸出視頻

processor.displayInput("InputVideo");

processor.displayOutput("OutputVideo");

//以原始幀率播放視頻

processor.setDelay(1000./process

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論