基於OpenCV從零開始的視訊播放器!聘美騰訊,優酷等軟體的神器!
實現了在MFC中顯示圖片,再要顯示一個視訊就是輕而易舉的事了,本篇介紹使用Opencv製作一個簡易的播放器,實現開啟檔案、暫停、繼續播放、再次播放和總當前幀數顯示功能。
首先還是先看一下介面效果:
嗯,是不是很有MFC的感覺,簡潔大方、樸素典雅又實用~~,如果用一個字來概括的話那就是——醜!(按下不表~~)
1. 定義變數
控制元件之間有一些標誌位等變數需要傳遞,這裡用了一個偷懶的方法,在檔案內直接定義一個類Vardefine,用來儲存和傳遞變數:
2.開啟視訊檔案
加入一個按鈕控制元件BUTTON1,雙擊控制元件新增事件處理程式:
裡邊playVideo(CString &str)是播放視訊的實現模組。
3. 暫停&繼續播放&再次播放
同樣加入第二個按鈕控制元件BUTTON2,雙擊新增事件處理程式,涉及每次點選控制元件都會改變控制元件的顯示文字,你一定玩過這個小把戲
進群:548377875 即可獲取大量的學習資料以及從零開始到專案的實戰的PDF數十本呢!
4.視訊播放模組
這裡首先要在OpencvVideoDlg.h(你命名的工程可能不叫OpencvVideo,替換為你的命名)標頭檔案裡宣告方法“playVideo(CString &str)”,為了顯示方便,把整個標頭檔案貼出來如下:
// OpencvVideoDlg.h : 標頭檔案
//
#pragma once
#include "afxwin.h"
// COpencvVideoDlg 對話方塊
class COpencvVideoDlg : public CDialogEx
{
// 構造
public:
COpencvVideoDlg(CWnd* pParent = NULL);// 標準建構函式
// 對話方塊資料
enum { IDD = IDD_OPENCVVIDEO_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX);// DDX/DDV 支援
// 實現
protected:
HICON m_hIcon;
// 生成的訊息對映函式
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedButton1();
afx_msg void OnBnClickedButton2();
<span style="color:#ff0000;"><strong>afx_msg void playVideo(CString &str);</strong></span>
//CButton IDC_BUTTON2;
afx_msg void OnBnClickedCancel();
afx_msg void OnBnClickedOk();
};
加粗標紅的那一行就是新增的視訊顯示函式宣告。
playVideo函式具體實現程式碼:
void COpencvVideoDlg::playVideo(CString &str)
{
//CString to string 使用這個方法記得字符集選用“使用多位元組字元”,不然會報錯
string videopath=str.GetBuffer(0);
VideoCapture videocap(videopath); //開啟視訊檔案
if(!videocap.isOpened()) //檢查是否開啟
{
MessageBox("視訊檔案開啟失敗,請檢查!");
return;
}
double totalFrameNumber = videocap.get(CV_CAP_PROP_FRAME_COUNT); //獲取視訊幀率
CString ctotalFrameNumber;
ctotalFrameNumber.Format("%f",totalFrameNumber); //double->CString
SetDlgItemText(IDC_EDIT1,ctotalFrameNumber); //在edit1控制元件裡顯示總幀數
double videorate=videocap.get(CV_CAP_PROP_FPS); //獲取幀率
double videodelay=1000/videorate; //計算視訊每一幀間隔
Mat image;
Mat videoimage;
//以下操作獲取圖形控制元件尺寸並以此改變圖片尺寸
CRect rect;
GetDlgItem(IDC_STATIC_Video)->GetClientRect(&rect);
Rect dst(rect.left,rect.top,rect.right,rect.bottom);
while(true)
{
videocap.read(image); //視訊一幀一幀讀入Mat
resize(image,videoimage,cv::Size(rect.Width(),rect.Height())); //調整以適應視窗
imshow("view",videoimage);
while(Vardefine::pause) //判斷是否要求暫停
{
if(Vardefine::playOn) //若要求繼續播放,則跳出
{
break;
}
waitKey(50);
}
waitKey(videodelay); //每幀之間時間間隔
Vardefine::frameNum+=1;
CString cFrameNum;
cFrameNum.Format("%f",Vardefine::frameNum-1);
SetDlgItemText(IDC_EDIT2,cFrameNum); //在edit2內顯示當前幀數
if(Vardefine::frameNum>totalFrameNumber) //若播放視訊完成,則跳出
{
break;
}
}
SetDlgItemText(IDC_BUTTON2,"再次播放"); //置按鈕控制元件為“再次播放”
videocap.release(); //釋放視訊
}
視訊總幀數以及當前幀顯示已經包含在播放方法內實現了,不再贅述。
最後顯示一下播放效果:
通過對話方塊選擇視訊檔案後介面:
點選暫停之後介面:
點選繼續播放後介面:
播放完成:
再次播放: