多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > OpenCV2學習筆記(九):視頻流讀取與處理

OpenCV2學習筆記(九):視頻流讀取與處理

來源:程序員人生   發布時間:2015-03-30 08:13:57 閱讀次數:9714次

由于項目需要,計劃實現9路視頻拼接,因此必須熟習OpenCV對視頻序列的處理。視頻信號處理是圖象處理的1個延伸,所謂的視頻序列是由按1定順序進行排放的圖象組成,即幀(Frame)。在這里,主要記錄下如何使用Qt+OpenCV讀取視頻中的每幀,以后,在這基礎上將1些圖象處理的算法應用到每幀上(如使用Canny算子檢測視頻中的邊沿)。

1. 讀取視頻序列

OpenCV提供了1個簡便易用的框架以提取視頻文件和USB攝像頭中的圖象幀,如果只是單單想讀取某個視頻,你只需要創建1個cv::VideoCapture實例,然后在循環中提取每幀。新建1個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) { // 嘗試讀取下1幀 if (!capture.read(frame)) break; cv::imshow("Extracted Frame",frame); // 引入延遲 if (cv::waitKey(delay)>=0) stop= true; } return a.exec(); }

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

這里寫圖片描述

2. 處理視頻幀

為了對視頻的每幀進行處理,這里創建自己的類VideoProcessor,其中封裝了OpenCV的視頻獲得框架,該類允許我們指定每幀調用的處理函數。

首先,我們希望指定1個回調解理函數,每幀中都將調用它。該函數接受1個cv::Mat對象,并輸出處理后的cv::Mat對象,其函數簽名以下:

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

作為這樣1個處理函數的例子,以下的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); }

現在我們需要創建1個VideoProcessor類,用來部署視頻處理模塊。而在此之前,需要先另外創建1個類,即VideoProcessor內部使用的幀處理類。這是由于在面向對象的上下文中,更合適使用幀處理類而不是1個幀處理函數,而使用類可以給程序員在觸及算法方面有更多的靈活度(書上介紹的)。將這個內部幀處理類命名為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; // 得到下1幀 // 可能來自:視頻文件或攝像頭 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(⑴), 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(); // 以下3個函數設置輸入的圖象向量 bool setInput(std::string filename); // 若輸入為攝像頭,設置ID bool setInput(int id); // 若輸入為1組圖象序列時,利用該函數 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(); // 返回下1幀的幀數 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); } // 若輸入為攝像頭,設置ID bool VideoProcessor::setInput(int id) { fnumber= 0; // 釋放之前打開過的視頻資源 capture.release(); images.clear(); // 打開視頻文件 return capture.open(id); } // 若輸入為1組圖象序列時,利用該函數 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(); } // 返回下1幀的幀數 long VideoProcessor::getFrameNumber() { if (images.size()==0) { // 得到捕獲裝備的信息 long f= static_cast<long>(capture.get(CV_CAP_PROP_POS_FRAMES)); return f; } else // 當輸入來自1組圖象序列時的情況 { 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()) { // 讀取下1幀 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(); } }

定義好視頻處理類,它將與1個回調函數相干聯。使用該類,可以創建1個實例,指定輸入的視頻文件,綁定回調函數,然后開始對每幀進行處理,要調用這個視頻處理類,只需在main函數中添加:

// 定義1個視頻處理類處理視頻幀 // 首先創建實例 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();

效果:

這里寫圖片描述

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 国产一二三区在线 | 男人看的网址 | 美女毛片视频 | 久久久精品456亚洲影院 | 亚洲免费中文字幕 | 日日摸人人看97人人澡 | 国产91精品高清一区二区三区 | 最近无中文字幕视频 | 欧美日韩国产高清一区二区三区 | 欧美日韩一区二区三区久久 | 欧美高清精品 | 伊人久久中文字幕久久cm | a国产片| 亚洲精品中文字幕一区在线 | 久久久久国产一级毛片高清版 | 在线观看国产小视频 | 国产男人女人做性全过程视频 | 精品国产一区二区三区在线 | 国产综合视频在线观看 | 国产aⅴ精品一区二区三区久久 | 伊人高清| 真实国产精品视频国产网 | 宅男午夜| 中国jizz妇女jizz妇女 | 尤物视频网站在线观看 | 日韩中文字幕视频在线观看 | 亚洲欧美日韩图片 | 最新国产视频 | 中文字幕无线 | 日韩欧美一区二区三区不卡在线 | 国产亚洲一区二区在线观看 | 欧美一欧美一区二三区性 | 亚洲成网站 | 就要精品综合久久久久五月天 | xxxxxx国产精品视频 | 精品国产亚洲人成在线 | 免费在线一区二区三区 | 在线观看h网站 | 麻豆精品成人免费国产片 | 久久亚 | 欧美成人精品高清在线观看 |