MFC视频播放器制作(OpenCV)

界面效果:


-----------------------------------------------------------------------------------------------------------------

工程源代码下载地址:http://download.csdn.net/detail/luoshixian099/9257633


1.新建一个MFC工程,工程名VideoPlayer,选择使用静态库(方便以后的在其他的电脑上也能打开此软件),添加控件如上图所示。

修改控件的属性:

Picture控件ID--->IDC_VIEW;

滑动条控件 --->为此控件绑定一个CSliderCtrl类对象Slider。为了得到拖动滑动条可以到达“快进”和“快退”的效果。



2.首先需要OpenCV里面的CvvImage类,如果版本低于OpencCV2.2,可以直接调用这个类,如果高于此版本,需要重新定义这个类。CvvImage.cpp与CvvImage.h源代码见文章最后,把两个文件加入到工程中即可。

在VideoPlayerDlg.h文件中加入头文件和定义变量

[cpp]  view plain  copy
 print ?
  1. #include "opencv2/highgui/highgui.hpp"  
  2. #include "CvvImage.h"  
  3. #include "afxcmn.h"  
  4. using namespace cv;  
  5.   
  6. // CVideoPlayerDlg 对话框  
  7. class CVideoPlayerDlg : public CDialog  
  8. {  
  9.     ....  
  10.     //添加代码  
  11.     VideoCapture capture;  
  12.     HBITMAP hbitmap;  
  13.     CRect rect;  
  14.     CStatic* pStc; //标识图像显示的Picture控件  
  15.     CDC* pDC; //视频显示控件设备上下文  
  16.     HDC hDC; //视频显示控件设备句柄  
  17.   
  18. };  

3.添加一副位图资源,用于界面美观;


4.在窗口初始化函数CVideoPlayerDlg::OnInitDialog()中添加代码如下:

[cpp]  view plain  copy
 print ?
  1. // TODO: 在此添加额外的初始化代码  
  2.   
  3. pStc=(CStatic *)GetDlgItem(IDC_VIEW);//IDC_VIEW为Picture控件ID  
  4. pStc->GetClientRect(&rect);//Picture的大小传给矩形rect  
  5. pDC=pStc->GetDC(); //得到Picture控件设备上下文  
  6. hDC=pDC->GetSafeHdc(); //得到Picture控件设备上下文的句柄   
  7. hbitmap = ::LoadBitmap(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDB_BITMAP1));//加载位图资源  
  8. pStc->ModifyStyle(1,SS_BITMAP);//修改控件的属性  
  9. pStc->SetBitmap(hbitmap);//显示位图  

5.双击“打开视频”按钮,为其添加响应函数

[cpp]  view plain  copy
 print ?
  1. void CVideoPlayerDlg::OnBnClickedButton1()  
  2. {  
  3.     CString caption;  
  4.     GetDlgItemText(IDC_BUTTON1,caption);  
  5.     if (caption == _T("关闭视频"))    //关闭视频按钮  
  6.     {  
  7.         KillTimer(1);  
  8.         capture.release();  
  9.         SetDlgItemText(IDC_BUTTON1,_T("打开视频"));  
  10.         ((CSliderCtrl *)GetDlgItem(IDC_SLIDER1))->EnableWindow(FALSE);  //滑动条失效  
  11.         ((CSliderCtrl *)GetDlgItem(IDC_SLIDER1))->SetPos(0); //设置滑动条位置  
  12.         pStc->SetBitmap(hbitmap); //恢复位图资源  
  13.         return;  
  14.     }  
  15.      
  16.   
  17.  //打开视频,弹出通用对话框,选择要播放的视频文件  
  18.     string _Path;    
  19.     CFileDialog Openfiledlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, _T("Video Files (*.rmvb;*.avi)|*.rmvb;*.avi||"));  
  20.     if (Openfiledlg.DoModal() == IDOK) //弹出模态对话框  
  21.     {  
  22.         //CString类型转换为string类型  
  23.         CString  filepath;        
  24.         filepath=Openfiledlg.GetPathName();  
  25.         CStringA temp(filepath.GetBuffer(0));  
  26.         filepath.ReleaseBuffer();  
  27.         _Path = temp.GetBuffer(0);  
  28.         temp.ReleaseBuffer();  
  29.     }  
  30.     else  
  31.         return ;  
  32.       
  33.   
  34.     capture.open(_Path);  //打开视频  
  35.     if (!capture.isOpened())  
  36.     {          
  37.         MessageBox(_T("无法打开视频!"),_T("错误"));       
  38.         return;  
  39.     }  
  40.     else  
  41.     {  
  42.         ((CSliderCtrl *)GetDlgItem(IDC_SLIDER1))->EnableWindow(TRUE);  //激活滑动条  
  43.         Slider.SetRange(0,(int)capture.get(CV_CAP_PROP_FRAME_COUNT));//设置滑动条的范围,为视频的总帧数  
  44.         SetTimer(1,(unsigned int)(1000*1.0/capture.get(CV_CAP_PROP_FPS)),NULL); //定时器,定时时间和帧率一致  
  45.         SetDlgItemText(IDC_BUTTON1,_T("关闭视频"));//修改按钮的Caption  
  46.     }  
  47. }  
