PariticalFilter在MFC上的运行
由于项目需要,进行过一段时间的PariticalFilter研究。主要的工作就是将网络上的Console代码和Mfc融合在一起,并且添加了Mfc端的控制功能。
程序还有不完善的地方,现将相关的函数发布出来,大家相互研究。
程序的核心为两个部分,一个是核心PF函数,一个是界面操作
核心函数
/@file
Definitionsrelatedtotrackingwithparticlefiltering
@authorRobHess
@version1.0.0-20060307
jsxyhelu2016年11月修改更多代码,请浏览jsxyhelu.cnblogs.com
jsxyhelu2016年12月代码梳理,重构
/
#include"stdafx.h"
#include"GOPF.h"
usingnamespacestd;
usingnamespacecv;
//非常值得注意的一点是,本例中的指针的运用极大地提高了系统速度
//使用方法
///变量
intnum_particles=100;//狗的数目
intiFrame=0;//当前为第几帧
RectrectStart;//初始化矩形
MatmatFrame;//原始帧
MatmatClone;//原始帧复制
MatmatHSV;//原始帧的HSV形式
particleparticles,new_particles;
//gsl初始化
gsl_rngrng;
gsl_rng_env_setup();
rng=gsl_rng_alloc(gsl_rng_mt19937);
gsl_rng_set(rng,time(NULL));
//gsl初始化结束,rng为输出
//打开视频
VideoCapturevideocapture;
videocapture.open("e:/sandbox/1.avi");
if(!videocapture.isOpened())
{
printf("视频打开失败!");
return-1;
}
//TODO
rectStart=Rect(449,86,21,13);
//主要循环
for(;;)
{
videocapture>>matFrame;
if(matFrame.empty())
break;
matClone=matFrame.clone();
imshow("原始图像",matFrame);
//step0当前帧转换为hsv模式,注意是在float下转换
matFrame.convertTo(matHSV,CV_32F,1.0/255);
cvtColor(matHSV,matHSV,COLOR_BGR2HSV);
//step1如果为第一帧,初始化相关数据
if(iFrame==0)
{
//计算初始区域的粒子
histogramref_histos=compute_ref_histos(matHSV,rectStart);
particles=init_distribution(rectStart,ref_histos,1,num_particles);
iFrame=1;
}
else
{
//step2放出100狗
for(intj=0;j {
//生成随机狗
particles[j]=transition(particles[j],matFrame.cols,matFrame.rows,rng);
floats=particles[j].s;
//计算相似性
particles[j].w=likelihood(matHSV,cvRound(particles[j].y),
cvRound(particles[j].x),
cvRound(particles[j].widths),
cvRound(particles[j].heights),
particles[j].histo);
}
//step3重新规划
normalize_weights(particles,num_particles);
new_particles=resample(particles,num_particles);
free(particles);
particles=new_particles;
}
display_particle(&matClone,particles);
imshow("结果图像",matClone);
waitKey(15);
iFrame=iFrame+1;
}/
//根据hsv的bin的返回结果
inthisto_bin(floath,floats,floatv)
{
#defineH_MAX360.0
#defineS_MAX1.0
#defineV_MAX1.0
#defineS_THRESH0.1
#defineV_THRESH0.2
inthd,sd,vd;
/ifSorVislessthanitsthreshold,returna"colorless"bin/
vd=MIN((int)(vNV/V_MAX),NV-1);
if(s returnNHNS+vd;
/otherwisedetermine"colorful"bin/
hd=MIN((int)(hNH/H_MAX),NH-1);
sd=MIN((int)(sNS/S_MAX),NS-1);returnsdNH+hd;
}
//计算直方图结果,因为所有的值都是计算成直方图,所以这个是核心算法(意味运行次数最多,优化最有效)
histogramcalc_histogram(IplImageimgs,intn)
{
histogramhisto;
IplImageh,s,v;
floathist;
inti,r,c,bin;
histo=(histogram)malloc(sizeof(histogram));
histo->n=NHNS+NV;
hist=histo->histo;
memset(hist,0,histo->nsizeof(float));
h=cvCreateImage(cvGetSize(imgs),IPL_DEPTH_32F,1);
s=cvCreateImage(cvGetSize(imgs),IPL_DEPTH_32F,1);
v=cvCreateImage(cvGetSize(imgs),IPL_DEPTH_32F,1);
cvSplit(imgs,h,s,v,NULL);
/incrementappropriatehistogrambinforeachpixel/
for(r=0;rheight;r++)
for(c=0;cwidth;c++)
{
bin=histo_bin(/pixval32f(h,r,c)/((float)(h->imageData+h->widthStepr))[c],
((float)(s->imageData+s->widthStepr))[c],
((float)(v->imageData+v->widthStepr))[c]);
hist[bin]+=1;
}
cvReleaseImage(&h);
cvReleaseImage(&s);
cvReleaseImage(&v);
returnhisto;
}
//直方图正定化
voidnormalize_histogram(histogramhisto)
{
floathist;
floatsum=0,inv_sum;
inti,n;
hist=histo->histo;
n=histo->n;
/computesumofallbinsandmultiplyeachbinbythesum''sinverse/
for(i=0;i sum+=hist[i];
inv_sum=1.0/sum;
for(i=0;i hist[i]=inv_sum;
}
//计算n个histogram的数据结构
histogramcompute_ref_histos(Matsrc,Rectrect)
{
IplImagematsrc(src);
IplImageframe=&matsrc;
CvRectregions=(CvRect)rect;
histogramhistos=(histogram)malloc(sizeof(histogram));
IplImagetmp;
cvSetImageROI(frame,regions);
tmp=cvCreateImage(cvGetSize(frame),IPL_DEPTH_32F,3);
cvCopy(frame,tmp,NULL);
cvResetImageROI(frame);
histos=calc_histogram(tmp,1);
normalize_histogram(histos);
cvReleaseImage(&tmp);
returnhistos;
}
//初始化distribution
particleinit_distribution(Rectrect,histogramhistos,intn,intp)
{
CvRectregions=(CvRect)rect;
particleparticles;
intnp;
floatx,y;
inti,j,width,height,k=0;
particles=(particle)malloc(psizeof(particle));
np=p/n;
width=regions.width;
height=regions.height;
x=regions.x+width/2;
y=regions.y+height/2;
for(j=0;j {
particles[k].x0=particles[k].xp=particles[k].x=x;
particles[k].y0=particles[k].yp=particles[k].y=y;
particles[k].sp=particles[k].s=1.0;
particles[k].width=width;
particles[k].height=height;
particles[k].histo=histos;
particles[k++].w=0;
}
/makesuretocreateexactlypparticles/
i=0;
while(k {
width=regions.width;
height=regions.height;
x=regions.x+width/2;
y=regions.y+height/2;
particles[k].x0=particles[k].xp=particles[k].x=x;
particles[k].y0=particles[k].yp=particles[k].y=y;
particles[k].sp=particles[k].s=1.0;
particles[k].width=width;
particles[k].height=height;
particles[k].histo=histos;
particles[k++].w=0;
i=(i+1)%n;
}
returnparticles;
}
//预测狗的位置
particletransition(particlep,intw,inth,gsl_rngrng)
{
#defineTRANS_X_STD1.0
#defineTRANS_Y_STD0.5
#defineTRANS_S_STD0.001
/autoregressivedynamicsparametersfortransitionmodel/
#defineA12.0
#defineA2-1.0
#defineB01.0000
floatx,y,s;
particlepn;
//采用second-order进行狗的估算
/samplenewstateusingsecond-orderautoregressivedynamics/
x=A1(p.x-p.x0)+A2(p.xp-p.x0)+
B0gsl_ran_gaussian(rng,TRANS_X_STD)+p.x0;
pn.x=MAX(0.0,MIN((float)w-1.0,x));
y=A1(p.y-p.y0)+A2(p.yp-p.y0)+
B0gsl_ran_gaussian(rng,TRANS_Y_STD)+p.y0;
pn.y=MAX(0.0,MIN((float)h-1.0,y));
s=A1(p.s-1.0)+A2(p.sp-1.0)+
B0gsl_ran_gaussian(rng,TRANS_S_STD)+1.0;
pn.s=MAX(0.1,s);
pn.xp=p.x;
pn.yp=p.y;
pn.sp=p.s;
pn.x0=p.x0;
pn.y0=p.y0;
pn.width=p.width;
pn.height=p.height;
pn.histo=p.histo;
pn.w=0;
returnpn;
}
//histogram比较,马氏距离
floathisto_dist_sq(histogramh1,histogramh2)
{
floathist1,hist2;
floatsum=0;
inti,n;
n=h1->n;
hist1=h1->histo;
hist2=h2->histo;
for(i=0;i sum+=sqrt(hist1[i]hist2[i]);
return1.0-sum;
}
//粒子比较
intparticle_cmp(constvoidp1,constvoidp2)
{
particle_p1=(particle)p1;
particle_p2=(particle)p2;
if(_p1->w>_p2->w)
return-1;
if(_p1->w<_p2->w)
return1;
return0;
}
//相似性计算
floatlikelihood(MatmatSrc,intr,intc,intw,inth,histogramref_histo)
{
#defineLAMBDA20
IplImagematimg(matSrc);
IplImageimg=&matimg;
IplImagetmp;
histogramhisto;
floatd_sq;
/extractregionaround(r,c)andcomputeandnormalizeitshistogram/
cvSetImageROI(img,cvRect(c-w/2,r-h/2,w,h));
tmp=cvCreateImage(cvGetSize(img),IPL_DEPTH_32F,3);
cvCopy(img,tmp,NULL);
cvResetImageROI(img);
histo=calc_histogram(tmp,1);
cvReleaseImage(&tmp);
normalize_histogram(histo);
/computelikelihoodase^{\lambdaD^2(h,h^)}/
d_sq=histo_dist_sq(histo,ref_histo);
free(histo);
returnexp(-LAMBDAd_sq);
}
//权值归一化
voidnormalize_weights(particleparticles,intn)
{
floatsum=0;
inti;
for(i=0;i sum+=particles[i].w;
for(i=0;i particles[i].w/=sum;
}
//重新采样
particleresample(particleparticles,intn)
{
particlenew_particles;
inti,j,np,k=0;
//quicksort
qsort(particles,n,sizeof(particle),&particle_cmp);
new_particles=(particle)malloc(nsizeof(particle));
for(i=0;i {
np=cvRound(particles[i].wn);
for(j=0;j {
new_particles[k++]=particles[i];
if(k==n)
gotoexit;
}
}
while(k new_particles[k++]=particles[0];
exit:
returnnew_particles;
}
//显示PF的结果
voiddisplay_particle(Matimg,particlep)
{
intx0,y0,x1,y1;
x0=cvRound(p.x-0.5p.sp.width);
y0=cvRound(p.y-0.5p.sp.height);
x1=x0+cvRound(p.sp.width);
y1=y0+cvRound(p.sp.height);
cv::rectangle(img,Point(x0,y0),Point(x1,y1),Scalar(0,0,255));
}
界面处理相关
voidCGOMfcTemplate2Dlg::OnMouseMove(UINTnFlags,CPointpoint)
{
CRectrect_ctr;
(this->GetDlgItem(IDC_CAM))->GetWindowRect(&rect_ctr);//获取Picture控件相对屏幕左上角的坐标,
ScreenToClient(rect_ctr);//获取Picture控件相对对话框客户区左上角的坐标
instant_position.x=point.x;
instant_position.y=point.y;
picture_ordinate_x=point.x-rect_ctr.left;
picture_ordinate_y=point.y-rect_ctr.top;//point获取的是鼠标相对对话框客户区左上角的坐标,减去rect_ctr.left和rect_ctr.top后,即为鼠标相对Picture控件左上角的坐标
if((nFlags==MK_LBUTTON)&&Is_LeftButton_Down)
{
::SetCursor(cross);
CClientDCdc(this);
CBrushOldBrush;
OldBrush=(CBrush)dc.SelectStockObject(NULL_BRUSH);
dc.SetROP2(R2_NOT);
dc.Rectangle(CRect(chosen_position,instant_position));
dc.Rectangle(CRect(chosen_position,point));
dc.SelectObwww.baiyuewang.netject(OldBrush);
instant_position=point;
}
else
::SetCursor(arrow);
CDialogEx::OnMouseMove(nFlags,point);
}
voidCGOMfcTemplate2Dlg::OnLButtonDown(UINTnFlags,CPointpoint)
{
Is_LeftButton_Down=true;
::SetCursor(cross);
chosen_position=instant_position=point;
CDialogEx::OnLButtonDown(nFlags,point);
}
voidCGOMfcTemplate2Dlg::OnLButtonUp(UINTnFlags,CPointpoint)
{
if(Is_LeftButton_Down)
{
Is_LeftButton_Down=false;
::SetCursor(arrow);
CClientDCdc(this);
CPenpOldPen=(CPen)dc.SelectObject(&pen);
dc.MoveTo(chosen_position);
dc.LineTo(chosen_position.x,instant_position.y);
dc.LineTo(instant_position);
dc.LineTo(instant_position.x,chosen_position.y);
dc.LineTo(chosen_position);
//写到rect_res中区
intrect_x=min(chosen_position.x,instant_position.x);
intrect_y=min(chosen_position.y,instant_position.y);
intrect_w=abs(chosen_position.x-instant_position.x);
intrect_h=abs(chosen_position.y-instant_position.y);
rectStart=Rect(rect_x,rect_y,rect_w,rect_h);
}
CDialogEx::OnLButtonUp(nFlags,point);
}
|
|