




版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 甘肅醫(yī)學(xué)院《生物化學(xué)生技生科制藥實驗》2023-2024學(xué)年第二學(xué)期期末試卷
- 云南能源職業(yè)技術(shù)學(xué)院《歌曲作法》2023-2024學(xué)年第二學(xué)期期末試卷
- 廣西演藝職業(yè)學(xué)院《園林植物病蟲害防治》2023-2024學(xué)年第二學(xué)期期末試卷
- 三亞中瑞酒店管理職業(yè)學(xué)院《土木工程造價與概預(yù)算》2023-2024學(xué)年第二學(xué)期期末試卷
- 哈爾濱電力職業(yè)技術(shù)學(xué)院《專項理論與技術(shù)武術(shù)套路類方向》2023-2024學(xué)年第二學(xué)期期末試卷
- 邯鄲幼兒師范高等??茖W(xué)?!抖嗝襟w作品創(chuàng)作》2023-2024學(xué)年第二學(xué)期期末試卷
- Crocacin-D-生命科學(xué)試劑-MCE
- 工業(yè)互聯(lián)網(wǎng)的信息化建設(shè)研究
- 工業(yè)互聯(lián)網(wǎng)的崛起與影響
- 工業(yè)互聯(lián)網(wǎng)的發(fā)展戰(zhàn)略及關(guān)鍵技術(shù)應(yīng)用研究
- 【上料機(jī)械手結(jié)構(gòu)中的真空系統(tǒng)的設(shè)計計算案例1100字】
- 西方美術(shù)史試題及答案
- 七年級數(shù)學(xué)下學(xué)期期末測試卷(1)(學(xué)生版+解析)-2025年七年級數(shù)學(xué)下學(xué)期期末總復(fù)習(xí)(北師大版)
- 校園短劇創(chuàng)作與演出指導(dǎo)行業(yè)跨境出海項目商業(yè)計劃書
- 2025年北京豐臺區(qū)九年級中考二模英語試卷試題(含答案詳解)
- 【7歷期末】安徽省合肥市包河區(qū)2023-2024學(xué)年部編版七年級下學(xué)期期末歷史試卷
- 新生兒收治流程規(guī)范與實施
- T/CBMCA 017-2021建筑用覆膜鋼板
- 《重癥監(jiān)護(hù)病房的臨終關(guān)懷和姑息治療指南》解讀
- 2025年初中地理會考試卷
- 中國鈦基復(fù)合材料行業(yè)市場前景預(yù)測及投資價值評估分析報告
評論
0/150
提交評論