cvCamShift得到掩膜内的反向投影

// camshift.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include "stdio.h"
#include "ctype.h"

IplImage *image=0,*hsv=0,*hue=0,*mask=0,*backproject=0,
		 *histimg=0;
CvHistogram *hist=0;

int backproject_mode=0;
int select_object=0;
int	track_object=0;
int show_hist=1;
CvPoint origin;
CvRect selection;
CvRect track_window;
CvBox2D track_box;			//tracking返回的区域box,带角度
 //Meanshift跟踪算法返回的Box类
 //typedef struct CvBox2D{
 //CvPoint2D32f center; /* 盒子的中心 */
 //CvSize2D32f size; /* 盒子的长和宽 */
 //float angle; /* 水平轴与第一个边的夹角,用弧度表示*/
 //}CvBox2D; 
CvConnectedComp track_comp;
 //连接部件 
//typedef struct CvConnectedComp{
 //double area; /* 连通域的面积 */
 //float value; /* 分割域的灰度缩放值 */
 //CvRect rect; /* 分割域的 ROI */
 //} CvConnectedComp;

int hdims=48;//划分HIST的个数,越高越精确//划分直方图bins的个数,越多越精确
float hranges_arr[]={0,180};//像素值的范围
float *hranges=hranges_arr;//用于初始化CvHistogram类

int vmin=10,vmax=256,smin=30;


//鼠标回调函数,该函数用鼠标进行跟踪目标的选择
void on_mouse(int event,int x,int y,int flags,void* param )
{
		if(!image)
			return;
		if(image->origin)
			 //如果图像原点坐标在左下,则将其改为左上
			y=image->height-y;
		if(select_object)
		{
			//最大和最小成矩形
			selection.x=MIN(x,origin.x);
			selection.y=MIN(y,origin.y);
			selection.width=selection.x+CV_IABS(x-origin.x);
			selection.height=selection.y+CV_IABS(y-origin.y);
			
			
			selection.x = MAX( selection.x, 0 );
			selection.y = MAX( selection.y, 0 );
			selection.width = MIN( selection.width, image->width );
			selection.height = MIN( selection.height, image->height );
			selection.width -= selection.x;
			selection.height -= selection.y;
		
		}
		switch(event)
		{
			case CV_EVENT_LBUTTONDOWN:
				//鼠标按下,开始点击选择跟踪物体
			origin=cvPoint(x,y);		//鼠标起点
			selection=cvRect(x,y,0,0);
			select_object=1;//坐标计算标志位
			break;
			case CV_EVENT_LBUTTONUP:
			   //鼠标松开,完成选择跟踪物体
			select_object=0;
			if(selection.width>0&&selection.height>0)
				track_object=-1;
			//如果选择物体有效,则打开跟踪功能
			break;
		
		}

}
CvScalar hsv2rgb( float hue )
 //用于将Hue量转换成RGB量
 {
     int rgb[3], p, sector;
     static const int sector_data[][3]=
         {{0,2,1}, {1,2,0}, {1,0,2}, {2,0,1}, {2,1,0}, {0,1,2}};
     hue *= 0.033333333333333333333333333333333f;
     //cvFloor 返回不大于参数的最大整数值
	 sector = cvFloor(hue);
     p = cvRound(255*(hue - sector));
     p ^= sector & 1 ? 255 : 0;
     rgb[sector_data[sector][0]] = 255;
     rgb[sector_data[sector][1]] = 0;
     rgb[sector_data[sector][2]] = p;
     return cvScalar(rgb[2], rgb[1], rgb[0],0);
 }




 

