基于mean-shift的简单目标跟踪

一、概述

作为即将踏入图像识别、目标跟踪领域的一名研究生,先从基础的学起,本文采用了经典的mean-shift算法,思路简单,实现的思路来源于一个网址:http://zhidao.baidu.com/link?url=v2PlqAHX45kjCWJUnSsZYBwHkPVCX8vp6oIZnRXV7IKG0phmuy0vwQ02_SRBgK1OLieVctpFJHR1cGoaxlDAIK,得到的跟踪结果较为勉强。


meanshift算法是一种密度函数梯度估计的非参数方法,通过迭代寻优找到概率分布的极值来定位目标。算法的步骤如下:(1)选择搜索窗(2)计算得窗口的重心(3)将窗口的重心设置在计算出的重心处(4).移动搜索窗的中心到重心,如果移动距离大于预设的固定阈值,则重复2)3)4),直到搜索窗的中心与质心间的移动距离小于预设的固定阈值,或者循环运算的次数达到某一最大值,停止计算。关于meanshift的收敛性证明可以google相关文献。


Opencv中实现该算法的函数是cvMeanShift( const CvArr* prob_image ,CvRect  window, CvTermCriteria  criteria, CvConnectedComp*  comp) ,prob_image为单通道图像,应为由只含目标的图像经过计算H分量直方图、计算直方图的方向投影得到的概率图像,window为指定搜索初始位置的窗口,criteria为终止条件,主要由mean-shift移动的最大迭代次数和可视为窗口位置收敛的最小移动距离组成,comp->rect中包含收敛后搜索窗口的位置,而comp->area包含了窗口内部所有像素和。


二、代码实现


具体代码

我的代码是基于VS2010+ OpenCV2.4.6的。代码可以读入视频,也可以读摄像头,两者的选择只需要在代码中稍微修改即可。无论选择何种,首先打开了视频后,需要由鼠标手动画圆选择视频中要跟踪的目标,由于我的摄像头分辨率低,采用手机拍摄视频后读入。跟踪目标的纹理与周围纹理差别较大时,效果较好吧。

具体代码:

#include "cv.h"
#include "highgui.h"
#include 

void my_mouse_callback(int event ,int x,int y,int flags ,void* param);
void getTarget(IplImage* src ,CvRect rect);               //得到目标图像

bool drawing_circle = false;
int circle_r = 0;
CvPoint circlr_center =cvPoint(0,0);
int circle_x = 0;
int circle_y = 0;
bool flag = false; 
int getting_target = 0;

int main()
{
	CvCapture* capture = cvCreateFileCapture("testMoving.avi");
	if (!capture)
	{
		printf("Can not open the file./n");
		return -1;
	}

	IplImage* frames ;
	frames = cvQueryFrame(capture);
	cvNamedWindow("Test Meanshift" ,1);
	cvSetMouseCallback( "Test Meanshift" ,my_mouse_callback,(void*)frames );
	CvRect rect;
	IplImage* pFrames = cvCreateImage(cvGetSize(frames) ,frames->depth ,3);
	CvHistogram* hist;
	IplImage* result=cvCreateImage(cvGetSize(frames),IPL_DEPTH_8U,1);
	cvZero(result);
	CvConnectedComp comp ;
	IplImage* srcImage =cvCreateImage(cvGetSize(frames),IPL_DEPTH_8U,1);
	CvBox2D box;

	while(1)
	{
		if(flag)
		{
			cvCircle(frames ,circlr_center ,circle_r ,CV_RGB(255 ,0,0),3,8,0);
			rect = cvRect(circlr_center.x-circle_r,circlr_center.y-circle_r,2*circle_r ,2*circle_r);

			if(getting_target)
			{
				pFrames = cvCloneImage(frames);
				getTarget(pFrames ,rect);

				IplImage* target_hsv =cvCreateImage( cvGetSize(pFrames), IPL_DEPTH_8U, 3 );
				IplImage* target_hue =cvCreateImage( cvGetSize(pFrames), IPL_DEPTH_8U, 1 );
				cvCvtColor(pFrames,target_hsv,CV_BGR2HSV);       //转化到HSV空间
				cvSplit( target_hsv, target_hue, NULL, NULL, NULL );    //获得H分量

				IplImage* h_plane=cvCreateImage( cvGetSize(target_hsv),IPL_DEPTH_8U,1 );
				int hist_size[]={255};          //将H分量的值量化到[0,255]
				float h_ranges[] ={0,360};
				float* ranges[] = {h_ranges};    //H分量的取值范围是[0,360)
				hist= cvCreateHist(1,hist_size, CV_HIST_ARRAY ,ranges ,1);
				cvCalcHist(&target_hue, hist, 0, NULL);    //计算得直方图hist

				getting_target = 0;
				cvReleaseImage(&target_hsv);
				cvReleaseImage(&target_hue);

			}

			cvCvtColor(frames ,srcImage ,CV_BGR2GRAY);

			cvCalcBackProject(&srcImage,result,hist);

			cvMeanShift(result ,rect ,cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS ,20 ,0.3),&comp );						
			circlr_center = cvPoint(comp.rect.x+0.5*comp.rect.width ,comp.rect.y+0.5*comp.rect.height);
			circle_r = comp.rect.width/2 ;

		}

		cvShowImage( "Test Meanshift" ,frames);
		if(cvWaitKey(33) == 27)
			break;
		frames = cvQueryFrame(capture);
	}

	return 0;

}

void my_mouse_callback(int event ,int x,int y,int flags ,void* param)
{
	IplImage* images = (IplImage* )param;
	switch(event)
	{
	case CV_EVENT_MOUSEMOVE:
		{
			if (drawing_circle == true)
			{
				circlr_center = cvPoint((x+circle_x)/2 ,(y+circle_y)/2);
				circle_r = (x-circle_x)/2;
			}

		}
		break;
	case CV_EVENT_LBUTTONDOWN:
		{
			drawing_circle = true ;
			circle_x = x;
			circle_y = y;

		}
		break;
	case CV_EVENT_LBUTTONUP:
		{

			drawing_circle = false;
			flag = true ;
			getting_target = 1;
		}
		break;
	}



}

void getTarget(IplImage* src ,CvRect rect)
{
	for(int i=0;iwidth ;i++)
		for(int j = 0; jheight ;j++)
		{
			if( i(rect.x+rect.width))
			{
				if( j(rect.y+rect.height))
					cvSet2D(src ,j , i,cvScalarAll(255));
			}
		}
}

三、结果

跟踪结果令人大致满意,但当照射到物体上的光照发生变化,或者跟踪物体保持不平衡时容易时,跟丢目标,这也是缺陷吧!!


基于mean-shift的简单目标跟踪_第1张图片基于mean-shift的简单目标跟踪_第2张图片基于mean-shift的简单目标跟踪_第3张图片基于mean-shift的简单目标跟踪_第4张图片



你可能感兴趣的:(opencv,opencv,mean-shift算法,简易目标跟踪)