注意到要使用MFC中的CFileDialog类,用来弹出通用对话框,效果如下:


关于CFileDialog类的构造方法,可以参考MSDN



6.为主对话框添加定时器响应函数;

右击主对话框->属性->Messages->WM_TIMER


添加代码如下:

[cpp]  view plain  copy
 print ?
  1. void CVideoPlayerDlg::OnTimer(UINT_PTR nIDEvent)  
  2. {  
  3.     if(1 == nIDEvent)  
  4.     {  
  5.         Mat img;  
  6.         capture>>img;  //取出一帧图像  
  7.         if (img.empty())   
  8.         {  
  9.             KillTimer(1);  
  10.             MessageBox(_T("视频结束"),_T("提示"));  
  11.             capture.release();  
  12.         }  
  13.         else  
  14.         {  
  15.             CvvImage m_CvvImage;      
  16.             IplImage frame(img);   //Mat 转IplImage  
  17.             m_CvvImage.CopyOf(&frame,1); //复制该帧图像     
  18.             m_CvvImage.DrawToHDC(hDC, &rect); //显示到设备的矩形框内  
  19.             Slider.SetPos( (int)capture.get(CV_CAP_PROP_POS_FRAMES));//设置视频的位置  
  20.         }  
  21.     }  
  22.     CDialog::OnTimer(nIDEvent);  
  23. }  

7.双击“滑动控件”为其添加响应函数,以到达“快进”和“快退”的效果

[cpp]  view plain  copy
 print ?
  1. void CVideoPlayerDlg::OnNMCustomdrawSlider1(NMHDR *pNMHDR, LRESULT *pResult)  
  2. {  
  3.     LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);  
  4.     // TODO: Add your control notification handler code here  
  5.    capture.set(CV_CAP_PROP_POS_FRAMES,Slider.GetPos());  //设置视频的起始帧  
  6.     *pResult = 0;  
  7. }  

8.编译运行,效果



------------------------------------------------------------------------------------

