基于OpenCV 、VS2008 MFC对话框的USB摄像头的控制和视频播放、跟踪(logitech sphere AF网络摄像头)
2010-01-18 17:29
549 查看
基于OpenCV 、VS2008 MFC对话框的USB摄像头的控制和视频播放、跟踪(logitech sphere AF网络摄像头)
1.opencv
2.vs2008 mfc
3.logitech sphere AF网络摄像头的pan tilt zoom控制
4.SIR粒子滤波
我已经做完了,总结完后上传。
草稿
PTZ
(Pan, Tilt, Zoom
)摄像机跟踪指图像工作站通过对摄像头所获取的视频图像序列处理,对运动目标进行检测、分割和跟踪,将得到的目标偏离视场中心的偏差值反馈给云台,控制其全方位转动,实现摄像机对目标的同步跟踪。
1.
界面设计
基于
Visual Studio 2008
的
MFC
技术,
在对话框GUI
界面,往里面添加若干Button
和一个Picture
控件,如图
图2.1 GUI
界面
各个控件的ID
号由Visual C++
自动产生并存放于Resource.h
文件中,比如其中一句定义:
#define IDC_ShowImg
1002
定义了图片控件的ID
号,由图片控件显示图片时只需要使用如下命令:
CDC* pDC = GetDlgItem( IDC_ShowImg)->GetDC();//
获得显示控件的DC
HDC hDC = pDC->GetSafeHdc();
//
获取HDC(
设备句柄)
来进行绘图操作
img.DrawToHDC( hDC, &rect );
//
将图片绘制到显示控件的指定区域内
同时,为了实时显示各种参数,创建了状态栏。
HWND hStatusWindow;
HWND hDlg=GetSafeHwnd();
int IDS_STATUS =1;
hStatusWindow=CreateStatusWindow(WS_CHILD|WS_VISIBLE|WS_BORDER,TEXT("
状态栏"),hDlg, IDS_STATUS);
int pint[4]={110,250,300,-1};//110,250,300
设定间隔
::SendMessage(hStatusWindow,SB_SETPARTS,4,(LPARAM)pint);
在状态栏中,将不断显示水平、垂直转动的角度和焦距变化值,这样可以使用户在使用系统的过程中得到一些关心的准确数据。
2.
人脸检测
人脸检测方法是一种基于积分图、级联检测器和AdaBoost
算法的方法,方法框架可以分为以下三大部分
:
第一部分,使用Harr-llke
特征表示人脸,使用“积分图’’实现特征数值的快速计算;
第二部分,使用Adaboost
算法挑选出一些最能代表人脸的矩形特征(
弱分类器)
,按照加权投票的方式将弱分类器构造为一个强分类器:
第三部分,将训练得到的若干强分类器串联组成一个级联结构的层叠分类器,级联结构能有效地提高分类器的检测速度。
基于AdaBoost
的人脸检测在OpenCV
中的具体实现步骤如图2.2
。
图 2.2 OpenCV2.0
实现人脸检测的基本步骤
1)
加载分类器。利用以下语句实现分类器的加载。
static CvHaarClassifierCascade* cascade = 0;
const char* cascade_name ="haarcascade_frontalface_alt.xml";
cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
2)
同时,0penCV
在加载的时候将分类器转化成了内部格式。加载检测图像。在本检测中,首先将3
通道8
位的彩色图转为灰度图,然后将灰度图按缩小1.3
倍。
cvCvtColor( img, gray, CV_BGR2GRAY );//
将彩色图转化为灰度图
cvResize( gray, small_img, CV_INTER_LINEAR );//
将灰度图缩小
3)
检测人脸。通过以下函数实现人脸检测
vSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
1.1, 2, 0/*CV_HAAR_DO_CANNY_PRUNING*/,cvSize(30, 30) );
通过以下函数得到脸部坐标:
CvRect r = (CvRect*)cvGetSeqElem( faces,0);
图 2.3
人脸检测效果图
3.
基于多线程的视频文件播放
在多线程方法中,同一进程内所有线程共享惟一的进程地址空间资源,线程间共用内存空间、寄存器、进程表项等,不存在通过第三方进行信息交换的问题;而线程内部也能通过线程数据槽等方法实现各自的变量存储,所以多线程技术是并发程序设计方式中最为简单的一种,是首选工具。
在未采用多线程前,单击Capture
按钮,视频播放的过程中整个GUI
界面将失去消息响应,因为视频播放是一个死循环的过程。为了解决这个问题,本系统采用多线程技术,实现了视频播放与主程序的独立。
在Button
控件Capture
下添加了void CmymfcDlg::OnBnClickedReadimg()
按钮点击的消息响应程序,在程序中添加如下代码:
CreateThread(NULL,0,CaptureThread,Capture_param,0,NULL);
创建了一个线程,线程函数为C
aptureThread
,传入参数为Capture_param
。在
DWORD WINAPI CaptureThread(LPVOID pParam)
函数中,实现了每帧视频的读取和粒子滤波的循环。
4.
基于OpenCV 2.0
的视频文件读取
OpenCV
是一种用于数字图像处理和计算机视觉的函数库。它由英特尔公司开发,是一套可免费获得的由一些C
函数和C++
类所组成的库。OpenCV
在Windows
系统及Linux
系统下都可以使用,它提供了很多标准的图像处理算法,主要用于对图像进行一些高级处理。这些函数可以直接在具体的视频开发项目中调用,通过简单编程即可完成十分复杂庞大的开发任务,具有很好的效率。
CvCapture* pCapture;
pCapture = cvCaptureFromCAM(0)
;
IplImage* ipl=NULL;
ipl = cvQueryFrame( Capture_param->plistener->pCapture );
通过以上代码实现了从摄像头读取每帧图片。由于图片控件的大小是276
×276
,需要对摄像头采集的图像进行缩放。摄像头采集的图像大小是320
×240
,上下添加黑边至320
×320,
然后进行256/320
的缩放。
cvSetImageROI( TheImage, cvRect( tlx, tly, nw, nh) );
cvResize( img, TheImage );
cvResetImageROI( TheImage );
通过OpenCV
设置感兴趣区域ROI
进行缩放,
可以很方便地实现图片以合适尺寸显示。
5.
PTZ
摄像头的控制
在PTZ.CPP
文件中,主要通过如下函数实现摄像头的控制。
HRESULT set_mechanical_pan_relative(IAMCameraControl *pCameraControl, long value);
HRESULT set_mechanical_tilt_relative(IAMCameraControl *pCameraControl, long value);
以上两个函数,实现了摄像头的水平和垂直转动,输入参数分别为摄像头的ID
号和转动角度。
HRESULT set_digital_zoom_absolute(IAMCameraControl *pCameraControl, long value);
这个函数实现了摄像头的放大缩小倍数。
在Logitech
此款摄像头中,焦距的变化范围从50mm
到200mm
。函数传入的value
即设置的焦距值
。这样可以看到,此摄像头最大的放大倍数是4
倍。
6.
粒子滤波程序的实现
在Button
控件track
下添加了void CmymfcDlg:: OnBnClickedTrace ()
按钮点击的消息响应程序,在程序中添加如下代码:
if(initPFTracking((PixelsInfor *)ImageSource->imageData,
&TrackLocation,
&goalFeatuerStuctAdr,
&G_MAIN_ParticlesAdr,
G_MAIN_PARNUMBER)!=0)
{
AfxMessageBox("SIR initialization error!");
}
启动粒子滤波程序。
其中TrackLocation
为目标位置,本系统由两种方式输入。
a)
由鼠标响应事件产生
在GUI
界面中,添加如下消息响应事件
void CmymfcDlg::OnLButtonDown(UINT nFlags, CPoint point)
void CmymfcDlg::OnLButtonUp(UINT nFlags, CPoint point)
由鼠标画框事件,记录下目标的坐标,再传给粒子滤波初始化程序。
b)
由AdaBoost
人脸检测程序的返回值确定。
人脸检测程序可以返回检测结果,通过一定的换算后可以得到目标位置,然后传递给粒子滤波程序,实现了人脸的自动检测和跟踪。
当初始化完成后,将粒子滤波的初始化完成标志位注为真,然后每帧图像显示前调用如下函数进行持续跟踪并返回位置坐标,画框程序根据位置坐标不断进行标注。
if(oncePFTracking((PixelsInfor *)(ImageSource->imageData),
Capture_param->plistener->G_MAIN_ParticlesAdr,
G_MAIN_PARNUMBER,
Capture_param->plistener->goalFeatuerStuctAdr,
&Capture_param->plistener->TrackLocation)!=0)
{
AfxMessageBox("tracking code error!");}
四
总结
本系统在VS2008
下开发环境下,开发出了基于MFC
对话框的人机交互界面,使用OpenCV 2.0
函数库和多线程技术,在流畅播放视频的同时,能进行基于用户操作的Logitech USB
摄像头的PTZ
控制,能自动运行基于Adaboost
的人脸检测并具有非常高的准确性,能提供两种目标输入模式的粒子滤波程序的人脸跟踪,并能根据跟踪结果对摄像头进行水平、垂直控制,使跟踪实现了水平360
,
垂直90
的跟踪效果。
本系统只是完成了水平和垂直的转动跟踪,没有使云台根据转动参数实现目标跟踪过程中的自动镜头缩放,这个是下一步需要继续深入下去的工作。
五 部分代码
回答一个朋友的问题
1.怎么交换数据?
在窗体初始化的时候,创建守护线程,在守护线程中不断获取图像,并通过MFC显示。通过函数调用传递参数,不会产生延时。
以下代码是Capture_param的定义
以下是显示代码
1.opencv
2.vs2008 mfc
3.logitech sphere AF网络摄像头的pan tilt zoom控制
4.SIR粒子滤波
我已经做完了,总结完后上传。
草稿
PTZ
(Pan, Tilt, Zoom
)摄像机跟踪指图像工作站通过对摄像头所获取的视频图像序列处理,对运动目标进行检测、分割和跟踪,将得到的目标偏离视场中心的偏差值反馈给云台,控制其全方位转动,实现摄像机对目标的同步跟踪。
1.
界面设计
基于
Visual Studio 2008
的
MFC
技术,
在对话框GUI
界面,往里面添加若干Button
和一个Picture
控件,如图
图2.1 GUI
界面
各个控件的ID
号由Visual C++
自动产生并存放于Resource.h
文件中,比如其中一句定义:
#define IDC_ShowImg
1002
定义了图片控件的ID
号,由图片控件显示图片时只需要使用如下命令:
CDC* pDC = GetDlgItem( IDC_ShowImg)->GetDC();//
获得显示控件的DC
HDC hDC = pDC->GetSafeHdc();
//
获取HDC(
设备句柄)
来进行绘图操作
img.DrawToHDC( hDC, &rect );
//
将图片绘制到显示控件的指定区域内
同时,为了实时显示各种参数,创建了状态栏。
HWND hStatusWindow;
HWND hDlg=GetSafeHwnd();
int IDS_STATUS =1;
hStatusWindow=CreateStatusWindow(WS_CHILD|WS_VISIBLE|WS_BORDER,TEXT("
状态栏"),hDlg, IDS_STATUS);
int pint[4]={110,250,300,-1};//110,250,300
设定间隔
::SendMessage(hStatusWindow,SB_SETPARTS,4,(LPARAM)pint);
在状态栏中,将不断显示水平、垂直转动的角度和焦距变化值,这样可以使用户在使用系统的过程中得到一些关心的准确数据。
2.
人脸检测
人脸检测方法是一种基于积分图、级联检测器和AdaBoost
算法的方法,方法框架可以分为以下三大部分
:
第一部分,使用Harr-llke
特征表示人脸,使用“积分图’’实现特征数值的快速计算;
第二部分,使用Adaboost
算法挑选出一些最能代表人脸的矩形特征(
弱分类器)
,按照加权投票的方式将弱分类器构造为一个强分类器:
第三部分,将训练得到的若干强分类器串联组成一个级联结构的层叠分类器,级联结构能有效地提高分类器的检测速度。
基于AdaBoost
的人脸检测在OpenCV
中的具体实现步骤如图2.2
。
图 2.2 OpenCV2.0
实现人脸检测的基本步骤
1)
加载分类器。利用以下语句实现分类器的加载。
static CvHaarClassifierCascade* cascade = 0;
const char* cascade_name ="haarcascade_frontalface_alt.xml";
cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
2)
同时,0penCV
在加载的时候将分类器转化成了内部格式。加载检测图像。在本检测中,首先将3
通道8
位的彩色图转为灰度图,然后将灰度图按缩小1.3
倍。
cvCvtColor( img, gray, CV_BGR2GRAY );//
将彩色图转化为灰度图
cvResize( gray, small_img, CV_INTER_LINEAR );//
将灰度图缩小
3)
检测人脸。通过以下函数实现人脸检测
vSeq* faces = cvHaarDetectObjects( small_img, cascade, storage,
1.1, 2, 0/*CV_HAAR_DO_CANNY_PRUNING*/,cvSize(30, 30) );
通过以下函数得到脸部坐标:
CvRect r = (CvRect*)cvGetSeqElem( faces,0);
图 2.3
人脸检测效果图
3.
基于多线程的视频文件播放
在多线程方法中,同一进程内所有线程共享惟一的进程地址空间资源,线程间共用内存空间、寄存器、进程表项等,不存在通过第三方进行信息交换的问题;而线程内部也能通过线程数据槽等方法实现各自的变量存储,所以多线程技术是并发程序设计方式中最为简单的一种,是首选工具。
在未采用多线程前,单击Capture
按钮,视频播放的过程中整个GUI
界面将失去消息响应,因为视频播放是一个死循环的过程。为了解决这个问题,本系统采用多线程技术,实现了视频播放与主程序的独立。
在Button
控件Capture
下添加了void CmymfcDlg::OnBnClickedReadimg()
按钮点击的消息响应程序,在程序中添加如下代码:
CreateThread(NULL,0,CaptureThread,Capture_param,0,NULL);
创建了一个线程,线程函数为C
aptureThread
,传入参数为Capture_param
。在
DWORD WINAPI CaptureThread(LPVOID pParam)
函数中,实现了每帧视频的读取和粒子滤波的循环。
4.
基于OpenCV 2.0
的视频文件读取
OpenCV
是一种用于数字图像处理和计算机视觉的函数库。它由英特尔公司开发,是一套可免费获得的由一些C
函数和C++
类所组成的库。OpenCV
在Windows
系统及Linux
系统下都可以使用,它提供了很多标准的图像处理算法,主要用于对图像进行一些高级处理。这些函数可以直接在具体的视频开发项目中调用,通过简单编程即可完成十分复杂庞大的开发任务,具有很好的效率。
CvCapture* pCapture;
pCapture = cvCaptureFromCAM(0)
;
IplImage* ipl=NULL;
ipl = cvQueryFrame( Capture_param->plistener->pCapture );
通过以上代码实现了从摄像头读取每帧图片。由于图片控件的大小是276
×276
,需要对摄像头采集的图像进行缩放。摄像头采集的图像大小是320
×240
,上下添加黑边至320
×320,
然后进行256/320
的缩放。
cvSetImageROI( TheImage, cvRect( tlx, tly, nw, nh) );
cvResize( img, TheImage );
cvResetImageROI( TheImage );
通过OpenCV
设置感兴趣区域ROI
进行缩放,
可以很方便地实现图片以合适尺寸显示。
5.
PTZ
摄像头的控制
在PTZ.CPP
文件中,主要通过如下函数实现摄像头的控制。
HRESULT set_mechanical_pan_relative(IAMCameraControl *pCameraControl, long value);
HRESULT set_mechanical_tilt_relative(IAMCameraControl *pCameraControl, long value);
以上两个函数,实现了摄像头的水平和垂直转动,输入参数分别为摄像头的ID
号和转动角度。
HRESULT set_digital_zoom_absolute(IAMCameraControl *pCameraControl, long value);
这个函数实现了摄像头的放大缩小倍数。
在Logitech
此款摄像头中,焦距的变化范围从50mm
到200mm
。函数传入的value
即设置的焦距值
。这样可以看到,此摄像头最大的放大倍数是4
倍。
6.
粒子滤波程序的实现
在Button
控件track
下添加了void CmymfcDlg:: OnBnClickedTrace ()
按钮点击的消息响应程序,在程序中添加如下代码:
if(initPFTracking((PixelsInfor *)ImageSource->imageData,
&TrackLocation,
&goalFeatuerStuctAdr,
&G_MAIN_ParticlesAdr,
G_MAIN_PARNUMBER)!=0)
{
AfxMessageBox("SIR initialization error!");
}
启动粒子滤波程序。
其中TrackLocation
为目标位置,本系统由两种方式输入。
a)
由鼠标响应事件产生
在GUI
界面中,添加如下消息响应事件
void CmymfcDlg::OnLButtonDown(UINT nFlags, CPoint point)
void CmymfcDlg::OnLButtonUp(UINT nFlags, CPoint point)
由鼠标画框事件,记录下目标的坐标,再传给粒子滤波初始化程序。
b)
由AdaBoost
人脸检测程序的返回值确定。
人脸检测程序可以返回检测结果,通过一定的换算后可以得到目标位置,然后传递给粒子滤波程序,实现了人脸的自动检测和跟踪。
当初始化完成后,将粒子滤波的初始化完成标志位注为真,然后每帧图像显示前调用如下函数进行持续跟踪并返回位置坐标,画框程序根据位置坐标不断进行标注。
if(oncePFTracking((PixelsInfor *)(ImageSource->imageData),
Capture_param->plistener->G_MAIN_ParticlesAdr,
G_MAIN_PARNUMBER,
Capture_param->plistener->goalFeatuerStuctAdr,
&Capture_param->plistener->TrackLocation)!=0)
{
AfxMessageBox("tracking code error!");}
四
总结
本系统在VS2008
下开发环境下,开发出了基于MFC
对话框的人机交互界面,使用OpenCV 2.0
函数库和多线程技术,在流畅播放视频的同时,能进行基于用户操作的Logitech USB
摄像头的PTZ
控制,能自动运行基于Adaboost
的人脸检测并具有非常高的准确性,能提供两种目标输入模式的粒子滤波程序的人脸跟踪,并能根据跟踪结果对摄像头进行水平、垂直控制,使跟踪实现了水平360
,
垂直90
的跟踪效果。
本系统只是完成了水平和垂直的转动跟踪,没有使云台根据转动参数实现目标跟踪过程中的自动镜头缩放,这个是下一步需要继续深入下去的工作。
五 部分代码
回答一个朋友的问题
1.怎么交换数据?
在窗体初始化的时候,创建守护线程,在守护线程中不断获取图像,并通过MFC显示。通过函数调用传递参数,不会产生延时。
以下代码是Capture_param的定义
typedef struct _tag_SOCKET_LISTEN_PARAM { CmymfcDlg* plistener; }SOCKETLISTENPARAM; SOCKETLISTENPARAM *Capture_param=(SOCKETLISTENPARAM*)pParam;
以下是显示代码
void CmymfcDlg::ShowImage( IplImage* img, UINT ID ) // ID 是Picture Control控件的ID号 { CDC* pDC = GetDlgItem( ID ) ->GetDC(); // 获得显示控件的 DC HDC hDC = pDC ->GetSafeHdc(); // 获取 HDC(设备句柄) 来进行绘图操作 CRect rect,rect2; ((CStatic*)GetDlgItem(ID))->GetWindowRect(&rect2); GetDlgItem(ID) ->GetClientRect( &rect ); int rw = rect.right - rect.left; // 求出图片控件的宽和高 int rh = rect.bottom - rect.top; int iw = img->width; // 读取图片的宽和高 int ih = img->height; tx = (int)(rw - iw)/2; // 使图片的显示位置正好在控件的正中 ty = (int)(rh - ih)/2; SetRect( rect, tx, ty, tx+iw, ty+ih ); if(TraceFlag==FALSE) DrawFrame(img,TraceLocation); CvvImage cimg; cimg.CopyOf( img ); // 复制图片 cimg.DrawToHDC( hDC, &rect ); // 将图片绘制到显示控件的指定区域内 cvWaitKey(50); ReleaseDC( pDC ); }
相关文章推荐
- opencv [c++版] 学习笔记(2) 在MFC基于对话框界面上播放视频
- OpenCV学习笔记(9)利用MFC的Picture控件显示图像+播放视频和捕获摄像头画面
- OpenCV学习笔记(9)利用MFC的Picture控件显示图像+播放视频和捕获摄像头画面
- (转载)MFC中使用OpenCV捕捉摄像头视频并在Image控件中播放
- 基于MFC对话框的摄像头跟踪
- OpenCV学习 利用MFC的Picture控件显示图像+播放视频和捕获摄像头画面
- 基于opencv与MFC的视频播放。
- opencv +MFC实现视频播放、暂停、视频标注、跟踪
- OpenCV学习笔记 利用MFC的Picture控件显示图像+播放视频和捕获摄像头画面 .
- VLC播放摄像头或者网络摄像头通过rtsp流读取视频
- 使用Opencv添加一个进度条来控制视频播放
- VS2010MFC对话框程序中使用Windows Media Player播放音频或视频文件
- [学习OpenCV攻略][005][视频播放控制]
- QT框架中快速应用OpenCV——基于视频播放
- OpenCV视频播放控制
- 1.0.1-学习Opencv与MFC混合编程之---播放AVI视频
- vs2008中,创建基于对话框的mfc动态库步骤
- 【OpenCV】视频读入、播放控制和写入
- 基于opencv调用USB摄像头拍照
- 视频运动目标跟踪,基于opencv , vc++