加载中…
个人资料
南冠彤
南冠彤
  • 博客等级:
  • 博客积分:0
  • 博客访问:415,028
  • 关注人气:59
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

(转)MFC中使用OpenCV捕捉摄像头视频并在Image控件中播放

(2011-11-01 09:40:55)
标签:

杂谈

分类: DirectShow

转载:http://troychengspace.appspot.com/2010/06/6/harvest4.html

感谢作者!如有侵权请留言hun_hun@yeah.net,即刻删除!

 

在参加腾讯校园之星大赛中做了一些手势识别的插件,其中需要使用OpenCV相关的东西,今天将它整理一下,希望对其他人能有所帮助。

首先,OpenCV 2.1似乎不能获取设想设备的数目,名称以及其它相关属性,在实际应用中很不方便,为了解决这个问题,OpenCV论坛上YuShiQi老师给出了一个风转好的CameraDS类,通过Directshow来调用摄像头(详情请见http://www.opencv.org.cn/index.php/使用DirectShow采集图像),不过,这个类只在VC++6.0编译下通过,对于VS2005、2008和2010,需要做相应的设置,如下:

 

1、在CameraDS.h包含头文件之上预先定义加入如下代码

#define POINTER_64 __ptr64

2、将project ->Property-> c++ ->general->Additional Include Directories 的DirectShow/Include挪到tools->options->project and solutions->vc++ Directories->include files的文件末尾就可以了,当然也可以换成绝对目录。

问题解决后,就可以在vs2005,vs2008上编译该工程了

其次,捕捉到了视频,还需要将它显示在Image控件上,这里就没有OpenCV自身所使用的UI控件那么方便了,需要自己定义Timer函数来重复调用,过程如下:

 

        //打开该摄像头之前,因先检查之前是否在进行图像捕捉,若有,关闭
        ReleaseCapture();
      //打开摄像头
        if(!camera.OpenCamera(sgCurSelCameraIndex,false,FRAME_WIDTH,FRAME_HEIGHT))//这里使用CameraDS中的方法打开摄像头
      {
              MessageBox(_T("打开视频设备"+sgCameraName+"失败,请检查设备状态"),_T("SmartGesture插件信息"), MB_OK | MB_ICONEXCLAMATION);
 }
      SetTimer(status,30,NULL);//关键是这里,需要自己定义Timer函数去反复读取图像并将它显示出来,处理的代码会在OnTimer函数中出现

 

SetTimer函数第一个参数是Timer的标识ID,也就是下面出现的nIDEvent。可以根据不同的ID调用不同的OnTimer函数,第二个参 数是调用的时间间隔,单位是ms,第三个回调函数,这里在下面的OnTimer函数中定义。接下来再来看OnTimer函数:

 

//定时器,用于定期查询摄像头并获得相应的帧并进行处理
void SmartGestureDlg::OnTimer(UINT_PTR nIDEvent)
{
       // TODO: 在此添加消息处理程序代码和/或调用默认值
      sgFrame = camera.QueryFrame();//从摄像头获得IplImage类型的图片
        //依据事件类型对捕捉的图像进行不同的处理
      switch (nIDEvent)
      {
      case SG_NORMAL://正常捕捉状态下对帧不做处理
             cvFlip(sgFrame,sgFrame,1);
             break;
 case SG_TRACING://跟踪状态
             SGTrace(sgFrame);//跟踪状态下对帧进行追踪处理
           break;
 case SG_SETTING://设置状态
             SGSet(sgFrame);//设置状态下对图像进行设置处理
            break;
 }
      //将IplImage类型的图片转换成MFC能显示的图片格式,其中sgImage的声明为:CvvImage sgImage,sgFrame的声明为IplImage*
 sgImage.CopyOf(sgFrame,3);
     //指定绘图所需的Picture控件
 HDC sgIDCPicture = (GetDlgItem(IDC_FRAME)->GetDC())->GetSafeHdc();//从MFC的界面上获取Image控件,控件ID为IDC_FRAME
 CRect rect;
    GetDlgItem(IDC_FRAME)->GetClientRect(&rect);
    //将图片显示到MFC的Picture控件上
     sgImage.DrawToHDC(sgIDCPicture,&rect);
 ::ReleaseDC(this->m_hWnd,sgIDCPicture);//一定要记住释放DC,否则会造成内存泄露
 __super::OnTimer(nIDEvent);//重新调用OnTimer函数
}

 

另外需要注意,如果有多个状态并调用了多个OnTimer函数,在状态转变的时候,或者是重新打开摄像头的时候,一定记住要Kill掉之前的Timer, 否则会造成画面的闪烁,之后导致应用假死。如果不能有效的记录Timer的ID,那就一次将所有的Timer全部Kill,然后重新调用,如下:

 

//退出插件之前需要释放相应的资源
void SmartGestureDlg::ReleaseCapture(){
       
for (int i = 0; i < TEMPLATE_COUNT; i++){
             KillTimer(i);
}
        camera.CloseCamera();
}

最后稍微提一下,使用CameraDS读取到的视频图像时ImlImage类型的,这个可以使用OpenCV的函数处理,在显示的时候,使用的是 CvvImage类型的,需要注意,可以在类中定义一个ImlImage类型的属性用来保存视频中的每一帧图像,处理的时候,使用这个图像的副本,然后再 显示回去。

这一部分基本就这些了,千万要注意内存泄露的问题,手动申请的一定要手动释放,创建局部变量的时候也要想一想是否会造成内存泄露,三思而后编码。

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有