zoukankan      html  css  js  c++  java
  • Opencv实现简易播放器

    实现了在MFC中显示图片,再要显示一个视频就是轻而易举的事了,本篇介绍使用Opencv制作一个简易的播放器,实现打开文件、暂停、继续播放、再次播放和总当前帧数显示功能。

    首先还是先看一下界面效果:


    嗯,是不是很有MFC的感觉,简洁大方、朴素典雅又实用~~,如果用一个字来概括的话那就是——丑!(按下不表~~可怜

    1. 定义变量

    控件之间有一些标志位等变量需要传递,这里用了一个偷懒的方法,在文件内直接定义一个类Vardefine,用来保存和传递变量:

    class Vardefine
    {
    public:
    	static bool pause;  //暂停标志位
    	static bool playOn;  //继续播放标志位
    	static bool playAgain; //再次播放标志位
    	static double frameNum;  //当前播放帧数
    	static CString str;     //保存视频文件路径
    };
    
    //变量初始化
    bool Vardefine::pause=false;
    bool Vardefine::playOn=false;
    bool Vardefine::playAgain=false;
    double Vardefine::frameNum=1.0;
    CString Vardefine::str="";

    2.打开视频文件

    加入一个按钮控件BUTTON1,双击控件添加事件处理程序:

    void COpencvVideoDlg::OnBnClickedButton1()
    {
    	// TODO: 在此添加控件通知处理程序代码	
    	CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT|OFN_ALLOWMULTISELECT,   
    		NULL, this);   //选择文件对话框  
    	if(dlg.DoModal() == IDOK)  
    	{  
    		Vardefine::str= dlg.GetPathName();  //获取视频文件路径  
    	}  
    	playVideo(Vardefine::str);   //自定义函数playVideo,播放视频
    }
    里边playVideo(CString &str)是播放视频的实现模块。

    3. 暂停&继续播放&再次播放

    同样加入第二个按钮控件BUTTON2,双击添加事件处理程序,涉及每次点击控件都会改变控件的显示文本,你一定玩过这个小把戏。

    void COpencvVideoDlg::OnBnClickedButton2()
    {
    	// TODO: 在此添加控件通知处理程序代码
    	CString button2Name;
    	GetDlgItemText(IDC_BUTTON2,button2Name);
    	if(button2Name=="暂停")
    	{
    		//设置暂停、继续播放、再次播放(再次播放本程序暂没用到)标志位
    		Vardefine::pause=true;
    		Vardefine::playAgain=false;
    		Vardefine::playOn=false;	
    		//如果是暂停,置位继续播放
    		SetDlgItemText(IDC_BUTTON2,"继续播放");
    	}
    	if(button2Name=="继续播放")
    	{
    		//设置暂停、继续播放、再次播放(再次播放本程序暂没用到)标志位
    		Vardefine::pause=false;
    		Vardefine::playOn=true;
    		Vardefine::playAgain=false;
    		//如果是继续播放,置为暂停
    		SetDlgItemText(IDC_BUTTON2,"暂停");
    	}
    	if(button2Name=="再次播放")
    	{
    		//设置暂停、继续播放、再次播放(再次播放本程序暂没用到)标志位
    		Vardefine::pause=false;
    		Vardefine::playOn=false;
    		Vardefine::playAgain=true;
    		//再次播放后置为初始的暂停
    		SetDlgItemText(IDC_BUTTON2,"暂停");
    		//置当前播放帧数为1
    		Vardefine::frameNum=1;
    		//调用视频播放方法
    	    playVideo(Vardefine::str);
    	}
    }

    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(); //释放视频
    }
    视频总帧数以及当前帧显示已经包含在播放方法内实现了,不再赘述。


    最后显示一下播放效果:

    通过对话框选择视频文件后界面:


    点击暂停之后界面:



    点击继续播放后界面:



    播放完成:


    再次播放:



  • 相关阅读:
    【操作系统】 管程机制
    【Java】 大话数据结构(13) 查找算法(4) (散列表(哈希表))
    【操作系统】 信号量机制
    【Java】 奇偶数的判断
    【Java】 大话数据结构(12) 查找算法(3) (平衡二叉树(AVL树))
    MySQL之库操作
    数据库简介
    MySQL的知识海洋
    python并发编程之多进程(理论)
    python并发编程之多进程(实现)
  • 原文地址:https://www.cnblogs.com/mtcnn/p/9412010.html
Copyright © 2011-2022 走看看