视频跟踪源码.docx
- 文档编号:10800966
- 上传时间:2023-05-27
- 格式:DOCX
- 页数:15
- 大小:20.29KB
视频跟踪源码.docx
《视频跟踪源码.docx》由会员分享,可在线阅读,更多相关《视频跟踪源码.docx(15页珍藏版)》请在冰点文库上搜索。
视频跟踪源码
#ifdef_CH_
#pragmapackage
#endif
#ifndef_EiC
#include"cv.h"
#include"highgui.h"
#include
#include
#include
#include
#include
#endif
IplImage*image=0,*hsv=0,*hue=0,*mask=0,*backproject=0,*histimg=0;
CvHistogram*hist=0;
intbackproject_mode=0;
intselect_object=0;
inttrack_object=0;
intshow_hist=1;
CvPointorigin;
CvRectselection;
CvRecttrack_window;
CvBox2Dtrack_box,t;
CvConnectedComptrack_comp;
//创建一个直方图时需要用到常量指针
inthdims=16;
floathranges_arr[]={0,180};
float*hranges=hranges_arr;
//图像掩膜需要的边界常数
intvmin=10,vmax=256,smin=30;
intfirsth;
intfirstw;
intduijiao;
intkaiguan;
charInch[128];
unsignedintData_lenth;//数据长度
unsignedintSend_lenth;//串口发送数据总长度
unsignedintIssue=0;
charsynHead[7]={11,22,33,44,0,0,0};//报头
charsynHead_num=4;
charsynTail[4]={66,77,88,99};//报尾
intData_Pack(inta,intb,intx,inty,intz);
//用鼠标选定跟踪目标矩形selection的子函数,返回selection的相关信息参数
voidon_mouse(intevent,intx,inty,intflags,void*param)
{
//待选图片不存在,直接退出该函数
if(!
image)
return;
//如果捕捉到了左上角点,则计算y
if(image->origin)
y=image->height-y;
//如果可以选择物体了,则给矩形selection赋相关信息参数
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;
}
kaiguan=1;
//鼠标消息响应
//按下键并未松开时select_object=1,松开鼠标后select_object=0,故select_object是正在选定目标的标识
//松开鼠标后track_object=-1,又得重新计算直方图了
//这里有点让人疑惑,不知道它是怎么捕捉目标窗口的对角点的
switch(event)
{
//按下鼠标时,捕获点,select_object置一
caseCV_EVENT_LBUTTONDOWN:
origin=cvPoint(x,y);
selection=cvRect(x,y,0,0);
select_object=1;
break;
//松开鼠标时,track_object置负一
caseCV_EVENT_LBUTTONUP:
select_object=0;
if(selection.width>0&&selection.height>0)
track_object=-1;
break;
}
}
//图像格式转换,HSV转成RGB,每一个float格式的hue值可以转换成三个uint8格式的RGB[3]
CvScalarhsv2rgb(floathue)
{
intrgb[3],p,sector;
staticconstintsector_data[][3]=
{{0,2,1},{1,2,0},{1,0,2},{2,0,1},{2,1,0},{0,1,2}};
hue*=0.033333333333333333333333333333333f;
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;
returncvScalar(rgb[2],rgb[1],rgb[0],0);
}
intmain(intargc,char**argv)
{
intIoff,Isize;
CvCapture*capture=0;
if(argc==1||(argc==2&&strlen(argv[1])==1&&isdigit(argv[1][0])))
capture=cvCaptureFromCAM(argc==3?
argv[1][0]-'0':
0);//argc==2?
elseif(argc==3)
capture=cvCaptureFromAVI(argv[1]);
//摄像头画面捕捉不成功则退出程序
if(!
capture)
{
fprintf(stderr,"Couldnotinitializecapturing...\n");
return-1;
}
//关于显示窗口的一些设置
cvNamedWindow("Histogram",1);
cvNamedWindow("CamShiftDemo",1);
//设置鼠标事件,把鼠标响应与on_mouse函数关联起来
cvSetMouseCallback("CamShiftDemo",on_mouse,0);
//创建三个滑块条,特定条件用滑块条选择不同参数能获得较好的跟踪效果
cvCreateTrackbar("Vmin","CamShiftDemo",&vmin,256,0);
cvCreateTrackbar("Vmax","CamShiftDemo",&vmax,256,0);
cvCreateTrackbar("Smin","CamShiftDemo",&smin,256,0);
//进入无限循环跟踪阶段
for(;;)
{
IplImage*frame=0;
inti,bin_w,c;
//从摄像头或者文件中抓取并返回一帧到frame
frame=cvQueryFrame(capture);
if(!
frame)
break;
//如果下面的if语句运行一遍了,则全局变量image被定义了,下次就不用在执行这个if块语句了
if(!
image)
{
/*allocateallthebuffers*/
//如果全局变量image尚未定义,则创建其内容
image=cvCreateImage(cvGetSize(frame),8,3);
image->origin=frame->origin;
//创建3通道的HSV图像,单通道的hue图像,单通道的mask图像
hsv=cvCreateImage(cvGetSize(frame),8,3);
hue=cvCreateImage(cvGetSize(frame),8,1);
mask=cvCreateImage(cvGetSize(frame),8,1);
//创建单通道的反向投影图backproject
backproject=cvCreateImage(cvGetSize(frame),8,1);
//创建一个空的直方图hist
hist=cvCreateHist(1,&hdims,CV_HIST_ARRAY,&hranges,1);
//创建一个,3通道直方图图像,分辨率320*200
histimg=cvCreateImage(cvSize(320,200),8,3);
cvZero(histimg);
}
//把frame里的数据拷贝到image里,并转化成HSV格式存于数组hsv
cvCopy(frame,image,0);
cvCvtColor(image,hsv,CV_BGR2HSV);
//选好了跟踪目标就会执行以下的if块语句
if(track_object)
{
int_vmin=vmin,_vmax=vmax;
//cvInRangeS函数用于检查数组元素是否在两个数量之间
//这里用于制作掩膜板,只处理像素值为H:
0~180,S:
smin~256,V:
vmin~vmax之间的部分
//结果得到表示ROI的二值化数组mask
cvInRangeS(hsv,cvScalar(0,smin,MIN(_vmin,_vmax),0),
cvScalar(180,256,MAX(_vmin,_vmax),0),mask);
//只抽取H分量,变成单通道的数组hue
cvSplit(hsv,hue,0,0,0);
//如果是第一次开始跟踪,则执行下面if块语句
//目的是得到跟踪目标的直方图,这个只需要在选定目标后执行一次计算即可,不必每次跟踪都计算
if(track_object<0)
{
floatmax_val=0.f;
//基于用户最初选定的目标矩形selection设置感兴趣区域
cvSetImageROI(hue,selection);
cvSetImageROI(mask,selection);
//绘制色调直方图hist,仅限于用户最初选定的目标矩形区域
cvCalcHist(&hue,hist,0,mask);
//寻找hist里面的最大和最小直方块,最大值指针是max_val
cvGetMinMaxHistValue(hist,0,&max_val,0,0);
//对直方图hist进行线性变换转换,在这里是将它拉伸到256
cvConvertScale(hist->bins,hist->bins,max_val?
255./max_val:
0.,0);
//释放图像感兴趣区域ROI
cvResetImageROI(hue);
cvResetImageROI(mask);
//跟踪窗口跟目标窗口一样
track_window=selection;
//把track_object置一,接下来就不用再执行这个if块里面的语句了
track_object=1;
//初始化直方图图像histimg,即置零
cvZero(histimg);
//计算每个直方的宽度
bin_w=histimg->width/hdims;
//量化等级一共有hdims=16个等级,故循环hdims=16次,画十六个直方块
for(i=0;i { intval=cvRound(cvGetReal1D(hist->bins,i)*histimg->height/255); //选用hdims=16种颜色来华这hdims=16个直方块 CvScalarcolor=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); } } //根据直方图hist计算整幅图像的反向投影图backproject cvCalcBackProject(&hue,backproject,hist); //计算两个数组backproject、mask的每个元素的按位与,mask起掩膜作用 cvAnd(backproject,mask,backproject,0); //调用最核心的camshif函数,关于这个函数的源码可参考文件camshift.cpp cvCamShift(backproject,track_window, cvTermCriteria(CV_TERMCRIT_EPS|CV_TERMCRIT_ITER,10,1), &track_comp,&track_box); //把camshif函数跟踪到的目标窗口矩形赋给track_window track_window=track_comp.rect; if(kaiguan==1) { firsth=int(track_box.size.height); firstw=int(track_box.size.width); duijiao=int(sqrt(firsth*firsth+firstw*firstw)); kaiguan=0; } //选择视频显示窗口是采用原始模式还是反响投影灰度模式 if(backproject_mode) cvCvtColor(backproject,image,CV_GRAY2BGR); //根据图像是顶左结构(origin=0)还是底左结构(origin=1)决定camshift函数返回的2D矩形的角度 if(image->origin) track_box.angle=-track_box.angle; //对跟踪目标画椭圆进行标识 cvEllipseBox(image,track_box,CV_RGB(255,0,0),3,CV_AA,0); intduijiao1=int(sqrt(track_box.size.height*track_box.size.height+track_box.size.width*track_box.size.width)); Ioff=int(track_box.center.x-(image->width/2));//目标的偏移 Isize=int(duijiao1-duijiao);//目标的远近,用大小表示 printf("%d%d",Ioff,Isize); Data_Pack(1,0,1,Ioff,Isize); } //如果正在重新选择目标,则执行下面的if块语句 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(5); } //释放摄像头,关闭窗口 cvReleaseCapture(&capture); cvDestroyWindow("CamShiftDemo"); return0; } ///////////////////////////////////////////////////////////////////// //发送数据到串口 //数据格式: 1前引导符(11,22,33,44) //2数据包括(2.1长度2字节,2.2流水号2字节,2.3站点1字节,2.4命令1字节, //2.5数据若干,2.6数据校验位(2.1-2.5)1字节,不包括引导符) //3后引导符(55,66,77,88) //说明: 2.5校验为: 长度,流水号,站点,命令,数据之和 //1a目标b源x命令y数据1z数据2 ///////////////////////////////////////////////////////////////////////// intData_Pack(inta,intb,intx,inty,intz)//a目标b源x命令y数据1z数据2 { unsignedinti; unsignedchar*pSrc; charVery; //Data_lenth1=2; //'数据若干+流水号2字节+站号1字节+命令1字节 DWORDdwBytes; DCBdcb;//串口模块 HANDLEhSer; hSer=CreateFile("com3",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); if(hSer==INVALID_HANDLE_VALUE) { printf("打开串口失败"); return0; } //settheDCBstructure printf("打开串口成功\n"); dcb.DCBlength=sizeof(DCB); GetCommState(hSer,&dcb); dcb.fParity=FALSE; dcb.fNull=FALSE; dcb.StopBits=ONESTOPBIT; dcb.Parity=NOPARITY; dcb.BaudRate=9600; dcb.ByteSize=8; SetCommState(hSer,&dcb); //Setthetimeout COMMTIMEOUTSCommTimeOuts; CommTimeOuts.ReadIntervalTimeout=0xFFFFFFFF; CommTimeOuts.ReadTotalTimeoutMultiplier=10; CommTimeOuts.ReadTotalTimeoutConstant=10; CommTimeOuts.WriteTotalTimeoutMultiplier=50; CommTimeOuts.WriteTotalTimeoutConstant=100; SetCommTimeouts(hSer,&CommTimeOuts); Data_lenth=2+2+1+1+1+2+2; Send_lenth=Data_lenth+8+1;//包括引导符前4字节+后4字节+校验1字节) //'数据报头 for(i=0;i<4;i++) { Inch[i]=synHead[i];//存储报头 } //'发送数据的总长度,不包括报头和尾 Inch[4]=12;//数据位固定长度 Inch[5]=(Data_lenth+2)/256;//数据位 //'数据包的流水号 Inch[6]=Issue&255;//流水号 Inch[7]=Issue/256;//流水号 Issue=Issue+1; Inch[8]=a;//目标地址 Inch[9]=b;//源地址 Inch[10]=x;//数据的命令字 Inch[11]=y&0xff; Inch[12]=(y>>8)&0xff;//数据1 Inch[13]=z&0xff;//数据2 Inch[14]=(z>>8)&0xff;//'校验和 Very=0;//发送的数据和 for(i=0;i { Very=(Very+Inch[i+4])&255;//将每个数据内容相加 } Inch[i+4]=Very;//将总和存入数组中 for(i=0;i<4;i++)//数据报尾 { Inch[i+Data_lenth+5]=synTail[i];//将报尾存入总数组中 } pSrc=(unsignedchar*)Inch; WriteFile
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 视频 跟踪 源码