[cpp]  view plain  copy
 print ?
  1. //CvvImage.h  
  2.   
  3. #pragma once  
  4. #ifndef CVVIMAGE_CLASS_DEF  
  5. #define CVVIMAGE_CLASS_DEF  
  6. #include "opencv.hpp"  
  7. /* CvvImage class definition */  
  8. class  CvvImage  
  9. {  
  10. public:  
  11.     CvvImage();  
  12.     virtual ~CvvImage();  
  13.     /* Create image (BGR or grayscale) */  
  14.     virtual bool  Create( int width, int height, int bits_per_pixel, int image_origin = 0 );  
  15.     /* Load image from specified file */  
  16.     virtual bool  Load( const char* filename, int desired_color = 1 );  
  17.     /* Load rectangle from the file */  
  18.     virtual bool  LoadRect( const char* filename,  
  19.         int desired_color, CvRect r );  
  20. #if defined WIN32 || defined _WIN32  
  21.     virtual bool  LoadRect( const char* filename,  
  22.         int desired_color, RECT r )  
  23.     {  
  24.         return LoadRect( filename, desired_color,  
  25.             cvRect( r.left, r.top, r.right - r.left, r.bottom - r.top ));  
  26.     }  
  27. #endif  
  28.     /* Save entire image to specified file. */  
  29.     virtual bool  Save( const char* filename );  
  30.     /* Get copy of input image ROI */  
  31.     virtual void  CopyOf( CvvImage& image, int desired_color = -1 );  
  32.     virtual void  CopyOf( IplImage* img, int desired_color = -1 );  
  33.     IplImage* GetImage() { return m_img; };  
  34.     virtual void  Destroy(void);  
  35.     /* width and height of ROI */  
  36.     int Width() { return !m_img ? 0 : !m_img->roi ? m_img->width : m_img->roi->width; };  
  37.     int Height() { return !m_img ? 0 : !m_img->roi ? m_img->height : m_img->roi->height;};  
  38.     int Bpp() { return m_img ? (m_img->depth & 255)*m_img->nChannels : 0; };  
  39.     virtual void  Fill( int color );  
  40.     /* draw to highgui window */  
  41.     virtual void  Show( const char* window );  
  42.   
  43. #if defined WIN32 || defined _WIN32  
  44.     /* draw part of image to the specified DC */  
  45.     virtual void  Show( HDC dc, int x, int y, int width, int height,  
  46.         int from_x = 0, int from_y = 0 );  
  47.     /* draw the current image ROI to the specified rectangle of the destination DC */  
  48.     virtual void  DrawToHDC( HDC hDCDst, RECT* pDstRect );  
  49. #endif  
  50. protected:  
  51.     IplImage*  m_img;  
  52. };  
  53. typedef CvvImage CImage;  
  54. #endif  


--------------------------------------------