int main(int argc, char* argv[])
{
	CvCapture* capture=0;
	IplImage * frame=0;
	//strlen 计算字符串S的长度并返回长度 isdigit判断字符是否是数字0-9返回非零的值

	capture=cvCaptureFromCAM(-1);


	//打开视频流的失败

	     printf( "Hot keys: \n"
         "\tESC - quit the program\n"
         "\tc - stop the tracking\n"
         "\tb - switch to/from backprojection view\n"
         "\th - show/hide object histogram\n"
         "To initialize tracking, select the object with mouse\n" );
 //程序功能列表
	cvNamedWindow("Histogram",1);
	//用于显示直方图
	cvNamedWindow("CamShiftDemo",1);
	//用于显示视频
	cvSetMouseCallback("CamShiftDemo",on_mouse,NULL);
	//设置鼠标回调函数
	cvCreateTrackbar("Vmin","CamShiftDemo",&vmin,256,0);
	cvCreateTrackbar("Vmin","CamShiftDemo",&vmax,256,0);
	cvCreateTrackbar("Vmin","CamShiftDemo",&smin,256,0);
    //设置滑动条 
	//进入视频帧处理主循环
	for(;;)
	{
		int i,bin_w,c;
		frame=cvQueryFrame(capture);		//获得图像
		if(!frame)
			break;
	//第一步
		if(!image)
			//image为0,表明刚开始还未对image操作过,先建立一些缓冲区
		{
			image=cvCreateImage(cvGetSize(frame),8,3);
			image->origin=frame->origin;		//得到原点
			hsv=cvCreateImage(cvGetSize(frame),8,3);
			hue=cvCreateImage(cvGetSize(frame),8,1);
			mask=cvCreateImage(cvGetSize(frame),8,1);
		   //分配掩膜图像空间
			backproject=cvCreateImage(cvGetSize(frame),8,1);
			//分配反向投影图空间,大小一样,单通道
			hist=cvCreateHist(1,&hdims,CV_HIST_ARRAY,&hranges,1);
			//创建一维直方图
			histimg=cvCreateImage(cvSize(320,200),8,3);
			
			//一维直方图显示空间
			cvZero(histimg);
			//初始化
		}


		cvCopy(frame,image);		//image得到整个图像
		cvCvtColor(image,hsv,CV_BGR2HSV);//把图像从RGB表色系转为HSV表色系
		if(track_object)
			//track_object非零,表示有需要跟踪的物体
		{
			int _vmin=vmin, _vmax=vmax;
		    cvInRangeS( hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0),
            cvScalar(180,256,MAX(_vmin,_vmax),0), mask );
             //制作掩膜板,只处理像素值为H:0~180,S:smin~256,V:vmin~vmax之间的部分
            cvSplit( hsv, hue, 0, 0, 0 );
			 //分离H分量
			if(track_object<0)
				 //如果需要跟踪的物体还没有进行属性提取,则进行选取框类的图像属性提取
			{
				float max_val=0.f;
				 //设置原选择框为ROI
				 cvSetImageROI( hue, selection );
                 cvSetImageROI( mask, selection );
                 //设置掩膜板选择框为ROI
                 cvCalcHist( &hue, hist, 0, mask );
                 //得到选择框内且满足掩膜板内的直方图  hist 记录下来
                 cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );
                 cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 );
                 // 对直方图的数值转为0~255
                 cvResetImageROI( hue );
                 //去除ROI
                 cvResetImageROI( mask );
                 //去除ROI
				 track_window = selection;
                 track_object = 1;
                //置track_object为1,表明属性提取完成
				  cvZero( histimg );
				 bin_w=histimg->width/hdims;
				 //画直方图到图像空间
				 for(i=0;i<hdims;i++)
                 {
                     int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 );
					 printf("%d",val);
                     CvScalar color = hsv2rgb(i*180.f/hdims);
                     cvRectangle( histimg, cvPoint(i*bin_w,histimg->height),
                                  cvPoint((i+1)*bin_w,histimg->height - val),
                                  color, -1, 8, 0 );
                 }
			}
			cvCalcBackProject(&hue,backproject,hist);//使用backproject计算hue的反向投影图
			//project大小=HIST
			cvAnd( backproject, mask, backproject, 0 );

             //得到掩膜内的反向投影
			cvCamShift( backproject, track_window,
                         cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),
                         &track_comp, &track_box );
             //使用MeanShift算法对backproject中的内容进行搜索,返回跟踪结果
             track_window = track_comp.rect;
			 //得到跟踪结果的矩形框
			   
           if( backproject_mode )
                cvCvtColor( backproject, image, CV_GRAY2BGR );
                 
            if( image->origin )
                 track_box.angle = -track_box.angle;//反向
             cvEllipseBox( image, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 );
             //画出跟踪结果的位置
		}
		  if( select_object && selection.width > 0 && selection.height > 0 )
         //如果正处于物体选择,画出选择框
         {
             cvSetImageROI( image, selection );
             cvXorS( image, cvScalarAll(255), image, 0 );
             cvResetImageROI( image );
         }
         cvShowImage( "CamShiftDemo", image );
         cvShowImage( "Histogram", histimg );
         c = cvWaitKey(10);
         if( (char) c == 27 )
             break;
         switch( (char) c )
         //按键切换功能
         {
         case 'b':
             backproject_mode ^= 1;
             break;
         case 'c':
             track_object = 0;
             cvZero( histimg );
             break;
         case 'h':
             show_hist ^= 1;
             if( !show_hist )
                 cvDestroyWindow( "Histogram" );
             else
                 cvNamedWindow( "Histogram", 1 );
             break;
         default:
             ;
         }
	}
	 cvReleaseCapture( &capture );
     cvDestroyWindow("CamShiftDemo");	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值