环境:MFC(Visual studio 2010)
图像库:OpenCV2.4.9
Step 1:默认读者已经熟练在Visual studio 2010环境中对OpenCV2.4.9的配置。
Step 2:创建一个基于对话框类型的MFC应用程序,在资源视图中添加一个Picture控件和一个Button控件,并修改控件的ID号,使得系统运行效果如图1所示:
Step 3:通过类向导创建一个新类CVideoShow,定义如图2,创建该新类的目的是为了将对话框的Picture控件变量申明为CVideoShow类型,这样做的原因是:
(1) 在OpenCV库中为了将图像在指定窗口显示出来必然要用imshow函数,该函数的C++版本定义为:C++: void imshow(const string& winname, InputArray mat),其中第一个参数是窗口名称,第二个参数是图像数据矩阵。本文想要把图像直接显示到自定义的Picture控件窗口中,而不是通过先调用OpenCV的namedWindow创建一个新窗口,然后通过imshow来显示。因此对于本文而言只需要借助OpenCV库来获取视频流图像数据即可。此时如果当视频暂停后,窗口发生变化就会发送WM_PAINT重绘消息,那么显示到Picture控件窗口的图像就会被擦除,此时只需要在CVideoShow类中重载WM_PAINT消息处理函数OnPaint(),并在该函数中重绘图像即可。
(2) 符合模块化设计思想。
图2 类CVideoShow的定义
Step 4:将Picture控件定义为CVideoShow类型后,该类主要是在Picture控件区域上显示视频的每一帧图像。具体本文是以DIB位图形式显示(关于Windows界面显示DIB位图的方法可以参考作者的《基于MFC对话框类的那些事儿》),核心代码如下:
其中pFrameofVideo就是视频每一帧图像数据的地址指针。为了显示DIB位图还需要填充一个与DIB位图相关的位图信息数据结构体BITMAPINFO,实现如下:
Step 5:接下来就是在主对话框类中实现视频流的逐帧图像读取功能,首先通过类向导先对Picture控件变量(ID号为ID_SHOWVIDEO)定义为CVideoShow类型,如图3所示:
图 3 成员变量的设置
其次就是按钮Button控件的响应函数,Button控件的ID号为IDC_BUTTON1,消息映射宏申明为:ON_BN_CLICKED(IDC_BUTTON1, &CVideoSysDlg::OnVideoShow),其响应函数体为:
Step 6: 当单击Button按钮控件时,创建一个工作线程,视频流的播放就是在该线程中实现的。这样做的好处就是避免窗口的其他消息(比如,窗口的放大、缩小、移动等)中断视频流的播放。具体实现如下:
Step 7(小技巧):最后在关闭对话框界面时,需要先关闭已创建的工作线程,再关闭整个应用程序进程。具体做法就是重载应用程序关闭的消息响应函数OnClose():