基于Qt+opencv開發(fā)的視頻播放器示例詳解
1、開發(fā)環(huán)境
Qt:Qt5.14
opencv:4.5.5
2、效果展示
可以實(shí)現(xiàn)播放、暫停、快進(jìn)、后退、重新播放、停止、拖動(dòng)進(jìn)度條等功能;
3、代碼功能解析
3.1 opencv庫(kù)加載
因?yàn)槭褂昧薿pencv的VideoCapture來加載視頻,這里需要添加opencv的庫(kù),右鍵項(xiàng)目工程添加外部庫(kù),填入opencv的庫(kù)和頭文件路徑,或者直接在皮肉文件下添加庫(kù)的文件路徑。
win32:CONFIG(release, debug|release): LIBS += -LD:/opencv/build/x64/vc15/lib/ -lopencv_world455 else:win32:CONFIG(debug, debug|release): LIBS += -LD:/opencv/build/x64/vc15/lib/ -lopencv_world455d INCLUDEPATH += D:/opencv/build/include DEPENDPATH += D:/opencv/build/include
這里我的opencv路徑在D盤對(duì)應(yīng)路徑下。
3.2 重寫horizontalSlider點(diǎn)擊事件
這里需要點(diǎn)擊進(jìn)度條實(shí)現(xiàn)視頻跳轉(zhuǎn)到當(dāng)前進(jìn)度的功能,這里需要對(duì)horizontalSlider的點(diǎn)擊事件函數(shù)進(jìn)行重寫。實(shí)現(xiàn)點(diǎn)擊后獲取點(diǎn)擊處的進(jìn)度值并更新進(jìn)度條。
#include "newqslider.h" newqslider::newqslider(QWidget *parent) : QSlider(parent) { } /***************************************************************** * 函數(shù)名稱:mousePressEvent(QMouseEvent *ev) * 功能描述:重寫鼠標(biāo)點(diǎn)擊事件,實(shí)現(xiàn)進(jìn)度條點(diǎn)擊哪跳到哪 * 參數(shù)說明: 無 * 返回值: 無 ******************************************************************/ void newqslider::mousePressEvent(QMouseEvent *ev) { //先調(diào)用父類的鼠標(biāo)點(diǎn)擊處理事件,這樣可以不影響拖動(dòng)的情況 QSlider::mousePressEvent(ev); //獲取鼠標(biāo)的位置,這里并不能直接從ev中取值(因?yàn)槿绻峭蟿?dòng)的話,鼠標(biāo)開始點(diǎn)擊的位置沒有意義了) double pos = ev->pos().x() / (double)width(); setValue(pos * (maximum() - minimum()) + minimum()); //發(fā)送自定義的鼠標(biāo)單擊信號(hào) emit costomSliderClicked(); }
3.3 opencv采集線程
videothread.h
#include <QObject> #include <QThread> #include <opencv2/opencv.hpp> #include <iostream> #include <QDebug> #include <QDateTime> using namespace std; using namespace cv; class videothread : public QThread { Q_OBJECT public: videothread(const char* filename); void run(); //釋放視頻采集對(duì)象 void releaseCap(); //獲取視頻總幀數(shù) int getVideoAllFramecount(); //設(shè)置當(dāng)前進(jìn)度條 void setCurrentFrame(int value); bool getStop() const; //設(shè)置視頻結(jié)束標(biāo)識(shí) void setStop(bool value); bool getIsrun() const; void setIsrun(bool value); //暫停 void pauseThread(); //繼續(xù) void resumeThread(); //停止 void stopThread(); signals: //發(fā)送當(dāng)前幀和 幀數(shù) void sendFrame(int currentFrame,Mat frame); private: //視頻對(duì)象 VideoCapture cap; Mat frame; //視頻當(dāng)前幀數(shù) int currentFramecount; //總幀數(shù) int allFramecount; //視頻幀率 int fps; //錄制視頻幀 int videoWriterFrame; //線程結(jié)束標(biāo)識(shí)位 bool stop; //視頻暫停標(biāo)識(shí)位 bool isrun; };
采集線程中設(shè)置了暫停、繼續(xù)播放、停止,并可以獲取幀率和幀率數(shù)量;
videothread.cpp
#include "videothread.h" videothread::videothread(const char* filename) { this->stop = false; this->isrun =false; this->currentFramecount=0; this->videoWriterFrame=0; if(cap.open(filename));//創(chuàng)建視頻對(duì)象 { this->allFramecount=cap.get(CAP_PROP_FRAME_COUNT);//獲取視頻文件中的總幀數(shù) this->fps=int(round(cap.get(CAP_PROP_FPS)));//獲取視頻幀率 } } void videothread::run() { while(stop==false)//線程運(yùn)行和停止 卡住線程 暫停時(shí)不退出線程 { while(isrun==true)//視頻運(yùn)行和暫停 { if(cap.read(frame))//捕獲視頻幀 { this->currentFramecount++; cvtColor(frame, frame, COLOR_BGR2RGB);//opencvBGR格式轉(zhuǎn)成Image用到的RGB emit sendFrame(currentFramecount,frame);//發(fā)送幀數(shù)據(jù) } msleep(40);//延時(shí) } } cap.release();//釋放打開的視頻 } int videothread::getVideoAllFramecount() { return allFramecount; } void videothread::setStop(bool value) { stop = value; } void videothread::setCurrentFrame(int value) { this->currentFramecount=value;//當(dāng)前幀數(shù) cap.set(CAP_PROP_POS_FRAMES,currentFramecount);//進(jìn)度條跳轉(zhuǎn)對(duì)應(yīng)幀 } bool videothread::getIsrun() const { return isrun; } void videothread::setIsrun(bool value) { isrun = value; } void videothread::pauseThread()//這兩個(gè)函數(shù)用于確保是在運(yùn)行情況下才能切換狀態(tài) { if(this->isRunning()&&this->isrun==true)//當(dāng)前線程運(yùn)行且視頻運(yùn)行 { this->isrun=false; } } void videothread::resumeThread() { if(this->isRunning()&&this->isrun==false)//當(dāng)前線程運(yùn)行且視頻暫停 { this->isrun=true; } } void videothread::stopThread() { if(this->isRunning())//當(dāng)前線程運(yùn)行 { this->stop=true;//結(jié)束線程 //msleep(10); releaseCap(); this->terminate(); } } bool videothread::getStop() const { return stop; } void videothread::releaseCap() { if(cap.isOpened()){ cap.release(); } }
總結(jié)
此視頻播放器只涉及到opencv加載視頻和對(duì)視頻幀的處理,以及進(jìn)度條管理等部分功能,包括加載視頻后線程發(fā)送視頻幀圖像和幀數(shù),再使用中需要注意線程指針的創(chuàng)建和釋放、opencv采圖對(duì)象的新建和釋放,不然頻繁停止和加載會(huì)出現(xiàn)野指針和內(nèi)存泄漏的bug。
源碼學(xué)習(xí)
最后附上源碼大家交流學(xué)習(xí),可以在倉(cāng)庫(kù)按需自取,倉(cāng)庫(kù)中代碼僅供學(xué)習(xí)使用。如果對(duì)自己有幫助,麻煩點(diǎn)個(gè)星支持一下。
以上就是基于Qt+opencv開發(fā)的視頻播放器示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Qt opencv視頻播放器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語(yǔ)言通過三步翻轉(zhuǎn)法實(shí)現(xiàn)單詞倒置詳解
這篇文章主要為大家分享了用三步翻轉(zhuǎn)法將一句話的單詞進(jìn)行倒置的方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-05-05C/C++ 連接MySql數(shù)據(jù)庫(kù)的方法
本文對(duì)如何使用MySql的API連接MySql數(shù)據(jù)庫(kù),開發(fā)環(huán)境為VS2008,需要的朋友可以參考下2017-06-06C語(yǔ)言 表、棧和隊(duì)列詳解及實(shí)例代碼
這篇文章主要介紹了C語(yǔ)言 表、棧和隊(duì)列詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-02-02C語(yǔ)言與C++動(dòng)態(tài)通訊錄超詳細(xì)實(shí)現(xiàn)流程
這篇文章主要為大家介紹了C語(yǔ)言與C++動(dòng)態(tài)實(shí)現(xiàn)通訊錄,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-05-05C++中范圍(Ranges)與視圖(Views)的常見問題、易錯(cuò)點(diǎn)
ranges和views是C20引入的重要特性,它們讓代碼更加簡(jiǎn)潔、高效且富有表達(dá)力,通過理解其基本概念、注意常見的陷阱,并合理應(yīng)用高級(jí)技巧,開發(fā)者可以充分利用這些新特性,提升軟件質(zhì)量和開發(fā)效率,,本文將深入淺出地探討ranges與views的基礎(chǔ)概念、常見問題、易錯(cuò)點(diǎn)及避免策略2024-06-06C語(yǔ)言實(shí)現(xiàn)病例管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)病例管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01C++實(shí)現(xiàn)將輸入復(fù)制到輸出的方法
這篇文章主要介紹了C++實(shí)現(xiàn)將輸入復(fù)制到輸出的方法,實(shí)例分析了C++字符串轉(zhuǎn)換及輸入輸出操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07