特别申明
本文装载地址:http://www.cnblogs.com/Romi/archive/2012/05/07/2487652.html
OpenCV中文网站上有讲怎么使用OpenCV读入和显示图像和视频,本文简述使用MFC显示图像和视频。
1.读取并显示图像
显示图像或视频使用VC中的Picture控件,用到VC图形设备接口的设备上下文(CDC类)。比如打开显示这样一个图片lean.jpg。先进行一些初始化工作,代码如下:
// DemoDlg.h
#include <highgui.h>
//在CDemoDlg类定义中加入如下几行
private:
CRect rect;
CStatic* pStc; //标识图像显示的Picture控件
CDC* pDC; //视频显示控件设备上下文
HDC hDC; //视频显示控件设备句柄
CvCapture* capture; //视频获取结构
//DemoDlg.cpp
#include <cv.h>
#include <highgui.h>
#include <cvaux.h>
#include <ml.h>
//在CDemoDlg构造函数内添加以下几行,指针初始化
pStc=NULL;
pDC=NULL;
capture=NULL;
//在CDemoDlg类的OnInitDialog()中添加如下几行,进行初始化
BOOL CFaceDlg::OnInitDialog()
{
//框架生成代码.......
pStc=(CStatic *)GetDlgItem(IDC_VIEW);//IDC_VIEW为Picture控件ID
pStc->GetClientRect(&rect);//将CWind类客户区的坐标点传给矩形
pDC=pStc->GetDC(); //得到Picture控件设备上下文
hDC=pDC->GetSafeHdc(); //得到控件设备上下文的句柄
return TRUE;
}
如上就将Picture控件的设备上下文句柄与图片/视频显示的矩形区域联系起来。下面显示图片,在对话框上添加一个打开按钮,点击该按钮触发读取显示图像的事件,事件响应如下:
void CDemoDlg::OnOpen()
{
IplImage * img=cvLoadImage("lena.jpg");//load image from file
CvvImage cvvImg; //CvvImage类
cvvImg.CopyOf(img);//复制图像到当前的CvvImage对象中
cvvImg.DrawToHDC(hDC,&rect); //绘制图像的ROI区域到DC的rect
}
2.读取并显示视频
因为视频时一帧一帧的图像,因此显示视频可以理解为间断地读取并显示不同帧的图像。这里有一个要点,为了合理利用资源,尽量不要使用一个死循环一直读取视频中的帧数据,应该根据视频的帧率设置合适的时钟,定时地对视频中的帧图像进行读取显示。因为帧率通常很低,所以显示的每一帧图像看起来就会使连续的。
初始化工作同上面的图像读取显示一样,所不同的是CDemoDlg::OnOpen()事件响应函数中的代码有区别,如下:
void CDemoDlg::OnOpen()
{
if (!capture)
{
capture=cvCaptureFromAVI("D://OtherUse//11.avi"); //初始化一个视频文件捕捉器
}
if(!capture)
{
AfxMessageBox("无法获得摄像头");
return;
}
SetTimer(1,25,NULL); //定时器,定时时间和帧率一致
}
然后设置时间响应,定时到达后,处理OnTimer(UINT nIDEvent)事件,视频显示在这里面完成。
void CDemoDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if(1==nIDEvent)
{
IplImage* img=0;
img=cvQueryFrame(capture); //从摄像头或者文件中抓取并返回一帧
//cvGrabFrame( capture ); //从摄像头或者视频文件中抓取帧
//img=cvRetrieveFrame(capture); //取回由函数cvGrabFrame抓取的图像
CvvImage m_CvvImage;
m_CvvImage.CopyOf(img,1); //复制该帧图像
m_CvvImage.DrawToHDC(hDC, &rect); //显示到设备的矩形框内
}
CDialog::OnTimer(nIDEvent);