[cpp]  view plain  copy
 print ?
  1. //CvvImage.cpp  
  2.   
  3. #include "StdAfx.h"  
  4. #include "CvvImage.h"  
  5. //  
  6. // Construction/Destruction  
  7. //  
  8. CV_INLINE RECT NormalizeRect( RECT r );  
  9. CV_INLINE RECT NormalizeRect( RECT r )  
  10. {  
  11.     int t;  
  12.     if( r.left > r.right )  
  13.     {  
  14.         t = r.left;  
  15.         r.left = r.right;  
  16.         r.right = t;  
  17.     }  
  18.     if( r.top > r.bottom )  
  19.     {  
  20.         t = r.top;  
  21.         r.top = r.bottom;  
  22.         r.bottom = t;  
  23.     }  
  24.   
  25.     return r;  
  26. }  
  27. CV_INLINE CvRect RectToCvRect( RECT sr );  
  28. CV_INLINE CvRect RectToCvRect( RECT sr )  
  29. {  
  30.     sr = NormalizeRect( sr );  
  31.     return cvRect( sr.left, sr.top, sr.right - sr.left, sr.bottom - sr.top );  
  32. }  
  33. CV_INLINE RECT CvRectToRect( CvRect sr );  
  34. CV_INLINE RECT CvRectToRect( CvRect sr )  
  35. {  
  36.     RECT dr;  
  37.     dr.left = sr.x;  
  38.     dr.top = sr.y;  
  39.     dr.right = sr.x + sr.width;  
  40.     dr.bottom = sr.y + sr.height;  
  41.   
  42.     return dr;  
  43. }  
  44. CV_INLINE IplROI RectToROI( RECT r );  
  45. CV_INLINE IplROI RectToROI( RECT r )  
  46. {  
  47.     IplROI roi;  
  48.     r = NormalizeRect( r );  
  49.     roi.xOffset = r.left;  
  50.     roi.yOffset = r.top;  
  51.     roi.width = r.right - r.left;  
  52.     roi.height = r.bottom - r.top;  
  53.     roi.coi = 0;  
  54.   
  55.     return roi;  
  56. }  
  57. void  FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp, int origin )  
  58. {  
  59.     assert( bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32));  
  60.   
  61.     BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);  
  62.   
  63.     memset( bmih, 0, sizeof(*bmih));  
  64.     bmih->biSize = sizeof(BITMAPINFOHEADER);  
  65.     bmih->biWidth = width;  
  66.     bmih->biHeight = origin ? abs(height) : -abs(height);  
  67.     bmih->biPlanes = 1;  
  68.     bmih->biBitCount = (unsigned short)bpp;  
  69.     bmih->biCompression = BI_RGB;  
  70.     if( bpp == 8 )  
  71.     {  
  72.         RGBQUAD* palette = bmi->bmiColors;  
  73.         int i;  
  74.         for( i = 0; i < 256; i++ )  
  75.         {  
  76.             palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;  
  77.             palette[i].rgbReserved = 0;  
  78.         }  
  79.     }  
  80. }  
  81. CvvImage::CvvImage()  
  82. {  
  83.     m_img = 0;  
  84. }  
  85. void CvvImage::Destroy()  
  86. {  
  87.     cvReleaseImage( &m_img );  
  88. }  
  89. CvvImage::~CvvImage()  
  90. {  
  91.     Destroy();  
  92. }  
  93. bool  CvvImage::Create( int w, int h, int bpp, int origin )  
  94. {  
  95.     const unsigned max_img_size = 10000;  
  96.   
  97.     if( (bpp != 8 && bpp != 24 && bpp != 32) ||  
  98.         (unsigned)w >=  max_img_size || (unsigned)h >= max_img_size ||  
  99.         (origin != IPL_ORIGIN_TL && origin != IPL_ORIGIN_BL))  
  100.     {  
  101.         assert(0); // most probably, it is a programming error  
  102.         return false;  
  103.     }  
  104.     if( !m_img || Bpp() != bpp || m_img->width != w || m_img->height != h )  
  105.     {  
  106.         if( m_img && m_img->nSize == sizeof(IplImage))  
  107.             Destroy();  
  108.         /* prepare IPL header */  
  109.         m_img = cvCreateImage( cvSize( w, h ), IPL_DEPTH_8U, bpp/8 );  
  110.     }  
  111.     if( m_img )  
  112.         m_img->origin = origin == 0 ? IPL_ORIGIN_TL : IPL_ORIGIN_BL;  
  113.     return m_img != 0;  
  114. }  
  115. void  CvvImage::CopyOf( CvvImage& image, int desired_color )  
  116. {  
  117.     IplImage* img = image.GetImage();  
  118.     if( img )  
  119.     {  
  120.         CopyOf( img, desired_color );  
  121.     }  
  122. }  
  123. #define HG_IS_IMAGE(img)                                                    
  124.     ((img) != 0 && ((const IplImage*)(img))->nSize == sizeof(IplImage) && 
  125.     ((IplImage*)img)->imageData != 0) //以上三行 是一行 
  126. void  CvvImage::CopyOf( IplImage* img, int desired_color )  
  127. {  
  128.     if( HG_IS_IMAGE(img) )  
  129.     {  
  130.         int color = desired_color;  
  131.         CvSize size = cvGetSize( img );   
  132.         if( color < 0 )  
  133.             color = img->nChannels > 1;  
  134.         if( Create( size.width, size.height,  
  135.             (!color ? 1 : img->nChannels > 1 ? img->nChannels : 3)*8,  
  136.             img->origin ))  
  137.         {  
  138.             cvConvertImage( img, m_img, 0 );  
  139.         }  
  140.     }  
  141. }  
  142. bool  CvvImage::Load( const char* filename, int desired_color )  
  143. {  
  144.     IplImage* img = cvLoadImage( filename, desired_color );  
  145.     if( !img )  
  146.         return false;  
  147.   
  148.     CopyOf( img, desired_color );  
  149.     cvReleaseImage( &img );  
  150.   
  151.     return true;  
  152. }  
  153. bool  CvvImage::LoadRect( const char* filename,  
  154.                          int desired_color, CvRect r )  
  155. {  
  156.     if( r.width < 0 || r.height < 0 ) return false;  
  157.   
  158.     IplImage* img = cvLoadImage( filename, desired_color );  
  159.     if( !img )  
  160.         return false;  
  161.     if( r.width == 0 || r.height == 0 )  
  162.     {  
  163.         r.width = img->width;  
  164.         r.height = img->height;  
  165.         r.x = r.y = 0;  
  166.     }  
  167.     if( r.x > img->width || r.y > img->height ||  
  168.         r.x + r.width < 0 || r.y + r.height < 0 )  
  169.     {  
  170.         cvReleaseImage( &img );  
  171.         return false;  
  172.     }  
  173.     /* truncate r to source image */  
  174.     if( r.x < 0 )  
  175.     {  
  176.         r.width += r.x;  
  177.         r.x = 0;  
  178.     }  
  179.     if( r.y < 0 )  
  180.     {  
  181.         r.height += r.y;  
  182.         r.y = 0;  
  183.     }  
  184.     if( r.x + r.width > img->width )  
  185.         r.width = img->width - r.x;  
  186.   
  187.     if( r.y + r.height > img->height )  
  188.         r.height = img->height - r.y;  
  189.     cvSetImageROI( img, r );  
  190.     CopyOf( img, desired_color );  
  191.     cvReleaseImage( &img );  
  192.     return true;  
  193. }  
  194. bool  CvvImage::Save( const char* filename )  
  195. {  
  196.     if( !m_img )  
  197.         return false;  
  198.     cvSaveImage( filename, m_img );  
  199.     return true;  
  200. }  
  201. void  CvvImage::Show( const char* window )  
  202. {  
  203.     if( m_img )  
  204.         cvShowImage( window, m_img );  
  205. }  
  206. void  CvvImage::Show( HDC dc, int x, int y, int w, int h, int from_x, int from_y )  
  207. {  
  208.     if( m_img && m_img->depth == IPL_DEPTH_8U )  
  209.     {  
  210.         uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];  
  211.         BITMAPINFO* bmi = (BITMAPINFO*)buffer;  
  212.         int bmp_w = m_img->width, bmp_h = m_img->height;  
  213.         FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin );  
  214.         from_x = MIN( MAX( from_x, 0 ), bmp_w - 1 );  
  215.         from_y = MIN( MAX( from_y, 0 ), bmp_h - 1 );  
  216.         int sw = MAX( MIN( bmp_w - from_x, w ), 0 );  
  217.         int sh = MAX( MIN( bmp_h - from_y, h ), 0 );  
  218.         SetDIBitsToDevice(  
  219.             dc, x, y, sw, sh, from_x, from_y, from_y, sh,  
  220.             m_img->imageData + from_y*m_img->widthStep,  
  221.             bmi, DIB_RGB_COLORS );  
  222.     }  
  223. }  
  224. void  CvvImage::DrawToHDC( HDC hDCDst, RECT* pDstRect )   
  225. {  
  226.     if( pDstRect && m_img && m_img->depth == IPL_DEPTH_8U && m_img->imageData )  
  227.     {  
  228.         uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];  
  229.         BITMAPINFO* bmi = (BITMAPINFO*)buffer;  
  230.         int bmp_w = m_img->width, bmp_h = m_img->height;  
  231.         CvRect roi = cvGetImageROI( m_img );  
  232.         CvRect dst = RectToCvRect( *pDstRect );  
  233.         if( roi.width == dst.width && roi.height == dst.height )  
  234.         {  
  235.             Show( hDCDst, dst.x, dst.y, dst.width, dst.height, roi.x, roi.y );  
  236.             return;  
  237.         }  
  238.         if( roi.width > dst.width )  
  239.         {  
  240.             SetStretchBltMode(  
  241.                 hDCDst,           // handle to device context  
  242.                 HALFTONE );  
  243.         }  
  244.         else  
  245.         {  
  246.             SetStretchBltMode(  
  247.                 hDCDst,           // handle to device context  
  248.                 COLORONCOLOR );  
  249.         }  
  250.         FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin );  
  251.         ::StretchDIBits(  
  252.             hDCDst,  
  253.             dst.x, dst.y, dst.width, dst.height,  
  254.             roi.x, roi.y, roi.width, roi.height,  
  255.             m_img->imageData, bmi, DIB_RGB_COLORS, SRCCOPY );  
  256.     }  
  257. }  
  258. void  CvvImage::Fill( int color )  
  259. {  
  260.     cvSet( m_img, cvScalar(color&255,(color>>8)&255,(color>>16)&255,(color>>24)&255) );  
  261. }  
  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值