使用Opencv中matchTemplate模板匹配方法跟踪移动目标

Home / C++ MrLee 2017-2-10 4030

模板匹配是一种在图像中定位目标的方法,通过把输入图像在实际图像上逐像素点滑动,计算特征相似性,以此来判断当前滑块图像所在位置是目标图像的概率
OpenCV中,模板匹配定义了6种相似性对比方式:
CV_TM_SQDIFF 平方差匹配法:计算图像像素间的距离之和,最好的匹配是0,值越大,是目标的概率就越低。 CV_TM_CCORR 相关匹配法:一种乘法操作;数值从小到大,匹配概率越来越高。 CV_TM_CCOEFF 相关系数匹配法:从-1到1,匹配概率越来越高。 CV_TM_SQDIFF_NORMED 归一化平方差匹配 CV_TM_CCORR_NORMED 归一化相关匹配 CV_TM_CCOEFF_NORMED 归一化相关系数匹配
视频文件中移动物体的跟踪,本质上还是图像上目标跟踪,可以使用模板匹配方法,实现简单的匹配跟踪效果,只不过模板匹配要逐像素移动去匹配目标图像,计算量大,实时性差。
以下代码实现基于模板匹配的目标跟踪。通过鼠标单击在视频上画出矩形,定义需要跟踪的目标,在匹配到目标的时候,用目标图像刷新输入图像:
#include "core/core.hpp"  
#include "highgui/highgui.hpp"  
#include "imgproc/imgproc.hpp"  
#include<iostream>  
using namespace cv;  
using namespace std;  
Mat image;   //视频流
Mat imageCopy; //绘制矩形框时用来拷贝原图的图像
Mat rectImage;  //子图像
bool leftButtonDownFlag=false; //左键单击后视频暂停播放的标志位
Point originalPoint; //矩形框起点
Point processPoint; //矩形框终点
int resultRows;  //模板匹配result的行
int resultcols;  //模板匹配result的列
Mat ImageResult;  //模板匹配result
double minValue;   //模板匹配result最小值
double maxValude;   //模板匹配result最大值
Point minPoint;   //模板匹配result最小值位置
Point maxPoint;    //模板匹配result最大值位置
int frameCount=0; //帧数统计
void onMouse(int event,int x,int y,int flags ,void* ustc); //鼠标回调函数
int main(int argc,char*argv[])  
{  
	VideoCapture video(argv[1]);
	double fps=video.get(CV_CAP_PROP_FPS); //获取视频帧率
	double pauseTime=1000/fps; //两幅画面中间间隔
	namedWindow("Man",0);
	setMouseCallback("Man",onMouse);
	while(true)
	{
		if(!leftButtonDownFlag) //鼠标左键按下绘制矩形时,视频暂停播放
		{
			video>>image;
			frameCount++;   //帧数
		}
		if(!image.data||waitKey(pauseTime+30)==27)  //图像为空或Esc键按下退出播放
		{
			break;
		}
		if(rectImage.data)
		{		
			ImageResult=Mat::zeros(resultRows,resultcols,CV_32FC1);
			matchTemplate(image,rectImage,ImageResult,CV_TM_SQDIFF);  //模板匹配
			minMaxLoc(ImageResult,&minValue,&maxValude,&minPoint,&maxPoint,Mat());  //最小值最大值获取
			rectangle(image,minPoint,Point(minPoint.x+rectImage.cols,minPoint.y+rectImage.rows),Scalar(0,0,255),2);
			//更新当前模板匹配的模板
			Mat resultImage=image(Rect(minPoint,Point(minPoint.x+rectImage.cols,minPoint.y+rectImage.rows)));
			rectImage=resultImage.clone();
			//当前帧数输出到视频流
			stringstream ss;
			ss<<frameCount; 
			string h="Current frame is: ";
			string fff=h+ss.str();
			putText(image,fff,Point(50,60),CV_FONT_HERSHEY_COMPLEX_SMALL,2,Scalar(0,0,255),2);
		}
		imshow("Man",image);		
	}
	return 0;
}  
//*******************************************************************//  
//鼠标回调函数  
void onMouse(int event,int x,int y,int flags,void *ustc)  
{     
	if(event==CV_EVENT_LBUTTONDOWN)  
	{  
		leftButtonDownFlag=true; //标志位
		originalPoint=Point(x,y);  //设置左键按下点的矩形起点
		processPoint=originalPoint;
	}  
	if(event==CV_EVENT_MOUSEMOVE&&leftButtonDownFlag)  
	{  
		imageCopy=image.clone();
		processPoint=Point(x,y);
		if(originalPoint!=processPoint)
		{
			//在复制的图像上绘制矩形
			rectangle(imageCopy,originalPoint,processPoint,Scalar(0,0,255),2);
		}
		imshow("Man",imageCopy);
	}  
	if(event==CV_EVENT_LBUTTONUP)  
	{  
		leftButtonDownFlag=false; 
		Mat subImage=image(Rect(originalPoint,processPoint)); //子图像
		rectImage=subImage.clone();   
		resultRows=image.rows-rectImage.rows+1;
		resultcols=image.cols-rectImage.rows+1;
		imshow("Sub Image",rectImage);	
	}	 
} 

 
框选出的跟踪目标:


跟踪效果:

本文链接:https://www.it72.com/11782.htm

推荐阅读
最新回复 (0)
返回