文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>MFC中使用OpenCV捕捉摄像头视频并在Image控件中播放

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

时间:2010-06-06  来源:frostmourn716

欢迎访问我的新博客(troychengspace, http://troychengspace.appspot.com/)

在参加腾讯校园之星大赛中做了一些手势识别的插件,其中需要使用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类型的属性用来保存视频中的每一帧图像,处理的时候,使用这个图像的副本,然后再显示回去。

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

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载