771 lines
26 KiB
C++
771 lines
26 KiB
C++
#include "Fast2D.h"
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include "memory.h"
|
|
//#pragma optimize("",off)
|
|
|
|
s32 Copied = 0;
|
|
/*************************************************************************************************************/
|
|
/*************************************************************************************************************/
|
|
/********* BEGIN RANSAC ****************************************************************************************/
|
|
/*************************************************************************************************************/
|
|
/*************************************************************************************************************/
|
|
u32 CFast2D::FB_init = 1;
|
|
Fast2DFeatureBox CFast2D::FB_Table[MAX_FEATBOX];
|
|
void DRawTEXT_Soft_B(u8 *pTEXT,u32 *pBase,u32 X, u32 Y, s32 Pitch , u32 Height , u32 Color);
|
|
|
|
u32 CFast2D::EvaluateNumber(u8 *Valid , u32 ulNumber)
|
|
{
|
|
u32 Result = 0,Counter = ulNumber;
|
|
while (Counter--){ if (*(Valid++) == 1) Result++;}
|
|
return Result;
|
|
}
|
|
/* Compute Error from estimation matrix by projecting Lastpos and compare it with Newpos */
|
|
float CFast2D::EvaluateError(u8 *Valid , u32 ulNumber, const Vector *Lastpos , const Vector *Newpos , MATRIX *Matrix23 , float Threshold)
|
|
{
|
|
float Error = 0.0f , Pond = 0.0f;
|
|
u32 Counter = ulNumber;
|
|
while (Counter--)
|
|
{
|
|
if (*(Valid))
|
|
{
|
|
Vector Result;
|
|
Result = *Matrix23 * *Lastpos;
|
|
float ErrorLocal = (*Newpos - Result).NormXY();
|
|
//Newpos->z = 1.0f / (ErrorLocal+1.0f);
|
|
if (ErrorLocal < Threshold)
|
|
{
|
|
if (*(Valid) == 1)
|
|
{
|
|
Error += ErrorLocal;
|
|
Pond++;
|
|
}//*/
|
|
*(Valid) = 1;
|
|
} else
|
|
*(Valid) = 2;
|
|
}
|
|
Valid++;
|
|
Newpos++;
|
|
Lastpos++;
|
|
}
|
|
if (Pond)
|
|
return Error/(float)Pond;
|
|
else
|
|
return 0.0f;
|
|
|
|
}
|
|
|
|
// Compute gravity center of the set by pondere it with Z ( = Matching quality )
|
|
u32 CFast2D::ComputeGCXY(u8 *Valid , u32 ulNumber , const Vector *Positions , Vector *GCenter )
|
|
{
|
|
*GCenter = Vector(0,0,0);
|
|
u32 Counter = ulNumber;
|
|
while (Counter--)
|
|
{
|
|
if (*(Valid++) == 1)
|
|
{
|
|
GCenter->x += Positions->x;
|
|
GCenter->y += Positions->y;
|
|
GCenter->z ++;
|
|
}
|
|
Positions++;
|
|
}
|
|
if (GCenter->z)
|
|
{
|
|
GCenter->x /= GCenter->z;
|
|
GCenter->y /= GCenter->z;
|
|
return 1;
|
|
} else
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
Compute scale factor from GravityCenter 1 & 2
|
|
*/
|
|
float CFast2D::ComputeGCScale(u8 *Valid , u32 ulNumber , const Vector *Lastpos , const Vector *Newpos , Vector *LastGC, Vector *NewGC , float *Scale , float *Angle)
|
|
{
|
|
float R1 = 0.0f, R2 = 0.0f,SinusAlpha = 0.0f , Pond = 0.0f , CosAlpha = 0.0f;
|
|
u32 Counter1 = ulNumber,RES = 0;
|
|
while (Counter1--)
|
|
{
|
|
if (*(Valid++) == 1)
|
|
{
|
|
float LastNorm = (*Lastpos - *LastGC).NormXY();
|
|
float NewNorm = (*Newpos - *NewGC).NormXY();
|
|
if (LastNorm * NewNorm > 2.0f*2.0f)
|
|
{
|
|
R1 += LastNorm ;
|
|
R2 += NewNorm ;
|
|
Vector V1,V2;
|
|
V1 = (*Lastpos - *LastGC);
|
|
V2 = (*Newpos - *NewGC);
|
|
V1.z = V2.z = 0.0f;
|
|
V1 *= NewNorm / V1.NormXY();
|
|
V2 *= 1.0f / V2.NormXY();
|
|
SinusAlpha += Newpos->z * (V1 ^ V2).z;
|
|
CosAlpha += Newpos->z * (V1 * V2);
|
|
Pond += Newpos->z * NewNorm/** NewNorm * LastNorm*/;
|
|
RES++;
|
|
}
|
|
}
|
|
Newpos++;
|
|
Lastpos++;
|
|
}
|
|
Valid-=ulNumber;
|
|
*Scale = 1.0f;
|
|
*Angle = 0.0f;
|
|
if (R1 * R2 != 0.0f)
|
|
{
|
|
//*Scale = R2 / R1 ;
|
|
if (Pond)
|
|
{
|
|
|
|
*Angle = asinf(SinusAlpha / Pond);
|
|
if (CosAlpha < 0)
|
|
*Angle = 3.1415927f - *Angle;
|
|
if (*Angle > 3.1415927f / 4) *Angle = 3.1415927f / 4;
|
|
if (*Angle < -3.1415927f / 4) *Angle = -3.1415927f / 4;
|
|
}
|
|
/* Compute Ratio Y */
|
|
}
|
|
return Pond;
|
|
}
|
|
|
|
void CFast2D::ComputeGCXYScale(u8 *Valid , u32 ulNumber , const Vector *Lastpos , const Vector *Newpos , Vector *YAxis,float *XScale,float *YScale)
|
|
{
|
|
float YPreviousSQR = 0,YPrevious = 0;
|
|
float YCurrentSQR = 0,YCurrent = 0;
|
|
float XPreviousSQR = 0,XPrevious = 0;
|
|
float XCurrentSQR = 0,XCurrent = 0;
|
|
float Pond = 0.0f ;
|
|
u32 Counter1 = ulNumber,RES = 0;
|
|
while (Counter1--)
|
|
{
|
|
if (*(Valid++) == 1)
|
|
{
|
|
float P = 1.0f;
|
|
float DPNew = (Newpos->x * YAxis->x + Newpos->y * YAxis->y) ;
|
|
YCurrentSQR += DPNew * DPNew * P ;
|
|
YCurrent += DPNew * P;
|
|
float DPOld = (Lastpos->x * YAxis->x + Lastpos->y * YAxis->y) ;
|
|
YPreviousSQR += DPOld * DPOld* P ;
|
|
YPrevious += DPOld* P ;
|
|
DPNew = (Newpos->x * YAxis->y - Newpos->y * YAxis->x) ;
|
|
XCurrentSQR += DPNew * DPNew* P ;
|
|
XCurrent += DPNew* P ;
|
|
DPOld = (Lastpos->x * YAxis->y - Lastpos->y * YAxis->x) ;
|
|
XPreviousSQR += DPOld * DPOld* P ;
|
|
XPrevious += DPOld* P ;
|
|
Pond += P ;
|
|
RES++;
|
|
}
|
|
Newpos++;
|
|
Lastpos++;
|
|
}
|
|
float OoP = 1.0f/Pond;
|
|
YPrevious = sqrtf(OoP * YPreviousSQR - OoP * OoP * YPrevious * YPrevious );
|
|
YCurrent = sqrtf(OoP * YCurrentSQR - OoP * OoP * YCurrent * YCurrent );
|
|
XPrevious = sqrtf(OoP * XPreviousSQR - OoP * OoP * XPrevious * XPrevious );
|
|
XCurrent = sqrtf(OoP * XCurrentSQR - OoP * OoP * XCurrent * XCurrent );
|
|
*YScale = YCurrent / YPrevious ;
|
|
*XScale = XCurrent / XPrevious ;
|
|
#define LIMITSCALE 0.25
|
|
if (*YScale < 0.25f) *YScale = 0.25f;
|
|
if (*YScale > 4.f) *YScale = 4.f;
|
|
if (*XScale < 0.25f) *XScale = 0.25f;
|
|
if (*XScale > 4.f) *XScale = 4.f;
|
|
}
|
|
|
|
/*
|
|
Try to find the best projection matrix as possible.
|
|
*/
|
|
float CFast2D::FeatureBoxRansac(u8 *Valid , u32 ulNumber , const Vector *LastPosition , const Vector *NewPosition , Vector *SpeedScaleDest , float *Rotation,Fast2DFeatureBox *pFB ,float LowLimit)
|
|
{
|
|
MATRIX Estim,Estim2,Covariance,InvCovariance;
|
|
Vector OldGC,NewGC,Speed,NewT;
|
|
float ErrorEst,Sclae,Rot,ErrorFactor;
|
|
u32 Converge = 10;
|
|
Sclae = 1.0f;
|
|
Rot = 0.0f;
|
|
ErrorFactor = 1.0f;
|
|
u32 FullMatrixMode = pFB->FixeMode * 3;
|
|
|
|
#define DOOMA LastPosition
|
|
#define DOOMB NewPosition
|
|
while (Converge--)
|
|
{
|
|
if (EvaluateNumber(Valid,ulNumber) < ulNumber * 0.75f) FullMatrixMode = 0;
|
|
|
|
/* 1 Evaluate a Speed */
|
|
ComputeGCXY(Valid ,ulNumber, DOOMA , &OldGC );
|
|
ComputeGCXY(Valid ,ulNumber, DOOMB , &NewGC );
|
|
if (FullMatrixMode)
|
|
{
|
|
/* Full matrix evaluation */
|
|
memset(&Covariance,0,sizeof(Covariance));
|
|
float RealNum = 0.0f;
|
|
|
|
Vector I = Vector(0,0,0);
|
|
Vector J = Vector(0,0,0);
|
|
Vector Res = Vector(0,0,0);
|
|
for (u32 i = 0; i < ulNumber ; i++)
|
|
{
|
|
if (Valid[i] == 1)
|
|
{
|
|
Vector Last,New;
|
|
Last = DOOMA[i] - OldGC;
|
|
New = DOOMB[i] - NewGC;
|
|
Covariance.I.x += Last.x * Last.x;
|
|
Covariance.I.y += Last.x * Last.y;
|
|
Covariance.J.y += Last.y * Last.y;
|
|
I.x += Last.x * New.x;
|
|
I.y += Last.y * New.x;
|
|
J.x += Last.x * New.y;
|
|
J.y += Last.y * New.y;
|
|
RealNum+=1.0f;
|
|
}
|
|
}
|
|
RealNum = 1.0f / RealNum;
|
|
Covariance.I *= RealNum;
|
|
Covariance.J *= RealNum;
|
|
Covariance.J.x = Covariance.I.y;
|
|
I *= RealNum;
|
|
J *= RealNum;
|
|
Covariance.K.z = 1;
|
|
Covariance.Inverse(InvCovariance);
|
|
I = InvCovariance * I;
|
|
J = InvCovariance * J;
|
|
Estim.Identity();
|
|
Estim2.Identity();
|
|
Estim2.T = OldGC * -1;
|
|
I -= Vector(1,0,0);
|
|
J -= Vector(0,1,0);
|
|
float LocalN = I.NormXY() + J.NormXY();
|
|
#define Smooth 0.25f
|
|
if (LocalN < Smooth)
|
|
{
|
|
LocalN = 15*LocalN / Smooth;
|
|
LocalN += 1;
|
|
LocalN /= 16;
|
|
I = I * LocalN ;
|
|
J = J * LocalN ;
|
|
}
|
|
I += Vector(1,0,0);
|
|
J += Vector(0,1,0);
|
|
Estim.I.x = I.x;
|
|
Estim.J.x = I.y;
|
|
Estim.I.y = J.x;
|
|
Estim.J.y = J.y;
|
|
Estim.T = NewGC;
|
|
Estim.T.z = 0;
|
|
Estim2 *= Estim;
|
|
Estim =Estim2 ;
|
|
} else {
|
|
ComputeGCScale(Valid , ulNumber,DOOMA, DOOMB, &OldGC , &NewGC , &Sclae, &Rot);
|
|
ComputeGCXYScale(Valid , ulNumber , DOOMA, DOOMB, &Vector(sinf(Rot),cosf(Rot),0),&pFB->XScale,&pFB->YScale);
|
|
if (pFB->ComputeRotation == 0) Rot = 0.0f;
|
|
if (pFB->ComputeScale == 0) pFB->XScale = pFB->YScale = 1.0f;
|
|
if (!pFB->FixeMode)
|
|
{
|
|
pFB->XScale = (pFB->YScale + pFB->XScale) / 2.0f;
|
|
pFB->YScale = pFB->XScale ;
|
|
pFB->XScale = pFB->YScale = 1.0f;
|
|
}
|
|
Estim2.Identity();
|
|
Estim2.T = OldGC * -1;
|
|
Estim.Identity();
|
|
Estim.I.x = pFB->XScale;
|
|
Estim.J.y = pFB->YScale;
|
|
Estim.RotateAround_K(Rot);
|
|
Estim.T = NewGC ;
|
|
Estim.T.z = 0.0f;//*/
|
|
Estim2 *= Estim;
|
|
Estim =Estim2 ;
|
|
}
|
|
/* 4 Decimate & Reinsert */
|
|
ErrorEst = EvaluateError(Valid , ulNumber , DOOMA, DOOMB, &Estim);
|
|
EvaluateError(Valid , ulNumber , DOOMA, DOOMB, &Estim , ErrorEst * ErrorFactor + LowLimit );//*/
|
|
ErrorFactor *= 1.0f/2.0f;
|
|
}
|
|
Speed = NewGC - OldGC;
|
|
SpeedScaleDest->x = Speed.x;
|
|
SpeedScaleDest->y = Speed.y;
|
|
SpeedScaleDest->z = (pFB->XScale + pFB->YScale) / 2;
|
|
*Rotation = Rot;//*/
|
|
pFB->LastTransforMatrix = Estim;
|
|
return (float) EvaluateNumber(Valid,ulNumber);
|
|
}
|
|
/*************************************************************************************************************/
|
|
/*************************************************************************************************************/
|
|
/********* END RANSAC ****************************************************************************************/
|
|
/*************************************************************************************************************/
|
|
/*************************************************************************************************************/
|
|
|
|
|
|
void CFast2D::FeatureBoxUpdateOne(u32 Index)
|
|
{
|
|
if (FB_init) return ;
|
|
{
|
|
FB_Table[Index].ulNumberOfParticules = 0;
|
|
s32 Counter = FB_Table[Index].DXSize * FB_Table[Index].DYSize;
|
|
|
|
while (Counter--)
|
|
{
|
|
s32 cX,cY;
|
|
cX = (float)(Counter % FB_Table[Index].DXSize) * (float)FB_Table[Index].W / (float)FB_Table[Index].DXSize + FB_Table[Index].X - (float)FB_Table[Index].W/2 + (float)FB_Table[Index].W / ((float)FB_Table[Index].DXSize * 2.0f);
|
|
cY = (float)(Counter / FB_Table[Index].DXSize) * (float)FB_Table[Index].H / (float)FB_Table[Index].DYSize + FB_Table[Index].Y - (float)FB_Table[Index].H/2 + (float)FB_Table[Index].H / ((float)FB_Table[Index].DYSize * 2.0f);
|
|
FB_Table[Index].FirstPos[FB_Table[Index].ulNumberOfParticules].x = cX;
|
|
FB_Table[Index].FirstPos[FB_Table[Index].ulNumberOfParticules].y = cY;
|
|
FB_Table[Index].FirstPos[FB_Table[Index].ulNumberOfParticules].z = 1.0f;
|
|
if (FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules] == -1)
|
|
FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules] = New(cX , cY);
|
|
else
|
|
{
|
|
Set(FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules],&FB_Table[Index].FirstPos[FB_Table[Index].ulNumberOfParticules]);
|
|
}
|
|
UpdateData(FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules]);
|
|
|
|
/* Max Optimize */
|
|
u32 FalsePoint = 0;
|
|
/* float Max = GetNorm(FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules], 0);
|
|
// int CounterIter = ((int)(0.5f * (float)FB_Table[Index].W / (float)FB_Table[Index].DXSize))<<2;
|
|
Vector FinalPos = FB_Table[Index].FirstPos[FB_Table[Index].ulNumberOfParticules];
|
|
#define RadiusSearch 6*1
|
|
for(int X = -RadiusSearch + 1 ; X < RadiusSearch ; X++)
|
|
for(int Y = -RadiusSearch + 1 ; Y < RadiusSearch ; Y++)
|
|
{
|
|
Vector Srch = FB_Table[Index].FirstPos[FB_Table[Index].ulNumberOfParticules];
|
|
Srch.x += X;
|
|
Srch.y += Y;
|
|
Set(FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules],&Srch);
|
|
UpdateData(FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules]);
|
|
if (Max >= GetNorm(FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules], 0))
|
|
{
|
|
FinalPos = Srch;
|
|
Max = GetNorm(FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules], 0);
|
|
FalsePoint = 0;
|
|
}
|
|
}
|
|
FB_Table[Index].FirstPos[FB_Table[Index].ulNumberOfParticules] = FinalPos;
|
|
Set(FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules],&FB_Table[Index].FirstPos[FB_Table[Index].ulNumberOfParticules]);
|
|
UpdateData(FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules]);//*/
|
|
ComputeTrack(FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules],2);
|
|
if ((FalsePoint) || (GetError(FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules]) <= 0.6))
|
|
{
|
|
Destroy(FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules]);
|
|
FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules] = -1;
|
|
} else
|
|
{
|
|
FB_Table[Index].ParticlesPonderation[FB_Table[Index].ulNumberOfParticules] = 1.0f / GetNorm(FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules], 0);
|
|
Set(FB_Table[Index].TrackerID[FB_Table[Index].ulNumberOfParticules],&FB_Table[Index].FirstPos[FB_Table[Index].ulNumberOfParticules]);
|
|
FB_Table[Index].ulNumberOfParticules ++;
|
|
}
|
|
|
|
}
|
|
float ParticlesPonderationSumm = 0;
|
|
for (int i = 0 ; i < FB_Table[Index].ulNumberOfParticules ; i ++)
|
|
ParticlesPonderationSumm += FB_Table[Index].ParticlesPonderation[i];
|
|
ParticlesPonderationSumm = 1.0f / ParticlesPonderationSumm;
|
|
for (int i = 0 ; i < FB_Table[Index].ulNumberOfParticules ; i ++)
|
|
FB_Table[Index].ParticlesPonderation[i] *= ParticlesPonderationSumm;
|
|
}
|
|
}
|
|
u32 CFast2D::DestroyFeatureBox(u32 Index)
|
|
{
|
|
if (Index > MAX_FEATBOX) return 0;
|
|
s32 Counter = MAX_QFB;
|
|
while (Counter--) Destroy(FB_Table[Index].TrackerID[Counter]);
|
|
return 1;
|
|
}
|
|
|
|
|
|
u32 CFast2D::CreateFeatureBox(u32 Index, s32 X,s32 Y,s32 W, s32 H, float Rotation)
|
|
{
|
|
if (FB_init)
|
|
{
|
|
memset(FB_Table,0,sizeof(FB_Table));
|
|
FB_init = 0;
|
|
}
|
|
if (Index > MAX_FEATBOX) return 0;
|
|
if (FB_Table[Index].IsInit) DestroyFeatureBox(Index);
|
|
memset(FB_Table[Index].TrackerID,-1,sizeof(FB_Table[Index].TrackerID));
|
|
FB_Table[Index].IsInit = 0;//*/
|
|
FB_Table[Index].X = X + abs(W) / 2;
|
|
FB_Table[Index].Y = Y + abs(H) / 2;
|
|
FB_Table[Index].SearchX = FB_Table[Index].SearchY = 0.0f;
|
|
FB_Table[Index].W = abs(W) ;
|
|
FB_Table[Index].H = abs(H) ;
|
|
FB_Table[Index].DXSize = W / DISC_PIXEL;
|
|
FB_Table[Index].DYSize = H / DISC_PIXEL;
|
|
FB_Table[Index].BigSearchBase = 1;
|
|
if (FB_Table[Index].DXSize < 3) FB_Table[Index].DXSize = 3;
|
|
if (FB_Table[Index].DYSize < 3) FB_Table[Index].DYSize = 3;
|
|
if (FB_Table[Index].DXSize > MAX_QFB_DX) FB_Table[Index].DXSize = MAX_QFB_DX;
|
|
if (FB_Table[Index].DYSize > MAX_QFB_DY) FB_Table[Index].DYSize = MAX_QFB_DY;
|
|
if (!FB_Table[Index].IsInit)
|
|
{
|
|
s32 Counter = FB_Table[Index].DXSize * FB_Table[Index].DYSize;
|
|
while (Counter--) FB_Table[Index].TrackerID[Counter] = -1;
|
|
}
|
|
FeatureBoxUpdateOne(Index);
|
|
FB_Table[Index].IsInit = 1;
|
|
FB_Table[Index].ComputeScale = 1;
|
|
FB_Table[Index].ComputeRotation = 1;
|
|
FB_Table[Index].LearningMode = 0;
|
|
FB_Table[Index].LastTransforMatrix.Identity();
|
|
FB_Table[Index].PertinenceLimiteDown = PertinenceLimiteDownDefault;
|
|
FB_Table[Index].DontMoveMode = 0;
|
|
FB_Table[Index].PausedMode = 0;
|
|
FB_Table[Index].MINIMALERROR = MINIMALERRORDEFAULT;
|
|
FB_Table[Index].TOLERANCE = 0;
|
|
return 1;
|
|
}
|
|
|
|
void CFast2D::FeatureBoxSetParam(u32 Index,char *String , float Value)
|
|
{
|
|
u32 P = ((u32)String[0]<<0) | ((u32)String[1]<<8) | ((u32)String[2]<<16) | ((u32)String[3]<<24);
|
|
if (Index > MAX_FEATBOX) return;
|
|
if (!FB_Table[Index].IsInit) return;
|
|
switch(P)
|
|
{
|
|
case 'TURN':case 'NRUT':
|
|
FB_Table[Index].ComputeRotation = 0;
|
|
if (Value != 0.0f)
|
|
FB_Table[Index].ComputeRotation = 1;
|
|
break;
|
|
case 'SCAL':case 'LACS':
|
|
FB_Table[Index].ComputeScale = 0;
|
|
if (Value != 0.0f)
|
|
FB_Table[Index].ComputeScale = 1;
|
|
break;
|
|
case 'INIT':case 'TINI':
|
|
FB_Table[Index].FixeMode = 0;
|
|
if (Value != 0.0f)
|
|
{
|
|
FB_Table[Index].FixeMode = 1;
|
|
}
|
|
break;
|
|
case 'JUMP':case 'PMUJ':
|
|
FB_Table[Index].BigSearchBase
|
|
= 1;
|
|
if (Value != 0.0f)
|
|
{
|
|
FB_Table[Index].BigSearchBase = (int)Value;
|
|
}
|
|
break;
|
|
case 'BLND':case 'DNLB':
|
|
FB_Table[Index].BigSearchBase = 1;
|
|
if (Value != 0.0f)
|
|
{
|
|
FB_Table[Index].BigSearchBase = (int)Value;
|
|
}
|
|
break;
|
|
case 'REST':case 'TSER':
|
|
FB_Table[Index].DontMoveMode = 0;
|
|
if (Value != 0.0f)
|
|
{
|
|
FB_Table[Index].DontMoveMode = 1;
|
|
}
|
|
break;
|
|
case 'PELD':case 'DLEP':
|
|
FB_Table[Index].PertinenceLimiteDown = Value;
|
|
break;
|
|
case 'EROR':case 'RORE':
|
|
FB_Table[Index].MINIMALERROR = Value;
|
|
break;
|
|
case 'LEAR':case 'RAEL':
|
|
FB_Table[Index].LearningMode = Value;
|
|
break;
|
|
case 'TOLE':case 'ELOT':
|
|
FB_Table[Index].TOLERANCE = Value;
|
|
break;
|
|
case 'STOP':case 'POTS':
|
|
FB_Table[Index].PausedMode = 0;
|
|
if (Value != 0.0f) FB_Table[Index].PausedMode = 1;
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
u32 CFast2D::FeatureBoxGetXYS(u32 Index,Vector *Result)
|
|
{
|
|
if (Index > MAX_FEATBOX) return 0;
|
|
*Result = FB_Table[Index].LastMovesXYS;
|
|
return 1;
|
|
}
|
|
u32 CFast2D::FeatureBoxGetSXSY(u32 Index,Vector *Result)
|
|
{
|
|
if (Index > MAX_FEATBOX) return 0;
|
|
Result->x = FB_Table[Index].XScale;
|
|
Result->y = FB_Table[Index].YScale;
|
|
Result->z = FB_Table[Index].LastMovesXYS.z;
|
|
return 1;
|
|
}
|
|
u32 CFast2D::FeatureBoxGetRot(u32 Index,float *Result)
|
|
{
|
|
if (Index > MAX_FEATBOX) return 0;
|
|
*Result = FB_Table[Index].Rotation;
|
|
return 1;
|
|
}
|
|
float CFast2D::FeatureBoxGetPertinence(u32 Index)
|
|
{
|
|
if (Index > MAX_FEATBOX) return 0.0f;
|
|
return FB_Table[Index].Pertinence;
|
|
}
|
|
MATRIX *CFast2D::FeatureBoxGetMatrix(u32 Index)
|
|
{
|
|
if (Index > MAX_FEATBOX) return NULL;
|
|
return &FB_Table[Index].LastTransforMatrix;
|
|
}
|
|
|
|
u32 CFast2D::FeatureBoxFrame(MAP *DbugMap,u32 Only4Clear)
|
|
{
|
|
Vector C,NewPos[MAX_QFB],SpeedScale;
|
|
float Rotation;
|
|
u8 Valid[MAX_QFB];
|
|
if (FB_init) return 0;
|
|
for (u32 FeatBoxIndex = 0; FeatBoxIndex < MAX_FEATBOX; FeatBoxIndex++)
|
|
{
|
|
u32 DrawIt = 0;
|
|
MATRIX NewM ;
|
|
if (!FB_Table[FeatBoxIndex].IsInit) continue;
|
|
if (FB_Table[FeatBoxIndex].PausedMode)
|
|
{
|
|
FB_Table[FeatBoxIndex].Pertinence = 0;
|
|
FB_Table[FeatBoxIndex].LastMovesXYS = Vector(0,0,1);
|
|
FB_Table[FeatBoxIndex].Rotation = 0.0f;
|
|
FB_Table[FeatBoxIndex].XScale = FB_Table[FeatBoxIndex].YScale = 1.0f;
|
|
FB_Table[FeatBoxIndex].LastTransforMatrix.Identity();
|
|
continue;
|
|
}
|
|
if (!Only4Clear)
|
|
{
|
|
u32 UlNumber = FB_Table[FeatBoxIndex].ulNumberOfParticules;
|
|
u32 CounterDest = 0;
|
|
if (FB_Table[FeatBoxIndex].LearningMode) FB_Table[FeatBoxIndex].Pertinence = 0;
|
|
float FinalFactor = 0;
|
|
FB_Table[FeatBoxIndex].LastMovesXYS = Vector(0,0,1);
|
|
FB_Table[FeatBoxIndex].Rotation = 0.0f;
|
|
FB_Table[FeatBoxIndex].XScale = FB_Table[FeatBoxIndex].YScale = 1.0f;
|
|
u32 BigSearchMode = 0;
|
|
if (FB_Table[FeatBoxIndex].Pertinence < 10.0) BigSearchMode = 2;
|
|
float OldPertinence = FB_Table[FeatBoxIndex].Pertinence;
|
|
FB_Table[FeatBoxIndex].Pertinence = 0.0f;
|
|
|
|
memset(Valid , 0 , sizeof(Valid ));
|
|
if ((FeatBoxIndex & 1) && (FB_Table[FeatBoxIndex-1].Pertinence > FB_Table[FeatBoxIndex-1].PertinenceLimiteDown * 0.6666f))
|
|
goto ByPass;
|
|
|
|
for (u32 Counter = 0 ; Counter < UlNumber;Counter++)
|
|
{
|
|
//if ((OldPertinence == 0.0) && ((Counter & 1) == 0)) continue;
|
|
u32 TrackedID = FB_Table[FeatBoxIndex].TrackerID[Counter];
|
|
if (Get(TrackedID, &C))
|
|
{
|
|
s32 BigSearch = 0;
|
|
C.z = 0;
|
|
do
|
|
{
|
|
Set(TrackedID, &C);
|
|
ComputeTrack(TrackedID,BigSearch++);
|
|
} while ((GetError(TrackedID) < FB_Table[FeatBoxIndex].MINIMALERROR) && (BigSearch < FB_Table[FeatBoxIndex].BigSearchBase + BigSearchMode));
|
|
if (GetError(TrackedID) < FB_Table[FeatBoxIndex].MINIMALERROR)
|
|
{
|
|
Set(TrackedID, &C);
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
for (u32 Counter = 0 ; Counter < UlNumber;Counter++)
|
|
{
|
|
NewPos[Counter].z = 0;
|
|
if (Get(FB_Table[FeatBoxIndex].TrackerID[Counter], &C) && (C.z > FB_Table[FeatBoxIndex].MINIMALERROR) )
|
|
{
|
|
NewPos[Counter] = C;
|
|
Valid[Counter] = 1;
|
|
}
|
|
}
|
|
// LAUNCH SIMILI RANSAC ******************************************************************
|
|
s32 MustRedo = 1;
|
|
s32 MustRedoCounter = 3;
|
|
do
|
|
{
|
|
float Tolerance = FB_Table[FeatBoxIndex].FixeMode ? TOLERANSAC_FIXE: TOLERANSAC_NOTFIXE;
|
|
if (FB_Table[FeatBoxIndex].TOLERANCE != 0) Tolerance = FB_Table[FeatBoxIndex].TOLERANCE;
|
|
FeatureBoxRansac(Valid,UlNumber, FB_Table[FeatBoxIndex].FirstPos, NewPos , &SpeedScale , &Rotation , &FB_Table[FeatBoxIndex], Tolerance) ;
|
|
MustRedo = 0;
|
|
for (u32 Counter = 0 ; Counter < UlNumber;Counter++)
|
|
{
|
|
if (Valid[Counter] == 2)
|
|
{
|
|
Vector Result , FirstPos = FB_Table[FeatBoxIndex].FirstPos[Counter];
|
|
Result = FB_Table[FeatBoxIndex].LastTransforMatrix * FirstPos;
|
|
u32 TrackedID = FB_Table[FeatBoxIndex].TrackerID[Counter];
|
|
Set(TrackedID, &Result);
|
|
ComputeTrack(TrackedID,0);
|
|
if (GetError(TrackedID) > FB_Table[FeatBoxIndex].MINIMALERROR )
|
|
{
|
|
Get(FB_Table[FeatBoxIndex].TrackerID[Counter], &Result);
|
|
NewPos[Counter] = Result;
|
|
Valid[Counter] = 1;
|
|
MustRedo = 1;
|
|
}
|
|
}
|
|
}
|
|
MustRedoCounter--;
|
|
} while (MustRedo && MustRedoCounter);
|
|
FB_Table[FeatBoxIndex].Pertinence = floor(100.0f * EvaluateNumber(Valid , UlNumber ) / (float)UlNumber );
|
|
|
|
|
|
for (u32 Counter = 0 ; Counter < UlNumber;Counter++)
|
|
{
|
|
if (Valid[Counter] == 1)
|
|
{
|
|
float Factor = NewPos[Counter].z * 1.25f;//FB_Table[FeatBoxIndex].ParticlesPonderation[Counter];
|
|
if (Factor > 1.0f) Factor = 1.0f;
|
|
|
|
Factor = FB_Table[FeatBoxIndex].ParticlesPonderation[Counter] * NewPos[Counter].z * 1.25f;
|
|
|
|
FinalFactor += Factor;
|
|
CounterDest++;
|
|
}
|
|
}
|
|
if (CounterDest>3)
|
|
{
|
|
FB_Table[FeatBoxIndex].LastMovesXYS = SpeedScale;
|
|
FB_Table[FeatBoxIndex].Rotation = Rotation;
|
|
}
|
|
|
|
|
|
if (CounterDest > 4)
|
|
{
|
|
//FinalFactor /= (float)CounterDest;
|
|
FB_Table[FeatBoxIndex].Pertinence *= FinalFactor;
|
|
FB_Table[FeatBoxIndex].Pertinence = (float)(int)FB_Table[FeatBoxIndex].Pertinence;
|
|
/*if (!FB_Table[FeatBoxIndex].LearningMode)
|
|
FB_Table[FeatBoxIndex].Pertinence = OldPertinence * PertinenceBlend + FB_Table[FeatBoxIndex].Pertinence * (1.0f - PertinenceBlend);*/
|
|
// FB_Table[FeatBoxIndex].Pertinence = FB_Table[FeatBoxIndex].Pertinence ;
|
|
}
|
|
else
|
|
FB_Table[FeatBoxIndex].Pertinence = 0;
|
|
|
|
|
|
|
|
if (FB_Table[FeatBoxIndex].Pertinence < FB_Table[FeatBoxIndex].PertinenceLimiteDown / 2)
|
|
{
|
|
FB_Table[FeatBoxIndex].LastMovesXYS.x = FB_Table[FeatBoxIndex].LastMovesXYS.y = 0.0f;
|
|
FB_Table[FeatBoxIndex].LastMovesXYS.z = 1.0f;
|
|
FB_Table[FeatBoxIndex].Rotation = 0.0f;
|
|
FB_Table[FeatBoxIndex].XScale = FB_Table[FeatBoxIndex].YScale = 1.0f;
|
|
FB_Table[FeatBoxIndex].LastTransforMatrix.Identity();
|
|
}
|
|
ByPass:
|
|
NewM = FB_Table[FeatBoxIndex].LastTransforMatrix;
|
|
if (FB_Table[FeatBoxIndex].LearningMode || FB_Table[FeatBoxIndex].DontMoveMode) NewM.Identity();
|
|
if ((FeatBoxIndex & 1) && (FB_Table[FeatBoxIndex -1].Pertinence > FB_Table[FeatBoxIndex -1].PertinenceLimiteDown * 0.6666f))
|
|
{
|
|
// Help From Static
|
|
FB_Table[FeatBoxIndex].LastTransforMatrix = FB_Table[FeatBoxIndex-1].LastTransforMatrix;
|
|
NewM = FB_Table[FeatBoxIndex].LastTransforMatrix;
|
|
FB_Table[FeatBoxIndex].LastMovesXYS = FB_Table[FeatBoxIndex-1].LastMovesXYS;
|
|
FB_Table[FeatBoxIndex].Rotation = FB_Table[FeatBoxIndex-1].Rotation;
|
|
FB_Table[FeatBoxIndex].XScale = FB_Table[FeatBoxIndex-1].YScale;
|
|
FB_Table[FeatBoxIndex].YScale = FB_Table[FeatBoxIndex-1].YScale;
|
|
FB_Table[FeatBoxIndex].Pertinence = 100;
|
|
DrawIt = 1;
|
|
}
|
|
|
|
u32 Done = 0;
|
|
for (u32 Counter = 0 ; Counter < UlNumber;Counter++)
|
|
{
|
|
Vector Result , FirstPos ;
|
|
|
|
FirstPos = FB_Table[FeatBoxIndex].FirstPos[Counter];
|
|
Result = NewM * FirstPos;
|
|
Result.z = NewPos[Counter].z;
|
|
if (Valid[Counter] != 1) Result.z = 0;
|
|
|
|
Set(FB_Table[FeatBoxIndex].TrackerID[Counter], &Result);
|
|
//if (Valid[Counter] != 1) UpdateData(FB_Table[FeatBoxIndex].TrackerID[Counter]);
|
|
if (!FB_Table[FeatBoxIndex].FixeMode)
|
|
{
|
|
float L = (FirstPos -NewPos[Counter]).SqrNormXY();
|
|
if (L > 1)
|
|
UpdateData(FB_Table[FeatBoxIndex].TrackerID[Counter]);
|
|
}
|
|
if (DbugMap)
|
|
{
|
|
if (FB_Table[FeatBoxIndex].ParticlesPonderation[Counter] > 0.01)
|
|
CopyDataRGBA(DbugMap,
|
|
TRACKSTACK[FB_Table[FeatBoxIndex].TrackerID[Counter]].InitMap ,
|
|
TRACKSTACK[FB_Table[FeatBoxIndex].TrackerID[Counter]].X ,
|
|
TRACKSTACK[FB_Table[FeatBoxIndex].TrackerID[Counter]].Y , F2DT8Size ,
|
|
TRACKSTACK[FB_Table[FeatBoxIndex].TrackerID[Counter]].Norm[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
if (DbugMap)
|
|
{
|
|
RECT r;
|
|
r.right = FB_Table[FeatBoxIndex].LastMovesXYS.x + FB_Table[FeatBoxIndex].X - FB_Table[FeatBoxIndex].XScale * FB_Table[FeatBoxIndex].W / 2;
|
|
r.top = FB_Table[FeatBoxIndex].LastMovesXYS.y + FB_Table[FeatBoxIndex].Y - FB_Table[FeatBoxIndex].YScale * FB_Table[FeatBoxIndex].H / 2;
|
|
r.left = r.right + FB_Table[FeatBoxIndex].XScale * FB_Table[FeatBoxIndex].W ;
|
|
r.bottom = r.top + FB_Table[FeatBoxIndex].YScale * FB_Table[FeatBoxIndex].H ;
|
|
if (FB_Table[FeatBoxIndex].Pertinence>FB_Table[FeatBoxIndex].PertinenceLimiteDown)
|
|
{
|
|
Vector Center ;
|
|
NewM = FB_Table[FeatBoxIndex].LastTransforMatrix;
|
|
Center.x = FB_Table[FeatBoxIndex].X ;
|
|
Center.y = FB_Table[FeatBoxIndex].Y ;
|
|
Center = NewM * Center;
|
|
Vector XAXIs = Vector(FB_Table[FeatBoxIndex].W*0.5,0,0);
|
|
Vector YAXIs = Vector(0,FB_Table[FeatBoxIndex].H*0.5,0);
|
|
NewM.T = Vector(0,0,0);
|
|
XAXIs = NewM * XAXIs;
|
|
YAXIs = NewM * YAXIs;
|
|
void DrawLine_Clip(MAP *MapDST,float X1,float Y1,float X2,float Y2,u32 Color);
|
|
for (int epx = -1 ;epx < 2 ; epx ++)
|
|
for (int epy = -1 ;epy < 2 ; epy ++)
|
|
{
|
|
DrawLine_Clip(DbugMap,
|
|
epx+(Center + XAXIs + YAXIs).x,epy+(Center + XAXIs + YAXIs).y,
|
|
epx+(Center - XAXIs + YAXIs).x,epy+(Center - XAXIs + YAXIs).y,
|
|
FB_Table[FeatBoxIndex].FixeMode?0xff0000:(Copied ? 0xffff00:0xff00ff));
|
|
DrawLine(DbugMap,
|
|
epx+(Center + XAXIs - YAXIs).x,epy+(Center + XAXIs - YAXIs).y,
|
|
epx+(Center - XAXIs - YAXIs).x,epy+(Center - XAXIs - YAXIs).y,
|
|
FB_Table[FeatBoxIndex].FixeMode?0xff0000:(Copied ? 0xffff00:0xff00ff));
|
|
DrawLine(DbugMap,
|
|
epx+(Center + XAXIs - YAXIs).x,epy+(Center + XAXIs - YAXIs).y,
|
|
epx+(Center + XAXIs + YAXIs).x,epy+(Center + XAXIs + YAXIs).y,
|
|
FB_Table[FeatBoxIndex].FixeMode?0xff0000:(Copied ? 0xffff00:0xff00ff));
|
|
DrawLine(DbugMap,
|
|
epx+(Center - XAXIs + YAXIs).x,epy+(Center - XAXIs + YAXIs).y,
|
|
epx+(Center - XAXIs - YAXIs).x,epy+(Center - XAXIs - YAXIs).y,
|
|
FB_Table[FeatBoxIndex].FixeMode?0xff0000:(Copied ? 0xffff00:0xff00ff));
|
|
}
|
|
//DrawQuad_R(DbugMap,r.right,r.top,r.left,r.bottom,FB_Table[FeatBoxIndex].FixeMode?0xff0000:(Copied ? 0xffff00:0xff00ff),FB_Table[FeatBoxIndex].FixeMode?4:3,FB_Table[FeatBoxIndex].Rotation);
|
|
}
|
|
|
|
|
|
char DEBUGTEXT[2048];
|
|
void DRawTEXT_Soft_B(u8 *pTEXT,u32 *pBase,u32 X, u32 Y, s32 Pitch , u32 Height , u32 Color);
|
|
sprintf(DEBUGTEXT,"%d",(u32)(FB_Table[FeatBoxIndex].YScale * 100));//,SPm.SX * SPm.SY ,CHKDBG*100 / (SPm.SX * SPm.SY));
|
|
// DRawTEXT_Soft_B((u8*)DEBUGTEXT , (u32*)DbugMap->GetBase() , 16 , 32 + 16 * FeatBoxIndex, DbugMap->PITCH , DbugMap->SY , 0xff00ff );
|
|
r.right = FB_Table[FeatBoxIndex].X - 5;
|
|
r.top = FB_Table[FeatBoxIndex].Y - 5;
|
|
r.left = FB_Table[FeatBoxIndex].X + 5;
|
|
r.bottom = FB_Table[FeatBoxIndex].Y + 5;
|
|
DrawQuad_R(DbugMap,r.right,r.top,r.left,r.bottom,0xffff00,3,0);
|
|
}
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|