📄 vehicletracedlg.cpp
字号:
}
void CVehicleTraceDlg::TraceBest (HTuple Seedx, HTuple Seedy, HTuple PreSeedx, HTuple PreSeedy, HTuple AreaSC, HTuple RowSC, HTuple ColumnSC, HTuple Seedarea, HTuple *SeedMatchInd)
{
// 结合最优匹配点与当前种子点之间的距离、角度和区域面积特征进行轨迹跟踪
HTuple DistancesSC, AnglesSC, RareasSC, w1, w2, w3, j;
HTuple DistanceSC, AngleSC, RareaSC, MaxDist, MaxAngle;
HTuple FResult, FIndices;
DistancesSC = HTuple();
AnglesSC = HTuple();
RareasSC = HTuple();
w1 = HTuple(0.5);
w2 = HTuple(0.5);
w3 = HTuple(0.5);
(*SeedMatchInd) = HTuple();
for (j=0; j<=(AreaSC.Num())-1; j+=1)
{
// 计算种子点与候选点之间的距离
::distance_pp(Seedx,Seedy,HTuple(RowSC[long(j[0])]),HTuple(ColumnSC[long(j[0])]),&DistanceSC);
::tuple_concat(DistancesSC,DistanceSC,&DistancesSC);
// 计算角度,分种子点与临时种子点
if (PreSeedx!=0) //种子点
{
::angle_ll(PreSeedx,PreSeedy,Seedx,Seedy,Seedx,Seedy,HTuple(RowSC[long(j[0])]),HTuple(ColumnSC[long(j[0])]),&AngleSC);
::tuple_concat(AnglesSC,AngleSC.Abs(),&AnglesSC); // 计算两直线之间的夹角,顺时针旋转,-pi<alpha<pi
}
else //倘若是临时种子点则角度不列入考虑
{
::tuple_concat(AnglesSC,HTuple(0),&AnglesSC); // 在尾部添加0
}
// 计算面积相对差别
RareaSC = ((HTuple(AreaSC[long(j[0])])-Seedarea).Abs())/Seedarea;
::tuple_concat(RareasSC,RareaSC,&RareasSC);
}
// 计算判断准则
::tuple_max(DistancesSC,&MaxDist); //找出最大的距离
::tuple_max(AnglesSC,&MaxAngle); //找出最大的角
if(MaxDist>0)
::tuple_div(DistancesSC,MaxDist,&DistancesSC); //DistancesSC中的每一个元素与MaxDist相除
if(MaxAngle>0)
::tuple_div(AnglesSC,MaxAngle,&AnglesSC);
::tuple_add(w1*DistancesSC,w2*AnglesSC,&FResult);
::tuple_add(FResult,w3*RareasSC,&FResult);
::tuple_sort_index(FResult,&FIndices);
(*SeedMatchInd) = FIndices[long(0)]; //找到最小值对应的序号
return;
/* if (PreSeedx!=0)
{
if (MaxDist!=0)
{
if (MaxAngle!=0)
{
FResult = (((w1*DistancesSC)/MaxDist)+((w2*AnglesSC)/MaxAngle))+(w3*RareasSC);
::tuple_sort_index(FResult,&FIndices);
if (HTuple(FResult[long(FIndices[long(0)])])<1.1)
{
(*SeedMatchInd) = FIndices[long(0)];
}
}
else
{
FResult = ((w1*DistancesSC)/MaxDist)+(w3*RareasSC);
::tuple_sort_index(FResult,&FIndices);
if (HTuple(FResult[long(FIndices[long(0)])])<1.1)
{
(*SeedMatchInd) = FIndices[long(0)];
}
}
}
else
{
if (MaxAngle!=0)
{
FResult = ((w2*AnglesSC)/MaxAngle)+(w3*RareasSC);
::tuple_sort_index(FResult,&FIndices);
if (HTuple(FResult[long(FIndices[long(0)])])<1.1)
{
(*SeedMatchInd) = FIndices[long(0)];
}
}
else
{
FResult = w3*RareasSC;
::tuple_sort_index(FResult,&FIndices);
if (HTuple(FResult[long(FIndices[long(0)])])<1.1)
{
(*SeedMatchInd) = FIndices[long(0)];
}
}
}
}
else
{
if (MaxDist!=0)
{
FResult = ((w1*DistancesSC)/MaxDist)+(w3*RareasSC);
::tuple_sort_index(FResult,&FIndices);
if (HTuple(FResult[long(FIndices[long(0)])])<0.51)
{
(*SeedMatchInd) = FIndices[long(0)];
}
}
else
{
FResult = w3*RareasSC;
::tuple_sort_index(FResult,&FIndices);
if (HTuple(FResult[long(FIndices[long(0)])])<0.51)
{
(*SeedMatchInd) = FIndices[long(0)];
}
}
} */
}
void CVehicleTraceDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
}
void CVehicleTraceDlg::OnCancelMode()
{
CDialog::OnCancelMode();
// TODO: Add your message handler code here
}
void CVehicleTraceDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
CDialog::OnTimer(nIDEvent);
//Hobject ActualImage,ImageZoomed,ForegroundRegion,RegionZoom;
Hobject RegionRec;
if(isPlay==true)
{
//***第一步:找出当前帧中所有运动目标********************************************
// 该段程序的作用是将当前帧图像与背景图像进行灰度对比,在当前帧中提炼出所有运动目标
// 的位置区域,为下面轨迹跟踪做好准备.
grab_image(&ActualImage,m_lFGHandle); // m_lFGHandle由前面open_framegrabber得到
FrameSerialNum++;
// 估计背景灰度或是前景灰度一般先用zoom_image_factor将其缩小,估计完后再恢复至原大小
::zoom_image_factor(ActualImage,&ImageZoomed,HTuple(0.5),HTuple(0.5),HTuple("constant"));
::run_bg_esti(ImageZoomed,&ForegroundRegion,BgEstiHandle); //BgEstiHandle由上面create_bg_esti()创建
::zoom_region(ForegroundRegion,&RegionZoom,HTuple(2),HTuple(2)); //放大到原图像大小
::intersection(RegionZoom,XingRegion,&RegionIntersection); //求交集
::connection(RegionIntersection,&ConnectedRegions);
::select_shape(ConnectedRegions,&SelectedRegions,HTuple("area"),HTuple("and"),HTuple(200),HTuple(99999));
::shape_trans(SelectedRegions,&RegionTrans,HTuple("convex"));
::union1(RegionTrans,&RegionUnion); //经该函数合并后元素个数为1
::connection(RegionUnion,&FinalConnected);
::select_gray(FinalConnected,ActualImage,&SelectedRegionsGray,HTuple("deviation"),HTuple("and"),HTuple(25),HTuple(1000));
::copy_obj(SelectedRegionsGray,&RegionGray,HTuple(1),HTuple(-1)); // 备份
//***第二步:对种子点进行轨迹跟踪**************************************************
// 以下程序段是对已有的种子点逐一进行轨迹跟踪,搜索范围为上面检测到的
// 新的所有可能区域。在针对每一质点时,会确定一个更小的搜索范围。搜索成功则在
// 下一帧中继续,搜索失败则轨迹跟踪断裂。
// 注意:被连续跟踪两帧及两帧以上的轨迹链上的点称为种子点,倘若只有一帧被搜索
// 到,则称为临时种子点。
for (int i=0; i<Vehicles.GetSize(); i++)
{
Vehicle existVehicle=Vehicles.GetAt(i);
if(existVehicle.isEnd==false)
{
int SeedNum=existVehicle.SeedX.Num(); // 求取目标的个数,即取当前车辆对应种子点的个数
// 由上两个点确定一个搜索的范围
WinXlimit = HTuple(HTuple(3)*HTuple(existVehicle.SeedX[SeedNum-2])-HTuple(2)*HTuple(existVehicle.SeedX[SeedNum-1])).Concat((HTuple(6)*HTuple(existVehicle.SeedX[SeedNum-1]))-(HTuple(5)*HTuple(existVehicle.SeedX[SeedNum-2]))); // concat用于将两个tuple变量合为一个
// WinXlimit = HTuple(-).Concat(()-());
// HTuple(3)*HTuple(existVehicle.SeedX[SeedNum-2])
// HTuple(2)*HTuple(existVehicle.SeedX[SeedNum-1])
// HTuple(6)*HTuple(existVehicle.SeedX[SeedNum-1])
// HTuple(5)*HTuple(existVehicle.SeedX[SeedNum-2])
WinYlimit = HTuple(HTuple(3)*HTuple(existVehicle.SeedY[SeedNum-2])-HTuple(2)*HTuple(existVehicle.SeedY[SeedNum-1])).Concat((HTuple(6)*HTuple(existVehicle.SeedY[SeedNum-1]))-(HTuple(5)*HTuple(existVehicle.SeedY[SeedNum-2])));
// WinYlimit = HTuple(-).Concat(()-());
// HTuple(3)*HTuple(existVehicle.SeedY[SeedNum-2])
// HTuple(2)*HTuple(existVehicle.SeedY[SeedNum-1])
// HTuple(6)*HTuple(existVehicle.SeedY[SeedNum-1])
// HTuple(5)*HTuple(existVehicle.SeedY[SeedNum-2])
::tuple_sort(WinXlimit,&WinXlimit); // 将winXlimit中的元素按升序排列!
::tuple_sort(WinYlimit,&WinYlimit);
::select_shape(SelectedRegionsGray,&ObjRegionCandinates,HTuple("row").Concat("column"),HTuple("and"),HTuple(WinXlimit[long(0)]).Concat(HTuple(WinYlimit[long(0)])),HTuple(WinXlimit[long(1)]).Concat(HTuple(WinYlimit[long(1)])));
// 上句对应:select_shape(SelectedRegionsGray,result,['row','column'],'and',[WinXlimit[0],WinYlimit[0]],[WinXlimit[1],WinXlimit[1]])
// 将中心坐标落在上述确定范围的区域选出来!
::area_center(ObjRegionCandinates,&AreaSC,&RowSC,&ColumnSC); //SC--新一代候选种子点
if ((AreaSC.Num())!=0) // 倘若有满足要求的区域存在,则进一步筛选
{
TraceBest(HTuple(existVehicle.SeedX[SeedNum-1]),HTuple(existVehicle.SeedY[SeedNum-1]),HTuple(existVehicle.SeedX[SeedNum-2]),HTuple(existVehicle.SeedY[SeedNum-2]),AreaSC,RowSC,ColumnSC,HTuple(existVehicle.SeedArea[SeedNum-2]),&SeedMatchInd);
if ((SeedMatchInd.Num())!=0) // 倘若有最佳目标出现...
{
// 将目标选出,然后剔除
::select_obj(ObjRegionCandinates,&ObjectMatched,SeedMatchInd+1);
::difference(SelectedRegionsGray,ObjectMatched,&SelectedRegionsGray);
// 将新得到的种子点添加到种子序列中(保存row,column,area)
::tuple_concat(existVehicle.SeedX,HTuple(RowSC[long(SeedMatchInd[0])]),&(existVehicle.SeedX));
::tuple_concat(existVehicle.SeedY,HTuple(ColumnSC[long(SeedMatchInd[0])]),&(existVehicle.SeedY));
::tuple_concat(existVehicle.SeedArea,HTuple(AreaSC[long(SeedMatchInd[0])]),&(existVehicle.SeedArea));
//将得到的图像坐标(row,column)转化为世界坐标(Qx,Qy)--(实质上是二维至二维)
HTuple Qx,Qy,Qw,XResult,YResult;
::projective_trans_point_2d(HomMat2D,HTuple(RowSC[long(SeedMatchInd[0])]),HTuple(ColumnSC[long(SeedMatchInd[0])]),HTuple(1),&Qx,&Qy,&Qw);
XResult = Qx/Qw;
YResult = Qy/Qw;
// 求得两点间的距离及目标运动速度
HTuple dist=HTuple((existVehicle.WorldX[SeedNum-1]-XResult)*(existVehicle.WorldX[SeedNum-1]-XResult)+(existVehicle.WorldY[SeedNum-1]-YResult)*(existVehicle.WorldY[SeedNum-1]-YResult)).Sqrt() ;
HTuple v=dist/HTuple(FrameTime);
// 记录新种子点的世界坐标和运动速度
::tuple_concat(existVehicle.WorldX,XResult,&(existVehicle.WorldX));
::tuple_concat(existVehicle.WorldY,YResult,&(existVehicle.WorldY));
::tuple_concat(existVehicle.Velocity,v,&(existVehicle.Velocity));
}
else // 未找到新种子点则跟踪断裂
{
existVehicle.isEnd=true;
existVehicle.FrameEnd=FrameSerialNum;
}
}
else
{
existVehicle.isEnd=true;
existVehicle.FrameEnd=FrameSerialNum;
}
Vehicles.SetAt(i,existVehicle);
}
}
//***第三步:对临时种子点进行轨迹跟踪**********************************************************
// 临时种子点即为轨迹还只存储过一个点的目标质点;
// 下面的SelectedRegionsGray是第二步选择后的结果,即已经剔除了那些成功匹配的区域
// (RowNS,ColumnNS)和AreaNS分别为临时种子点对应区域的中心点坐标和面积,LenNS=AreaNS的平方根。
// 注意:倘若临时种子点成功匹配到一个新点,则其与新点同时升级为种子点,同时保存其相关信息!!!!
for(int r=0;r<AreaNS.Num();r++) //NS----new seed
{
::select_shape(SelectedRegionsGray,&ObjRegionCandinates,HTuple("row").Concat("column"),HTuple("and"),
(HTuple(RowNS[r])-HTuple(LenNS[r])).Concat(HTuple(ColumnNS[r])-HTuple(LenNS[r])),
(HTuple(RowNS[r])+HTuple(LenNS[r])).Concat(HTuple(ColumnNS[r])+HTuple(LenNS[r])));
::area_center(ObjRegionCandinates,&AreaSC,&RowSC,&ColumnSC);//计算候选区域面积,中心坐标
if ((AreaSC.Num())!=0)
{
TraceBest(HTuple(RowNS[r]),ColumnNS[r],HTuple(0),HTuple(0),AreaSC,RowSC,ColumnSC,HTuple(AreaNS[r]),&SeedMatchInd);
if ((SeedMatchInd.Num())!=0) // 成功匹配则保存!
{
::select_obj(ObjRegionCandinates,&ObjectMatched,SeedMatchInd+1);
::difference(SelectedRegionsGray,ObjectMatched,&SelectedRegionsGray); //剔除匹配过的点
// 将临时种子点之RowNS,ColumnNS,AreaNS及其相应的世界坐标添加到newVehicle的尾部
Vehicle newVehicle;
::tuple_concat(newVehicle.SeedX,RowNS[r],&newVehicle.SeedX);
::tuple_concat(newVehicle.SeedY,ColumnNS[r],&newVehicle.SeedY);
::tuple_concat(newVehicle.SeedArea,AreaNS[r],&newVehicle.SeedArea);
// 图像平面坐标向二维世界坐标转换
HTuple Qx1,Qy1,Qw1,XResult1,YResult1;
::projective_trans_point_2d(HomMat2D,RowNS[r],ColumnNS[r],HTuple(1),&Qx1,&Qy1,&Qw1);
XResult1 = Qx1/Qw1;
YResult1 = Qy1/Qw1;
::tuple_concat(newVehicle.WorldX,XResult1,&(newVehicle.WorldX));
::tuple_concat(newVehicle.WorldY,YResult1,&(newVehicle.WorldY));
// 将新匹配成功的候选点之RowSC,ColumnSC,AreaSC及其相应的世界坐标添加到newVehicle的尾部
::tuple_concat(newVehicle.SeedX,HTuple(RowSC[long(SeedMatchInd[0])]),&(newVehicle.SeedX));
::tuple_concat(newVehicle.SeedY,HTuple(ColumnSC[long(SeedMatchInd[0])]),&(newVehicle.SeedY));
::tuple_concat(newVehicle.SeedArea,HTuple(AreaSC[long(SeedMatchInd[0])]),&(newVehicle.SeedArea));
// 图像平面坐标向二维世界坐标转换
HTuple Qx2,Qy2,Qw2,XResult2,YResult2;
::projective_trans_point_2d(HomMat2D,HTuple(RowSC[long(SeedMatchInd[0])]),HTuple(ColumnSC[long(SeedMatchInd[0])]),HTuple(1),&Qx2,&Qy2,&Qw2);
XResult2 = Qx2/Qw2;
YResult2 = Qy2/Qw2;
::tuple_concat(newVehicle.WorldX,XResult2,&(newVehicle.WorldX));
::tuple_concat(newVehicle.WorldY,YResult2,&(newVehicle.WorldY));
// 计算两点之间的距离及目标运动速度
HTuple dist=HTuple((XResult2-XResult1)*(XResult2-XResult1)+(YResult2-YResult1)*(YResult2-YResult1)).Sqrt() ;
HTuple v=dist/HTuple(FrameTime);
::tuple_concat(newVehicle.Velocity,v,&(newVehicle.Velocity));
// 记录新轨迹开始的起始帧号,并将新发现的具有轨迹链的目标添加到运动目标中
newVehicle.FrameStart=FrameSerialNum-1;
newVehicle.isEnd=false;
Vehicles.Add(newVehicle);
}
}
}
//////////////////Trace Join 轨迹连接
/*
HTuple FrameSubs,AreaSubs,Distances,AngleSubs,VehicleIndex;
HTuple FrameSubsMAX,AreaSubsMAX,DistancesMAX,AngleSubsMAX;
for (int f=0; f<Vehicles.GetSize(); f++)
{
Vehicle existVehicle=Vehicles.GetAt(f);
if(existVehicle.isEnd==true)
if(k-existVehicle.FrameEnd<10)
{
int SeedNum=existVehicle.SeedX.Num();
int FrameSub;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -