跟一位学院的老师做SRP快一年了,老师一直要我们负责软件部分。其中软件只要是计算机视觉,在VC6.0下使用OpenCV跟踪摄像头下的一个运动物体。虽然之前也写过一个模式识别的程序,但是那次是使用模板匹配函数MatchTemplate来写的MatchTemlate函数对于不旋转的物体跟踪效果很好,我们最后写的程序跟踪的很稳定。但是现在我们要跟踪的模板是旋转的,这样就想到了使用Hu不变距的性质来实现。函数原型如下
double cvMatchShapes( const void* object1, const void* object2, int method, double parameter=0 );
MatchShapes是OpenCV提供的一个根据计算比较两张图像Hu不变距的函数,函数返回值代表相似度大小,完全相同的图像返回值是0,返回值最大是1。这可以用在在一堆照片中搜索出两张相同或相同程度最大的图像。虽然网上有很多关于这个函数匹配两张图像的程序或例子,但是还没有看到有人使用它来跟踪一个旋转的物体。一个最重要的原因是运算时间问题。比如一张1000*600的图像里根据模板搜索出位置,时间不下于半分钟,这就大大限制了它在处理视频流方面的使用。但是这一次我与同学采用的方法是继承性的跟踪搜索,由于我们摄像头下物体运动的速度不大,大概20多个像素距离,那么,我们只需要在上一次搜索出的位置四周扩大20像素这个范围上搜索即可,这样时间就大大缩短了。我们可以使用一个静态变量来存放函数 MatchShapes的返回值,假如某一帧的返回值比上一帧的返回值小则把这一次的坐标信息保留下来。
void CHuDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default IplImage *temp = cvQueryFrame( pCapture ); //抓取一帧 if(!temp) //假如是空指针,则表明播放完毕,关掉定时器并返回 { KillTimer(1); //假如播放完则停止定时器,并返回 return; } cvCvtColor(temp,src,CV_BGR2GRAY); //图像彩色变灰阶,3通道变1通道,MathchShapes匹配的图像要是灰阶 cvFlip(src); //翻转图像, if(cutok) //假如鼠标已经截好模板,则进入匹配过程 { // TODO: Add your control notification handler code here static CvRect pos; //存储匹配最相似区域 static CvRect rect; //指定剪切矩形区域的范围,以上两个变量一定要是静态的,或者是全局的 double result=1; //匹配结果,初始值为1 int i,j,imax,jmax; if(cutpoint) //只是一开始是进入 { pos.width=RoiImg->width; //RoiImg是鼠标截图的区域 pos.height=RoiImg->height; pos.x=dx*p1.x; //关于鼠标截图的一个比例系数,可以先不管 pos.y=dy*p1.y; rect.width = RoiImg->width; //rect用来代表模板逐行逐列匹配是的位置 rect.height = RoiImg->height; cutpoint=false; //下次不用进入初始化 } imax=pos.x+15+RoiImg->width; //搜索位置的终点右移15个像素 jmax=pos.y+15+RoiImg->height; //搜索位置的终点下移15个像素 for(i=(pos.x-15);i<imax;i+=1) for(j=(pos.y-15);j<jmax;j+=1) { //逐列搜索 rect.x=i; rect.y=j; cvSetImageROI(src, rect); //设置ROI区域 double matching=cvMatchShapes( src, RoiImg, 3); ///匹配 if(matching<result) //使用冒泡法保存匹配结果最小的那一次 { result=matching; pos.x=i; pos.y=j; } cvResetImageROI(src); } cvRectangle(src,cvPoint(pos.x,pos.y),cvPoint(pos.x+pos.width,pos.y+pos.height),cvScalar(222,0,192),2,8,0); //框出匹配的结果 } ShowPicture(IDC_srcp,src);转载请注明出处 http://blog.csdn.net/chenhezhuyan//显示画框以后的图像CDialog::OnTimer(nIDEvent);
}