9.3.4 界面设计(1)
在这个实例中我们要实现的任务是在预览视频的同时从VMR中定时捕捉图像数据,然后从ARGB32转换到YUV420(I420)格式,并保存到*.yuv文件。预览可暂停、重启。能够在不退出应用程序的情况下,终止捕捉图像。
应用VC++(www.cppentry.com) 2005应用程序向导建立对话框程序框架,项目名称为9-2。建立过程请参考8.1.3章节。
添加控件:6个Button、1个Combo Box、1个Picture Control,如表9-2所示。根据其功能修改所有控件的ID。
表9-2 控件功能列表
|
方法< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> |
说明 |
|
ID_PREVIEW |
预览视频 |
|
ID_PAUSEPLAY |
暂停/开始预览 |
|
ID_CAPTURE |
捕捉图像 |
|
ID_STOPCAP |
终止捕捉图像 |
|
ID_SAVEGRAPH |
保存滤波器链表 |
|
ID_EXITAPP |
退出程序(终止预览捕捉) |
|
IDC_LISTDEVICE |
设备列表组合框 |
|
IDC_VIDEO_WINDOW |
显示捕捉的视频图像 |
修改控件大小,重排其位置。添加控件后的主界面设计如图9-19所示。
|
| (点击查看大图)图9-19 VMR Capture主界面设计 |
控件与变量捆绑。为便于控制,把IDC_VIDEO_WINDOW控件、IDC_LISTDEVICE控件分别与变量捆绑,途径是选中控件的右键菜单中的"添加变量"命令,激活"添加成员变量向导"。添加后的代码如下。
// 显示捕获的图像 CStatic m_videoWindow; // 组合框列表,显示设备名称 CComboBox m_listCtrl; |
添加功能按钮在线提示ToolTip,添加过程请参照9.2.3的(5)步骤。功能按钮的消息响应,即单击按钮的事件处理。双击某按钮,实现单击按钮事件处理函数的添加。为了使用类CVMR_Capture的变量和函数,在应用类中CMy92Dlg引入并定义。
在类CMy92Dlg中定义成员变量。
CToolTipCtrl m_tooltip; //在线提示控件 CVMR_Capture m_VMRCap; //VMR类 ColorSpaceConversions conv; //颜色空间转换类 UINT m_timerID; //定时器ID CString m_yuvFileName; //YUV文件名 CFile m_pFile; //文件类 BOOL m_fileState; //文件状态:打开=true ,关闭=false int m_imageWidth; //图像宽度 int m_imageHeight; //图像高度 BYTE *p_yuv420; //YUV420空间
|
定义宏以为修改提供方便。
#define TIMER_ID 1 //定时器ID #define TIMER_DELAY 20 //定时器周期 #define CAMERA_WIDTH 352 //图像宽度 #define CAMERA_HEIGHT 288 //图像高度 |
对话框初始化,初始化变量。
this->m_VMRCap.EnumDevices(this->m_listCtrl); //枚举系统采集设备,设备名称添加到组合框 this->m_listCtrl.SetCurSel(0); //选择0索引的设备 m_yuvFileName = _T(""); //yuv文件名 m_fileState = FALSE; //文件当前状态 m_imageWidth = CAMERA_WIDTH; //预采集的图像宽度 m_imageHeight= CAMERA_HEIGHT; //预采集的图像高度 p_yuv420 = NULL; //YUV420数据空间
|
添加定时器消息处理函数
为了以不低于25f/s的帧率捕捉图像,使用定时器周期从VMR中读取图像数据。
void CMy92Dlg::OnTimer(UINT_PTR nIDEvent) { //TODO: 在此添加消息处理程序代码和/或调用默认值 if (nIDEvent==TIMER_ID) //定时器ID { //定时获取图像帧,转换颜色空间,写文件 if (m_fileState) //文件已经打开 { DWORD dwSize; dwSize = this->m_VMRCap.GrabFrame(); //获取图像帧数据 if (dwSize >0 ) { BYTE *pImage; this->m_VMRCap.GetFrame(&pImage); //读取图像内容 //把RGB24转换为YUV420 conv.RGB24_to_YV12(pImage,this->p_ yuv420,m_imageWidth, m_imageHeight); //写YUV420数据到文件 m_pFile.Write(p_yuv420,m_imageWidth*m_imageHeight*3/2); } } } CDialog::OnTimer(nIDEvent); } |
成员函数GrabFrame是真正地获取图像数据,而GetFrame只是获取前者保存的数据指针。为便于大部分的算法处理,进行了颜色空间转换RGB24到YUV420。该转换功能使用了经典的cscc.lib库。
添加功能按钮的单击消息处理函数。双击"预览视频"按钮,添加事件处理代码:
void CMy92Dlg::OnBnClickedPreview() { //TODO: 在此添加控件通知处理程序代码 HWND hwnd = this->m_videoWindow.GetSafeHwnd(); //获取显示窗口句柄 int id = this->m_listCtrl.GetCurSel(); //获取当前设备索引 HRESULT hr = m_VMRCap.Init(id,hwnd,m_imageWidth,m_imageHeight); //创建预览的所有任务 if (FAILED(hr)) AfxMessageBox(_T("无法创建滤波器链表!")); //创建失败 }
|
【责任编辑:
云霞 TEL:(010)68476606】