JD2022-TU1/main/extern/Camcam/HeadTracker/FERN.cpp

1777 lines
No EOL
49 KiB
C++

#include "memory.h"
#include "HeadTracker.h"
#include "Fern.h"
#include "stdlib.h"
#include "math.h"
extern u32 ConstantRandom();
extern unsigned short RandBase;
u32 LastErrorDetected;
Ferns FernUsed[8][NUM_OF_FERNS];
Ferns FernOptimsed[8][NUM_OF_FERNS];
#define ERROR_T (NUM_OF_FERNS - 4)//(NUM_OF_FERNS>>5))
void FERN_InitBase(LearnBase *Ret)
{
/* Init ferns */
Ret->p_FernUsed = Ret->FernUsed[0];
RandBase = 0;
for (u32 Counter = 0 ; Counter < NUM_OF_FERNS ; Counter++)
{
u32 CounterComp;
CounterComp = NUM_OF_BINTEST;
while(CounterComp--)
{
s32 X,Y,X2,Y2;
do{
X = ConstantRandom()%PatchSize;
Y = ConstantRandom()%PatchSize;
} while (((X - (PatchSize>>1))*(X - (PatchSize>>1)) + (Y - (PatchSize>>1)) * (Y - (PatchSize>>1)) > ((PatchSize * PatchSize) >> 2))) ;
Ret->FernUsed[0][Counter].Compar[CounterComp * 2 + 0] = X + (Y << 8);
Ret->FernUsed[8][Counter].Compar[CounterComp * 2 + 0] = (PatchSize - X) + (Y << 8);
X2 = X;
Y2 = Y;
do{
X = ConstantRandom()%PatchSize;
Y = ConstantRandom()%PatchSize;
} while (
((X - (PatchSize>>1))*(X - (PatchSize>>1)) + (Y - (PatchSize>>1)) * (Y - (PatchSize>>1)) > ((PatchSize * PatchSize) >> 2)) &&
((X - X2)*(X - X2) + (Y - Y2) * (Y - Y2) < (2*2)) &&
((X - X2)*(X - X2) + (Y - Y2) * (Y - Y2) > (7*7)) //*/
)//*/
;
Ret->FernUsed[0][Counter].Compar[CounterComp * 2 + 1] = X + (Y << 8);
Ret->FernUsed[8][Counter].Compar[CounterComp * 2 + 1] = (PatchSize - X) + (Y << 8);
for (u32 RotateCounter = 1; RotateCounter < 4 ; RotateCounter++)
{
s32 Swap;
Swap = Y2;
Y2 = X2;
X2 = PatchSize-Swap;
Ret->FernUsed[RotateCounter][Counter].Compar[CounterComp * 2 + 0] = X2 + (Y2 << 8);
Swap = Y;
Y = X;
X = PatchSize-Swap;
Ret->FernUsed[RotateCounter][Counter].Compar[CounterComp * 2 + 1] = X + (Y << 8);
}
for (u32 RotateCounter = 4; RotateCounter < 8 ; RotateCounter++)
{
#define COS_45 0.70710678118654752440084436210485f
X2 = (Ret->FernUsed[RotateCounter - 4][Counter].Compar[CounterComp * 2 + 0] & 0xff) - (PatchSize>>1);
Y2 =((Ret->FernUsed[RotateCounter - 4][Counter].Compar[CounterComp * 2 + 0] >> 8) & 0xff) - (PatchSize>>1);
X = (s32)(0.5f + ((float)X2 * COS_45) + ((float)Y2 * COS_45) + (float)(PatchSize>>1));
Y = (s32)(0.5f - ((float)X2 * COS_45) + ((float)Y2 * COS_45) + (float)(PatchSize>>1));
if (X < 0) X = 0;
if (Y < 0) Y = 0;
Ret->FernUsed[RotateCounter][Counter].Compar[CounterComp * 2 + 0] = X + (Y << 8);
X2 = (Ret->FernUsed[RotateCounter - 4][Counter].Compar[CounterComp * 2 + 1] & 0xff) - (PatchSize>>1);
Y2 =((Ret->FernUsed[RotateCounter - 4][Counter].Compar[CounterComp * 2 + 1] >> 8) & 0xff) - (PatchSize>>1);
X = (s32)(0.5f + ((float)X2 * COS_45) + ((float)Y2 * COS_45) + (float)(PatchSize>>1));
Y = (s32)(0.5f - ((float)X2 * COS_45) + ((float)Y2 * COS_45) + (float)(PatchSize>>1));
if (X < 0) X = 0;
if (Y < 0) Y = 0;
Ret->FernUsed[RotateCounter][Counter].Compar[CounterComp * 2 + 1] = X + (Y << 8);
}
}
}
}
/* ValidateFern : Called after load */
void ValidateFern(LearnBase *LB)
{
FERN_InitBase(LB);
LB->p_FernUsed = &LB->FernOptimsed[LB->ActiveFern][0];
LB->Pitch = 7;
}
u32 FERN_PatchKnowledgeSize(LearnBase*LB)
{
return ((LB->PatchNumber) * (1<<NUM_OF_BINTEST) * NUM_OF_FERNS) >> 3;
}
u32 FERN_LOAD(FILE *F,LearnBase**LB)
{
u32 LN;
fread((void*)&LN,1,4,F);
if (LN == 0xC1DE0001) // Good Version Number
{
*LB = (LearnBase*)malloc(sizeof(LearnBase));
fread((void*)*LB,1,sizeof(LearnBase),F);
(*LB)->PatchKnowledge = (LEARN_TYPE *)malloc(FERN_PatchKnowledgeSize(*LB));
fread((void*)(*LB)->PatchKnowledge,1,FERN_PatchKnowledgeSize(*LB),F);
fread((void*)&LN,1,4,F);
(*LB)->ActiveFern = 0;
(*LB)->p_FernUsed = &FernOptimsed[(*LB)->ActiveFern][0];
(*LB)->Pitch = 7;
if (LN == 0xC1DE0001) // Good Version Number
return 1;
}
return 0;
}
void FERN_SAVE(FILE *F,LearnBase*LB)
{
u32 LN;
LN = 0xC1DE0001;
fwrite((void*)&LN,1,4,F);
fwrite((void*)LB,1,sizeof(LearnBase),F);
fwrite((void*)LB->PatchKnowledge,1,FERN_PatchKnowledgeSize(LB),F);
LN = 0xC1DE0001;
fwrite((void*)&LN,1,4,F);
}
u32 FERN_GetPatchBestResponse(LearnBase *LB, u32 *BWIm , u32 Optim )
{
u8 Results[MAX_NUM_OF_PATCH+8];
u32 *FernKnRes;
u32 FASTER;
LEARN_TYPE *FernKnParser;
Ferns *FernS,*FernL,*FernFaster;
FernS = LB->p_FernUsed;
FernKnParser = LB->PatchKnowledge;
FernL = FernS + NUM_OF_FERNS;
FernFaster = FernS + 8;
memset(Results,0,LB->PatchNumber+8);
FASTER = 0;
LastErrorDetected = 0;
while (FernS < FernL)
{
s32 *PatchStatB,*PatchStatL,Indx;
PatchStatB = FernS->Compar;
PatchStatL = PatchStatB + NUM_OF_BINTEST*2;
Indx = 0;
while (PatchStatB < PatchStatL)
{
u32 Compare;
Indx += Indx;
Compare = *(BWIm + *(PatchStatB++));
Compare -= *(BWIm + *(PatchStatB++));
Indx |= Compare>>31;
}
LEARN_TYPE *FernKnS,*FernKnE;
FernKnS = FernKnParser + ((Indx * LB->PatchNumber)>>5);
FernKnE = FernKnS + (LB->PatchNumber>>5);
FernKnRes = (u32*)Results;
while (FernKnS < FernKnE)
{
u32 MASK,*FernKnRes2;
MASK = *(FernKnS++);
FernKnRes2 = FernKnRes;
while (MASK)
{
*(FernKnRes2) += MASK & 0x01010101;
FASTER |= *(FernKnRes2++);
MASK>>=1;
MASK &= 0x7f7f7f7f;
}
FernKnRes+=8;
}
FernKnParser += ((1<<NUM_OF_BINTEST) * LB->PatchNumber)>>5;
FernS++;
if (FernS == FernFaster)
{
if ((FASTER & 0xfcfcfcfc) == 0)
return 0xffffffff;
}
}
u32 MAXV = 0;
u32 MAXI = 0;
for (u32 i = 0; i < LB->PatchNumber ; i++)
{
if (Results[i] > MAXV)
{
MAXI = i;
MAXV = Results[i];
}
}
LastErrorDetected = MAXV;
MAXI = ((MAXI & 3)<<3) | ((MAXI >>2 )& 7) | (MAXI & ~31);
return MAXI;
}
void FERN_SetPatchBestResponse(LearnBase *LB, u32 *BWIm , u32 PatchToSEt)
{
LEARN_TYPE *FernKnParser;
Ferns *FernS,*FernL;
FernS = LB->p_FernUsed;
u32 MASK;
FernKnParser = LB->PatchKnowledge+(PatchToSEt>>5);
MASK = 1<<(PatchToSEt & 31);
FernL = FernS + NUM_OF_FERNS;
while (FernS < FernL)
{
s32 *PatchStatB,*PatchStatL,Indx;
PatchStatB = FernS->Compar;
PatchStatL = PatchStatB + NUM_OF_BINTEST*2;
Indx = 0;
while (PatchStatB < PatchStatL)
{
u32 Compare;
Indx += Indx;
Compare = *(BWIm + *(PatchStatB++));
Compare -= *(BWIm + *(PatchStatB++));
Indx |= Compare>>31;
}
/* Learn Here */
*(FernKnParser + (Indx * LB->PatchNumber>>5)) |= MASK;
FernKnParser += ((1<<NUM_OF_BINTEST) * LB->PatchNumber)>>5;
FernS++;
}
}
void FERN_SetPitch(LearnBase *LB, u32 pitch )
{
/* Optimize Here */
for (u32 Counter3 = 0 ; Counter3 < 8 ; Counter3++)
{
for (u32 Counter = 0 ; Counter < NUM_OF_FERNS ; Counter++)
{
for (u32 Counter2 = 0 ; Counter2 < NUM_OF_BINTEST*2; Counter2++)
{
FernOptimsed[Counter3][Counter].Compar[Counter2] = ((s32)(FernUsed[Counter3][Counter].Compar[Counter2] & 0xff) - (PatchSize >> 1)) + ((s32)((FernUsed[Counter3][Counter].Compar[Counter2]>>8) & 0xff) - (PatchSize>>1)) * pitch;
}
}
}
LB->p_FernUsed = &FernOptimsed[LB->ActiveFern][0];
LB->Pitch = pitch;
}
void FERN_TrainAPatch(LearnBase *LB, u32 *BWIm , u32 pitch , u32 PatchToSEt)
{
if (pitch != LB->Pitch)
{
FERN_SetPitch(LB, pitch );
}
FERN_SetPatchBestResponse(LB, BWIm , PatchToSEt);
}
u32 FERN_MatchPatch2(LearnBase *LB, u32 *BWIm , u32 pitch )
{
if (pitch != LB->Pitch)
{
FERN_SetPitch(LB, pitch );
}
return FERN_GetPatchBestResponse(LB, BWIm );
}
u32 FERN_MatchPatch(LearnBase *LB, u32 *BWIm , u32 pitch )
{
u32 GetBob;
GetBob = FERN_MatchPatch2(LB, BWIm , pitch );
if (LastErrorDetected > ERROR_T)
return GetBob;
else
return 0xffffffff;
}
void FERN_ClearPatchBase(LearnBase *LB)
{
memset(LB->PatchKnowledge,0,FERN_PatchKnowledgeSize(LB));
LB->p_FernUsed = FernUsed[0];
LB->ActiveFern = 0;
}
void FERN_ClearAClass(LearnBase *LB,u32 ClassNum)
{
u32 Counter,*pBase,MASK;
Counter = NUM_OF_FERNS * (1<<NUM_OF_BINTEST);
pBase = LB->PatchKnowledge + (ClassNum>>5);
MASK = 1<<(ClassNum&31);
MASK ^= 0xffffffff;
while (Counter--)
{
*pBase &= MASK;
pBase += (LB->PatchNumber>>5);
}
}
LearnBase *FERN_CreatePatchBase(u32 ulNumberOfPatch)
{
LearnBase *Ret;
u32 Size;
static u32 IsInit = 1;
/* ALIGN NP with 32 */
ulNumberOfPatch += 31;
ulNumberOfPatch &= ~31;
Ret = (LearnBase *)malloc(sizeof(LearnBase));
memset(Ret,0,sizeof(LearnBase));
Ret->PatchNumber = ulNumberOfPatch;
Size = FERN_PatchKnowledgeSize(Ret);
*(void **)&Ret->PatchKnowledge = malloc(Size);
memset(Ret->PatchKnowledge,0,Size);
/* Init ferns */
Ret->p_FernUsed = FernUsed[0];
RandBase = 0;
if (IsInit)
for (u32 Counter = 0 ; Counter < NUM_OF_FERNS ; Counter++)
{
u32 CounterComp;
CounterComp = NUM_OF_BINTEST;
while(CounterComp--)
{
s32 X,Y,X2,Y2;
do{
X = ConstantRandom()%PatchSize;
Y = ConstantRandom()%PatchSize;
} while (((X - (PatchSize>>1))*(X - (PatchSize>>1)) + (Y - (PatchSize>>1)) * (Y - (PatchSize>>1)) > ((PatchSize * PatchSize) >> 2))) ;
FernUsed[0][Counter].Compar[CounterComp * 2 + 0] = X + (Y << 8);
X2 = X;
Y2 = Y;
do{
X = ConstantRandom()%PatchSize;
Y = ConstantRandom()%PatchSize;
} while (
((X - (PatchSize>>1))*(X - (PatchSize>>1)) + (Y - (PatchSize>>1)) * (Y - (PatchSize>>1)) > ((PatchSize * PatchSize) >> 2)) &&
((X - X2)*(X - X2) + (Y - Y2) * (Y - Y2) < (2*2)) &&
((X - X2)*(X - X2) + (Y - Y2) * (Y - Y2) > (7*7)) //*/
)//*/
;
FernUsed[0][Counter].Compar[CounterComp * 2 + 1] = X + (Y << 8);
for (u32 RotateCounter = 1; RotateCounter < 4 ; RotateCounter++)
{
s32 Swap;
Swap = Y2;
Y2 = X2;
X2 = PatchSize-Swap;
FernUsed[RotateCounter][Counter].Compar[CounterComp * 2 + 0] = X2 + (Y2 << 8);
Swap = Y;
Y = X;
X = PatchSize-Swap;
FernUsed[RotateCounter][Counter].Compar[CounterComp * 2 + 1] = X + (Y << 8);
}
for (u32 RotateCounter = 4; RotateCounter < 8 ; RotateCounter++)
{
#define COS_45 0.70710678118654752440084436210485f
X2 = (FernUsed[RotateCounter - 4][Counter].Compar[CounterComp * 2 + 0] & 0xff) - (PatchSize>>1);
Y2 =((FernUsed[RotateCounter - 4][Counter].Compar[CounterComp * 2 + 0] >> 8) & 0xff) - (PatchSize>>1);
X = (s32)(0.5f + ((float)X2 * COS_45) + ((float)Y2 * COS_45) + (float)(PatchSize>>1));
Y = (s32)(0.5f - ((float)X2 * COS_45) + ((float)Y2 * COS_45) + (float)(PatchSize>>1));
if (X < 0) X = 0;
if (Y < 0) Y = 0;
FernUsed[RotateCounter][Counter].Compar[CounterComp * 2 + 0] = X + (Y << 8);
X2 = (FernUsed[RotateCounter - 4][Counter].Compar[CounterComp * 2 + 1] & 0xff) - (PatchSize>>1);
Y2 =((FernUsed[RotateCounter - 4][Counter].Compar[CounterComp * 2 + 1] >> 8) & 0xff) - (PatchSize>>1);
X = (s32)(0.5f + ((float)X2 * COS_45) + ((float)Y2 * COS_45) + (float)(PatchSize>>1));
Y = (s32)(0.5f - ((float)X2 * COS_45) + ((float)Y2 * COS_45) + (float)(PatchSize>>1));
if (X < 0) X = 0;
if (Y < 0) Y = 0;
FernUsed[RotateCounter][Counter].Compar[CounterComp * 2 + 1] = X + (Y << 8);
}
}
}
IsInit = 0;
return Ret;
}
u32 FERN_GetClassNumber(LearnBase *LB)
{
return LB->PatchNumber;
}
/*********************************************************************************************************************/
/*********************************************************************************************************************/
/* FULL TRAINING *****************************************************************************************************/
/*********************************************************************************************************************/
/*********************************************************************************************************************/
static void COPY_PATCH_ScaleRotation(MAP *MapSRC,MAP *MapDST,s32 SX,s32 SY,s32 DX,s32 DY,u32 DSizeX,u32 DSizeY,u32 SizeX,u32 SizeY,float Rot128,float SCLAEV)
{
s32 *LAST,*DST,*DST2,*SRC,*BIGLAST;
s32 SYS,SYS2,SXS2,SXS3,SXI3,SYS3,SYI3,SXI,SYI,SYI2,SXI2;
s32 ScaleROTTable[1024],*p_ScaleROTTable;
s32 ScaleROTTableLenght[1024],*p_ScaleROTTableLenght;
float CosA,SinA;
CosA = cosf(Rot128);
SinA = sinf(Rot128);
//AAAA+= 1<<13;
SX -= (int)((CosA * (DSizeX>>1)) - (SinA * (DSizeY>>1))) ;
SY -= (int)((SinA * (DSizeX>>1)) + (CosA * (DSizeY>>1))) ;
SX <<= 8;
SY <<= 8;
SYS = 0;
SXI = (int)(65536.0f * ((float)DSizeX / (float)SizeX ));
SYI = (int)(65536.0f * ((float)DSizeY / (float)SizeY ));
/* Compute Scale X */
SXI3 = -(int)((float)SXI * SinA * SCLAEV);
SYI3 = (int)((float)SXI * CosA * SCLAEV);
SXS3 = SX;
SYS3 = SY;
/* Compute raster X */
SXI2 = (int)((float)SXI * CosA);
SYI2 = (int)((float)SXI * SinA);
SXS2 = 0;
SYS2 = 0;
/* Rasterize */
DX -= SizeX>>1;
DY -= SizeY>>1;
DX>>=8;DY>>=8;
if (DX < 0 ) DX = 0;
if (DY < 0 ) DY = 0;
p_ScaleROTTable = (s32 *)ScaleROTTable;
p_ScaleROTTableLenght = (s32*)ScaleROTTableLenght;
DST = MapDST->GetBase() + DY * MapDST->PITCH + DX;
BIGLAST = MapDST->GetBase() + MapDST->SY * MapDST->PITCH;
SizeX>>=8;SizeY>>=8;
while (SizeY--)
{
DST2 = DST;
SRC = MapSRC->GetBase();
LAST = DST + SizeX;
SXS2 = SXS3 + SXI2 * SizeX;
SYS2 = SYS3 + SYI2 * SizeX;
while (((SXS2>>16 > (s32)MapSRC->SX) || (SXS2>>16 < 0) ||
(SYS2>>16 > (s32)MapSRC->SY) || (SYS2>>16 < 0)) && (DST < LAST))
{
SXS2 -= SXI2;
SYS2 -= SYI2;
LAST--;
}
SXS2 = SXS3;
SYS2 = SYS3;
while (((SXS2>>16 > (s32)MapSRC->SX) || (SXS2>>16 < 0) ||
(SYS2>>16 > (s32)MapSRC->SY) || (SYS2>>16 < 0)) && (DST < LAST))
{
SXS2 += SXI2;
SYS2 += SYI2;
DST++;
}
while (DST < LAST)
{
//if ((DST > MapDST->GetBase()) && (DST < BIGLAST))
*(DST) = (*(SRC+(SXS2>>16) + (SYS2>>16)*MapSRC->PITCH)) & 0xfffffffe;
SXS2 += SXI2;
SYS2 += SYI2;
DST++;
}
SXS3 += SXI3;
SYS3 += SYI3;
DST = DST2 + MapDST->PITCH;
}
}
u32 SamplerMap_PIXELS[128 * 128];
MAP SamplerMap;
void FERN_SignalFail(struct LearnBase_ *LB)
{
//return;
/* Change BittestBase */
LB->ActiveFern ++;
LB->ActiveFern &= 0x7;
LB->p_FernUsed = &FernOptimsed[LB->ActiveFern][0];
}
void FERN_TrainAPatchOnFly(LearnBase *LB, u32 *BWIm , u32 pitch , u32 PatchToSEt , u32 StatisticalMode)
{
FERN_TrainAPatch(LB, BWIm, pitch, PatchToSEt);
}
void FERN_TrainAPatchComplete(LearnBase *LB, u32 *BWIm , u32 pitch , u32 PatchToSEt )
{
MAP SamplerMap2;
SamplerMap.SetBase((s32*)SamplerMap_PIXELS);
SamplerMap.SX = 64;
SamplerMap.SY = 64;
SamplerMap.PITCH = 64;
SamplerMap2.SetBase((s32*)(BWIm - 32 * pitch - 32));
SamplerMap2.SX = 64;
SamplerMap2.SY = 64;
SamplerMap2.PITCH = pitch;
FERN_ClearAClass(LB,PatchToSEt);
FERN_TrainAPatch(LB, BWIm, pitch, PatchToSEt);
FERN_TrainAPatch(LB, BWIm + 1, pitch, PatchToSEt);
FERN_TrainAPatch(LB, BWIm - 1, pitch, PatchToSEt);
FERN_TrainAPatch(LB, BWIm + pitch, pitch, PatchToSEt);
FERN_TrainAPatch(LB, BWIm - pitch, pitch, PatchToSEt);
u32 Trainer;
Trainer = 64;
while (Trainer--)
{
float ScaleNoise;
float AngleNoise;
ScaleNoise = (1.0f + 0.05f * ((float)(rand()&255) / 128.0f - 1.0f));
AngleNoise = 0.05f * ((float)(rand()&255) / 128.0f - 1.0f);
COPY_PATCH_ScaleRotation(&SamplerMap2,&SamplerMap,
SamplerMap2.SX<<7,
SamplerMap2.SY<<7,
SamplerMap.SX<<7,
SamplerMap.SY<<7,
(u32)(ScaleNoise * (float)(3*PatchSize))<<8,
(u32)(ScaleNoise * (float)(3*PatchSize))<<8,
(3*PatchSize)<<8,
(3*PatchSize)<<8,
AngleNoise,
1.0f);
//ADD_NOISE(&SamplerMap);
FERN_TrainAPatch(
LB,
(u32 *)(SamplerMap.GetBase() + (SamplerMap.SX>>1) + (SamplerMap.SY>>1) * SamplerMap.PITCH + ((rand()%3) - 1) + ((rand()%3) - 1) * SamplerMap.PITCH ),
SamplerMap.PITCH ,
PatchToSEt);
}
}
#if 0
#include "TRACK.h"
#include "Rrasters.h"
extern u32 ConstantRandom();
extern unsigned short RandBase;
#define ERROR_T (NUM_OF_FERNS - 4)//(NUM_OF_FERNS>>5))
u32 FERN_FastDetect(LearnBase *LB,u8 *Vector);
u32 FERN_MatchPatch_Error(LearnBase *LB, u32 *BWIm , u32 pitch , u32 Error);
/* PatchKnowledgeSize : compute the size */
u32 FERN_PatchKnowledgeSize(LearnBase*LB)
{
return ((LB->PatchNumber) * (1<<NUM_OF_BINTEST) * NUM_OF_FERNS) >> 3;
}
/* ValidateFern : Called after load */
void ValidateFern(LearnBase *LB)
{
FERN_InitBase(LB);
LB->p_FernUsed = &LB->FernOptimsed[LB->ActiveFern][0];
LB->Pitch = 7;
}
u32 FERN_GetPatchBestResponse_GI(LearnBase *LB, u32 *BWIm , u32 LearnMode , u8 *PrecomputeFlags)
{
u8 Results[MAX_NUM_OF_PATCH+8];
u32 *FernKnRes;
u32 FASTER;
START_RASTER(FRN);
LEARN_TYPE *FernKnParser;
Ferns *FernS,*FernL,*FernFaster;
FernS = LB->p_FernUsed;
FernKnParser = LB->PatchKnowledge;
FernL = FernS + NUM_OF_FERNS;
FernFaster = FernS + 8;
memset(Results,0,LB->PatchNumber+8);
if (LearnMode) LearnMode = 0xffffffff;
FASTER = LearnMode;
LB->LastErrorDetected = 0;
while (FernS < FernL)
{
s32 Indx;
if (PrecomputeFlags)
{
s32 *PatchStatB,*PatchStatL;
PatchStatB = FernS->Compar;
Indx = *(PrecomputeFlags++);
}
else
{
s32 *PatchStatB,*PatchStatL;
PatchStatB = FernS->Compar;
PatchStatL = PatchStatB + NUM_OF_BINTEST*2;
Indx = 0;
while (PatchStatB < PatchStatL)
{
u32 Compare;
Indx += Indx;
Compare = *(BWIm + *(PatchStatB++));
Compare -= *(BWIm + *(PatchStatB++));
Indx |= Compare>>31;
}
}
LEARN_TYPE *FernKnS,*FernKnE;
FernKnS = FernKnParser + ((Indx * LB->PatchNumber)>>5);
FernKnE = FernKnS + (LB->PatchNumber>>5);
FernKnRes = (u32*)Results;
while (FernKnS < FernKnE)
{
u32 MASK,*FernKnRes2;
MASK = *(FernKnS++);
FernKnRes2 = FernKnRes;
while (MASK)
{
*(FernKnRes2) += MASK & 0x01010101;
FASTER |= *(FernKnRes2++);
MASK>>=1;
MASK &= 0x7f7f7f7f;
}
FernKnRes+=8;
}
FernKnParser += ((1<<NUM_OF_BINTEST) * LB->PatchNumber)>>5;
FernS++;
if (FernS == FernFaster)
{
if ((FASTER & 0xfcfcfcfc) == 0)
{
STOP_RASTER(FRN);
return 0xffffffff;
}
}
}
u32 MAXV = 0;
u32 MAXI = 0;
u32 LEARN_MAXV = 1000000000;
u32 LEARN_MAXI = 0;
LB->LastErrorDetected = MAXV;
LB->LastNumberOfValids = 0;
for (u32 i = 0; i < LB->PatchNumber ; i++)
{
if (Results[i] > MAXV)
{
MAXI = i;
MAXV = Results[i];
LB->LastNumberOfValids = 0;
} else
if (Results[i] == MAXV)
{
LB->LastNumberOfValids++;
}
/* if (LearnMode)
{
u32 ReinDex;
ReinDex = ((i & 3)<<3) | ((i >>2 )& 7) | (i & ~31);
if ((NUM_OF_FERNS - Results[i])*LB->LearnCounter[ReinDex] <= LEARN_MAXV)
{
LEARN_MAXI = i;
LEARN_MAXV = (NUM_OF_FERNS - Results[i])*LB->LearnCounter[ReinDex];
}
}*/
}
LB->LastErrorDetected = MAXV;
/*if (LearnMode)
{
MAXI = LEARN_MAXI;
LB->LastErrorDetected = LEARN_MAXV;
} */
MAXI = ((MAXI & 3)<<3) | ((MAXI >>2 )& 7) | (MAXI & ~31);
STOP_RASTER(FRN);
return MAXI;
}
void FERN_SetPatchBestResponse_GI(LearnBase *LB, u32 *BWIm , u32 PatchToSEt , u8 *PrecomputeFlags)
{
LEARN_TYPE *FernKnParser;
Ferns *FernS,*FernL;
FernS = LB->p_FernUsed;
u32 MASK;
START_RASTER(FRN);
LB->LearnCounter[PatchToSEt] ++;
FernKnParser = LB->PatchKnowledge+(PatchToSEt>>5);
MASK = 1<<(PatchToSEt & 31);
FernL = FernS + NUM_OF_FERNS;
while (FernS < FernL)
{
s32 Indx;
if (PrecomputeFlags)
{
s32 *PatchStatB,*PatchStatL;
PatchStatB = FernS->Compar;
Indx = *(PrecomputeFlags++);
} else
{
s32 *PatchStatB,*PatchStatL;
PatchStatB = FernS->Compar;
PatchStatL = PatchStatB + NUM_OF_BINTEST*2;
Indx = 0;
while (PatchStatB < PatchStatL)
{
u32 Compare;
Indx += Indx;
Compare = *(BWIm + *(PatchStatB++));
Compare -= *(BWIm + *(PatchStatB++));
Indx |= Compare>>31;
}
}
/* Learn Here */
*(FernKnParser + (Indx * LB->PatchNumber>>5)) |= MASK;
FernKnParser += ((1<<NUM_OF_BINTEST) * LB->PatchNumber)>>5;
FernS++;
}
STOP_RASTER(FRN);
}
u32 FERN_GetPatchBestResponse(LearnBase *LB, u32 *BWIm , u32 Optim)
{
return FERN_GetPatchBestResponse_GI(LB, BWIm , Optim , 0);
}
void FERN_SetPatchBestResponse(LearnBase *LB, u32 *BWIm , u32 PatchToSEt)
{
FERN_SetPatchBestResponse_GI(LB, BWIm , PatchToSEt , 0);
}
void FERN_SetPitch(LearnBase *LB, u32 pitch )
{
/* Optimize Here */
START_RASTER(FRN);
for (u32 Counter3 = 0 ; Counter3 < 9 ; Counter3++)
{
for (u32 Counter = 0 ; Counter < NUM_OF_FERNS ; Counter++)
{
for (u32 Counter2 = 0 ; Counter2 < NUM_OF_BINTEST*2; Counter2++)
{
LB->FernOptimsed[Counter3][Counter].Compar[Counter2] = ((s32)(LB->FernUsed[Counter3][Counter].Compar[Counter2] & 0xff) - (PatchSize >> 1)) + ((s32)((LB->FernUsed[Counter3][Counter].Compar[Counter2]>>8) & 0xff) - (PatchSize>>1)) * pitch;
}
}
}
LB->p_FernUsed = &LB->FernOptimsed[LB->ActiveFern][0];
LB->Pitch = pitch;
STOP_RASTER(FRN);
}
void FERN_TrainAPatch(LearnBase *LB, u32 *BWIm , u32 pitch , u32 PatchToSEt)
{
START_RASTER(FRN);
if (pitch != LB->Pitch)
{
FERN_SetPitch(LB, pitch );
}
FERN_SetPatchBestResponse(LB, BWIm , PatchToSEt);
STOP_RASTER(FRN);
}
u32 FERN_MatchPatch2(LearnBase *LB, u32 *BWIm , u32 pitch )
{
if (pitch != LB->Pitch)
{
FERN_SetPitch(LB, pitch );
}
return FERN_GetPatchBestResponse(LB, BWIm );
}
u32 FERN_MatchPatch(LearnBase *LB, u32 *BWIm , u32 pitch )
{
u32 GetBob;
if (pitch != LB->Pitch) FERN_SetPitch(LB, pitch );
GetBob = FERN_GetPatchBestResponse_GI(LB, BWIm , 0,0);
if (LB->LastErrorDetected > ERROR_T)
return GetBob;
else
return 0xffffffff;
}
void FERN_ClearPatchBase(LearnBase *LB)
{
memset(LB->PatchKnowledge,0,FERN_PatchKnowledgeSize(LB));
LB->p_FernUsed = LB->FernUsed[0];
LB->ActiveFern = 0;
}
void FERN_ClearAClass(LearnBase *LB,u32 ClassNum)
{
u32 Counter,*pBase,MASK;
Counter = NUM_OF_FERNS * (1<<NUM_OF_BINTEST);
LB->LearnCounter[ClassNum] = 0;
pBase = LB->PatchKnowledge + (ClassNum>>5);
MASK = 1<<(ClassNum&31);
MASK ^= 0xffffffff;
while (Counter--)
{
*pBase &= MASK;
pBase += (LB->PatchNumber>>5);
}
}
u32 FERN_GetFullData(LearnBase *LB,u32 *Mask,u32 ClassNum)
{
u32 Counter,*pBase,MASK;
Counter = NUM_OF_FERNS * (1<<NUM_OF_BINTEST);
pBase = LB->PatchKnowledge + (ClassNum>>5);
MASK = 1<<(ClassNum&31);
u32 Bitnum = 0;
while (Counter--)
{
if (*pBase & MASK)
{
Mask[(Counter>>5)] |= 1<<(Counter&31);
Bitnum++;
}
else
Mask[(Counter>>5)] &= ~(1<<(Counter&31));
pBase += (LB->PatchNumber>>5);
}
return Bitnum;
}
void FERN_SetFullData(LearnBase *LB,u32 *Mask,u32 ClassNum)
{
u32 Counter,*pBase,MASK;
Counter = NUM_OF_FERNS * (1<<NUM_OF_BINTEST);
pBase = LB->PatchKnowledge + (ClassNum>>5);
MASK = 1<<(ClassNum&31);
while (Counter--)
{
if (Mask[(Counter>>5)] & (1<<(Counter&31)))
*pBase |= MASK;
else
*pBase &= ~MASK;
pBase += (LB->PatchNumber>>5);
}
}
void FERN_InitBase(LearnBase *Ret)
{
/* Init ferns */
Ret->p_FernUsed = Ret->FernUsed[0];
RandBase = 0;
for (u32 Counter = 0 ; Counter < NUM_OF_FERNS ; Counter++)
{
u32 CounterComp;
CounterComp = NUM_OF_BINTEST;
while(CounterComp--)
{
s32 X,Y,X2,Y2;
do{
X = ConstantRandom()%PatchSize;
Y = ConstantRandom()%PatchSize;
} while (((X - (PatchSize>>1))*(X - (PatchSize>>1)) + (Y - (PatchSize>>1)) * (Y - (PatchSize>>1)) > ((PatchSize * PatchSize) >> 2))) ;
Ret->FernUsed[0][Counter].Compar[CounterComp * 2 + 0] = X + (Y << 8);
Ret->FernUsed[8][Counter].Compar[CounterComp * 2 + 0] = (PatchSize - X) + (Y << 8);
X2 = X;
Y2 = Y;
do{
X = ConstantRandom()%PatchSize;
Y = ConstantRandom()%PatchSize;
} while (
((X - (PatchSize>>1))*(X - (PatchSize>>1)) + (Y - (PatchSize>>1)) * (Y - (PatchSize>>1)) > ((PatchSize * PatchSize) >> 2)) &&
((X - X2)*(X - X2) + (Y - Y2) * (Y - Y2) < (2*2)) &&
((X - X2)*(X - X2) + (Y - Y2) * (Y - Y2) > (7*7)) //*/
)//*/
;
Ret->FernUsed[0][Counter].Compar[CounterComp * 2 + 1] = X + (Y << 8);
Ret->FernUsed[8][Counter].Compar[CounterComp * 2 + 1] = (PatchSize - X) + (Y << 8);
for (u32 RotateCounter = 1; RotateCounter < 4 ; RotateCounter++)
{
s32 Swap;
Swap = Y2;
Y2 = X2;
X2 = PatchSize-Swap;
Ret->FernUsed[RotateCounter][Counter].Compar[CounterComp * 2 + 0] = X2 + (Y2 << 8);
Swap = Y;
Y = X;
X = PatchSize-Swap;
Ret->FernUsed[RotateCounter][Counter].Compar[CounterComp * 2 + 1] = X + (Y << 8);
}
for (u32 RotateCounter = 4; RotateCounter < 8 ; RotateCounter++)
{
#define COS_45 0.70710678118654752440084436210485f
X2 = (Ret->FernUsed[RotateCounter - 4][Counter].Compar[CounterComp * 2 + 0] & 0xff) - (PatchSize>>1);
Y2 =((Ret->FernUsed[RotateCounter - 4][Counter].Compar[CounterComp * 2 + 0] >> 8) & 0xff) - (PatchSize>>1);
X = (s32)(0.5f + ((float)X2 * COS_45) + ((float)Y2 * COS_45) + (float)(PatchSize>>1));
Y = (s32)(0.5f - ((float)X2 * COS_45) + ((float)Y2 * COS_45) + (float)(PatchSize>>1));
if (X < 0) X = 0;
if (Y < 0) Y = 0;
Ret->FernUsed[RotateCounter][Counter].Compar[CounterComp * 2 + 0] = X + (Y << 8);
X2 = (Ret->FernUsed[RotateCounter - 4][Counter].Compar[CounterComp * 2 + 1] & 0xff) - (PatchSize>>1);
Y2 =((Ret->FernUsed[RotateCounter - 4][Counter].Compar[CounterComp * 2 + 1] >> 8) & 0xff) - (PatchSize>>1);
X = (s32)(0.5f + ((float)X2 * COS_45) + ((float)Y2 * COS_45) + (float)(PatchSize>>1));
Y = (s32)(0.5f - ((float)X2 * COS_45) + ((float)Y2 * COS_45) + (float)(PatchSize>>1));
if (X < 0) X = 0;
if (Y < 0) Y = 0;
Ret->FernUsed[RotateCounter][Counter].Compar[CounterComp * 2 + 1] = X + (Y << 8);
}
}
}
}
LearnBase *FERN_CreatePatchBase(u32 ulNumberOfPatch)
{
LearnBase *Ret;
u32 Size;
/* ALIGN NP with 32 */
ulNumberOfPatch += 31;
ulNumberOfPatch &= ~31;
Ret = (LearnBase *)malloc(sizeof(LearnBase));
memset(Ret,0,sizeof(LearnBase));
Ret->PatchNumber = ulNumberOfPatch;
Size = FERN_PatchKnowledgeSize(Ret);
*(void **)&Ret->PatchKnowledge = malloc(Size);
memset(Ret->PatchKnowledge,0,Size);
FERN_InitBase(Ret);
return Ret;
}
u32 FERN_GetClassNumber(LearnBase *LB)
{
return LB->PatchNumber;
}
/*********************************************************************************************************************/
/*********************************************************************************************************************/
/* FULL TRAINING *****************************************************************************************************/
/*********************************************************************************************************************/
/*********************************************************************************************************************/
static void COPY_PATCH_ScaleRotation(MAP *MapSRC,MAP *MapDST,s32 SX,s32 SY,s32 DX,s32 DY,u32 DSizeX,u32 DSizeY,u32 SizeX,u32 SizeY,float Rot128,float SCLAEV)
{
s32 *LAST,*DST,*DST2,*SRC,*BIGLAST,*BIGSRCLAST;
s32 SYS,SYS2,SXS2,SXS3,SXI3,SYS3,SYI3,SXI,SYI,SYI2,SXI2;
s32 ScaleROTTable[1024],*p_ScaleROTTable;
s32 ScaleROTTableLenght[1024],*p_ScaleROTTableLenght;
float CosA,SinA;
CosA = cosf(Rot128);
SinA = sinf(Rot128);
//AAAA+= 1<<13;
SX -= (int)((CosA * (DSizeX>>1)) - (SinA * (DSizeY>>1))) ;
SY -= (int)((SinA * (DSizeX>>1)) + (CosA * (DSizeY>>1))) ;
SX <<= 8;
SY <<= 8;
SYS = 0;
SXI = (int)(65536.0f * ((float)DSizeX / (float)SizeX ));
SYI = (int)(65536.0f * ((float)DSizeY / (float)SizeY ));
/* Compute Scale X */
SXI3 = -(int)((float)SXI * SinA * SCLAEV);
SYI3 = (int)((float)SXI * CosA * SCLAEV);
SXS3 = SX;
SYS3 = SY;
/* Compute raster X */
SXI2 = (int)((float)SXI * CosA);
SYI2 = (int)((float)SXI * SinA);
SXS2 = 0;
SYS2 = 0;
/* Rasterize */
DX -= SizeX>>1;
DY -= SizeY>>1;
DX>>=8;DY>>=8;
if (DX < 0 ) DX = 0;
if (DY < 0 ) DY = 0;
p_ScaleROTTable = (s32 *)ScaleROTTable;
p_ScaleROTTableLenght = (s32*)ScaleROTTableLenght;
DST = MapDST->GetBase() + DY * MapDST->PITCH + DX;
BIGLAST = MapDST->GetBase() + MapDST->SX + MapDST->SY * MapDST->PITCH;
BIGSRCLAST = MapSRC->GetBase() + MapSRC->SX + MapSRC->SY * MapSRC->PITCH;
SizeX>>=8;SizeY>>=8;
while (SizeY--)
{
DST2 = DST;
SRC = MapSRC->GetBase();
LAST = DST + SizeX;
SXS2 = SXS3 + SXI2 * SizeX;
SYS2 = SYS3 + SYI2 * SizeX;
while (((SXS2>>16 >= (s32)MapSRC->SX) || (SXS2>>16 < 0) ||
(SYS2>>16 >= (s32)MapSRC->SY) || (SYS2>>16 < 0)) && (DST < LAST))
{
SXS2 -= SXI2;
SYS2 -= SYI2;
LAST--;
}
SXS2 = SXS3;
SYS2 = SYS3;
while (((SXS2>>16 >= (s32)MapSRC->SX) || (SXS2>>16 < 0) ||
(SYS2>>16 >= (s32)MapSRC->SY) || (SYS2>>16 < 0)) && (DST < LAST))
{
SXS2 += SXI2;
SYS2 += SYI2;
DST++;
}
while (DST < LAST)
{
if ((DST > MapDST->GetBase()) && (DST < BIGLAST) && (SRC > MapSRC->GetBase()) && (SRC < BIGSRCLAST) )
*(DST) = (*(SRC+(SXS2>>16) + (SYS2>>16)*MapSRC->PITCH)) & 0xfffffffe;
SXS2 += SXI2;
SYS2 += SYI2;
DST++;
}
SXS3 += SXI3;
SYS3 += SYI3;
DST = DST2 + MapDST->PITCH;
}
}
u32 SamplerMap_PIXELS[256 * 256];
u32 Random_T[65536];
MAP SamplerMap;
void ADD_NOISE(MAP *MapDST)
{
s32 *LAST,*DST;
u32 K,KA;
static u32 Init = 1;
if (Init)
{
Init = 65536;
while (Init--)
{
Random_T[Init] = rand()&255;
Random_T[Init] *= Random_T[Init];
Random_T[Init] >>= 8;//*/
Random_T[Init] >>= 2;
}
Init = 0;
}
DST = MapDST->GetBase();
K = rand()&65535;
KA = rand()&127;
for (s32 SizeY = 0; SizeY < (s32)MapDST->SY;SizeY ++)
{
LAST = DST + MapDST->SX;
while (DST < LAST)
{
*(DST++) += Random_T[K&65535];
K+=KA;
}
DST+=MapDST->PITCH-MapDST->SX;
}
}
void FERN_SignalFail(struct LearnBase_ *LB)
{
//return;
/* Change BittestBase */
LB->ActiveFern ++;
LB->ActiveFern &= 0x7;
LB->p_FernUsed = &LB->FernOptimsed[LB->ActiveFern][0];
}
void FERN_TrainAPatchOnFly(LearnBase *LB, u32 *BWIm , u32 pitch , u32 PatchToSEt , u32 StatisticalMode)
{
FERN_TrainAPatch(LB, BWIm, pitch, PatchToSEt);
}
void FERN_TrainAPatchComplete_P(LearnBase *LB, u32 *BWIm , u32 pitch , u32 PatchToSEt , u32 SampleNum , u32 Clear , u32 Noise , float Scale , float angle , u32 Disp)
{
MAP SamplerMap2;
SamplerMap.BASE = (s32*)SamplerMap_PIXELS;
SamplerMap.SX = 128;
SamplerMap.SY = 128;
SamplerMap.PITCH = 128;
SamplerMap2.BASE = (s32*)(BWIm - 64 * pitch - 64);
SamplerMap2.SX = 128;
SamplerMap2.SY = 128;
SamplerMap2.PITCH = pitch;
if (Clear) FERN_ClearAClass(LB,PatchToSEt);
FERN_TrainAPatch(LB, BWIm, pitch, PatchToSEt);
if (Disp)
{
FERN_TrainAPatch(LB, BWIm + 1, pitch, PatchToSEt);
FERN_TrainAPatch(LB, BWIm - 1, pitch, PatchToSEt);
FERN_TrainAPatch(LB, BWIm + pitch, pitch, PatchToSEt);
FERN_TrainAPatch(LB, BWIm - pitch, pitch, PatchToSEt);
}
u32 Trainer;
Trainer = SampleNum;
while (Trainer--)
{
float ScaleNoise;
float AngleNoise;
ScaleNoise = (1.0f + Scale * 0.05f * ((float)(rand()&255) / 128.0f - 1.0f));
AngleNoise = angle * 0.05f * ((float)(rand()&255) / 128.0f - 1.0f);
COPY_PATCH_ScaleRotation(&SamplerMap2,&SamplerMap,
SamplerMap2.SX<<7,
SamplerMap2.SY<<7,
SamplerMap.SX<<7,
SamplerMap.SY<<7,
(u32)(ScaleNoise * (float)(3*PatchSize))<<8,
(u32)(ScaleNoise * (float)(3*PatchSize))<<8,
(3*PatchSize)<<8,
(3*PatchSize)<<8,
AngleNoise,
1.0f);
if (Noise) ADD_NOISE(&SamplerMap);
FERN_TrainAPatch(
LB,
(u32 *)(SamplerMap.BASE + (SamplerMap.SX>>1) + (SamplerMap.SY>>1) * SamplerMap.PITCH + ((rand()%3) - 1) + ((rand()%3) - 1) * SamplerMap.PITCH ),
SamplerMap.PITCH ,
PatchToSEt);
FERN_TrainAPatch(
LB,
(u32 *)(SamplerMap.BASE + 1+(SamplerMap.SX>>1) + (SamplerMap.SY>>1) * SamplerMap.PITCH + ((rand()%3) - 1) + ((rand()%3) - 1) * SamplerMap.PITCH ),
SamplerMap.PITCH ,
PatchToSEt);
FERN_TrainAPatch(
LB,
(u32 *)(SamplerMap.BASE -SamplerMap.PITCH+ (SamplerMap.SX>>1) + (SamplerMap.SY>>1) * SamplerMap.PITCH + ((rand()%3) - 1) + ((rand()%3) - 1) * SamplerMap.PITCH ),
SamplerMap.PITCH ,
PatchToSEt);
FERN_TrainAPatch(
LB,
(u32 *)(SamplerMap.BASE +SamplerMap.PITCH + (SamplerMap.SX>>1) + (SamplerMap.SY>>1) * SamplerMap.PITCH + ((rand()%3) - 1) + ((rand()%3) - 1) * SamplerMap.PITCH ),
SamplerMap.PITCH ,
PatchToSEt);
}
}
void FERN_TrainAPatchComplete(LearnBase *LB, u32 *BWIm , u32 pitch , u32 PatchToSEt )
{
START_RASTER(FRN);
FERN_TrainAPatchComplete_P(LB, BWIm , pitch , PatchToSEt , 0, 1, 1 , 0.5f , 0.5f ,0);
STOP_RASTER(FRN);
}
/*********************************************************************************************************************/
/*********************************************************************************************************************/
/* Features functions ***********************************************************************************************/
/*********************************************************************************************************************/
/*********************************************************************************************************************/
void FERN_FillFull(LearnBase *LB)
{
}
/////////////////////////////////////////////////////
// Feature learning, merging the two nearest vectors
u32 FERN_MergeNearest(LearnBase *LB,u32 SuggestedClass, u32 ErrorSugested = -1)
{
u32 Counter,*pBase,MASK,MASKXOR,MASKXORMIN,FI,FJ,MASKNUMMIN;
u32 Mask1[(32+NUM_OF_FERNS * (1<<NUM_OF_BINTEST)) >> 5];
u32 Mask2[(32+NUM_OF_FERNS * (1<<NUM_OF_BINTEST)) >> 5];
u32 MergedMask[(32+NUM_OF_FERNS * (1<<NUM_OF_BINTEST)) >> 5];
memset(Mask1,0,sizeof(Mask1));
memset(Mask2,0,sizeof(Mask2));
memset(MergedMask,0,sizeof(MergedMask));
u32 RealPatchNumber = LB->PatchNumber;
RealPatchNumber = 40;
if (RealPatchNumber > LB->PatchNumber) RealPatchNumber = LB->PatchNumber;
if (ErrorSugested != -1)
{
for (u32 i = 0 ; i < RealPatchNumber ; i++)
{
FERN_GetFullData(LB,Mask1,i);
Counter = (32+NUM_OF_FERNS * (1<<NUM_OF_BINTEST)) >> 5;
MASK = 0;
while (Counter--)
{
MASK += GetBitNumber(Mask1[Counter]);
}
if (SuggestedClass == i) ErrorSugested += MASK;
if (MASK == 0)
return i;
}
}
//return SuggestedClass;
// u32 CounterMM = RealPatchNumber >> 2;
// while (CounterMM--)
{
MASKNUMMIN = 100000000;
FJ = FI = 0;
for (u32 i = 0 ; i < RealPatchNumber - 1 ; i++)
{
if (FERN_GetFullData(LB,Mask1,i) )
{
for (u32 j = i+1 ; j < RealPatchNumber ; j++)
{
if (FERN_GetFullData(LB,Mask2,j))
{
/* Compute distance */
Counter = (32+NUM_OF_FERNS * (1<<NUM_OF_BINTEST)) >> 5;
MASK = MASKXOR = 0;
while (Counter--)
{
MASK += GetBitNumber(Mask1[Counter]|Mask2[Counter]);
MASKXOR += GetBitNumber(Mask1[Counter]&Mask2[Counter]);
}
if (MASK <= MASKNUMMIN)
{
FI = i;
FJ = j;
MASKXORMIN = MASK;
Counter = (32+NUM_OF_FERNS * (1<<NUM_OF_BINTEST)) >> 5;
while (Counter--)
{
MergedMask[Counter] = Mask1[Counter]|Mask2[Counter];
}
MASKNUMMIN = MASK;
}
if (MASKNUMMIN == 0) i = j = 1000000;
}
}
}
}
if (FJ != FI)
{
if (MASKXORMIN >= ErrorSugested)
return SuggestedClass;//*/
FERN_SetFullData(LB,MergedMask,FI);
memset(MergedMask,0,sizeof(MergedMask));
FERN_SetFullData(LB,MergedMask,FJ);
LB->LearnCounter[FI] += LB->LearnCounter[FJ];
LB->LearnCounter[FJ] = 0;
FERN_GetFullData(LB,Mask1,FI);
FERN_GetFullData(LB,Mask2,FJ);
return FJ;
} else
return 0;
}
}
///////////////////////////////////////////////
// Feature learning --- Special function
void FERN_PrecomputeFlags(LearnBase *LB, u32 *BWIm , u8 *Flags)
{
u32 Counter = NUM_OF_FERNS;
while (Counter--)
{
u32 V;
if (Counter > 15)
V = 0;
else
V = *(BWIm + LB->p_FernUsed[Counter].Compar[0]);
/* V |= *(BWIm +1+ LB->p_FernUsed[Counter].Compar[0]);
V |= *(BWIm -1+ LB->p_FernUsed[Counter].Compar[0]);
BWIm+=LB->Pitch;
V = *(BWIm + LB->p_FernUsed[Counter].Compar[0]);
V |= *(BWIm +1+ LB->p_FernUsed[Counter].Compar[0]);
V |= *(BWIm -1+ LB->p_FernUsed[Counter].Compar[0]);
BWIm-=LB->Pitch;
BWIm-=LB->Pitch;
V = *(BWIm + LB->p_FernUsed[Counter].Compar[0]);
V |= *(BWIm +1+ LB->p_FernUsed[Counter].Compar[0]);
V |= *(BWIm -1+ LB->p_FernUsed[Counter].Compar[0]);
// V |= (*(BWIm + LB->p_FernUsed[Counter].Compar[1]) & 0xaa)>>1;//*/
V &= 0xaa;
V |= V >> 5;
V &= 0xf;//*/
*(Flags++) = V;
}
}
//////////////////////////////////////////
// Feature learning --- Match function
#define Learn_Error (NUM_OF_FERNS - 1)
u32 FERN_MatchPatch_Error(LearnBase *LB, u32 *BWIm , u32 pitch , u32 Error)
{
u32 GetBob;
if (pitch != LB->Pitch) FERN_SetPitch(LB, pitch );
u8 Flags[NUM_OF_FERNS];
FERN_PrecomputeFlags(LB, BWIm , Flags);
if (FERN_FastDetect(LB,Flags))
{
GetBob = FERN_GetPatchBestResponse_GI(LB, BWIm , 0,Flags);
if ((LB->LastErrorDetected > Learn_Error) && (LB->LastNumberOfValids >= 0 ))
return GetBob;
}
return 0xffffffff;
}
//////////////////////////////////////////
// Feature learning --- Train function
// LearnMode = 0, nothing
// LearnMode = 1, Add Positive samples
// LearnMode = 2, Add Negative samples
void FERN_TrainBestPatch(LearnBase *LB, u32 *BWIm , u32 pitch , u32 LearnMode )
{
u32 BestClass;
if (pitch != LB->Pitch) FERN_SetPitch(LB, pitch );
LB->p_FernUsed = &LB->FernOptimsed[0][0];
u8 Flags[NUM_OF_FERNS];
FERN_PrecomputeFlags(LB, BWIm , Flags);
#define LearGrnul_Alloc (1<<18)
if (LearnMode == 1) // Positiv sample is added
{
if ((LB->ulNumberOfPositivesSamples & (LearGrnul_Alloc-1)) == 0)
{
if (LB->PositiveSamples == NULL)
LB->PositiveSamples = (u8*)malloc(LearGrnul_Alloc * NUM_OF_FERNS);
else
LB->PositiveSamples = (u8*)realloc(LB->PositiveSamples,(LB->ulNumberOfPositivesSamples + LearGrnul_Alloc + 1) * NUM_OF_FERNS);
}
memcpy(&LB->PositiveSamples[LB->ulNumberOfPositivesSamples * NUM_OF_FERNS],Flags,NUM_OF_FERNS);
LB->ulNumberOfPositivesSamples++;
}
if (LearnMode == 2) // Negativ sample is added
{
if (LB->ulNumberOfNegativesSamples > 10000000) return;
if (LB->LearnCounter[0])
{
// If this is already learned, then add only false positiv
if (!FERN_FastDetect(LB,Flags))
{
return;
}
}
if ((LB->ulNumberOfNegativesSamples & (LearGrnul_Alloc-1)) == 0)
{
if (LB->NegativeSamples == NULL)
LB->NegativeSamples = (u8**)malloc(4*(LearGrnul_Alloc+1));
else
LB->NegativeSamples = (u8**)realloc(LB->NegativeSamples,4*(LB->ulNumberOfNegativesSamples + LearGrnul_Alloc + 1));
}
LB->NegativeSamples[LB->ulNumberOfNegativesSamples] = (u8*)malloc(NUM_OF_FERNS);
memcpy(LB->NegativeSamples[LB->ulNumberOfNegativesSamples],Flags,NUM_OF_FERNS);
LB->ulNumberOfNegativesSamples++;
}//*/
}
/////////////////////////////////////////////
// Feature learning --- Compute Vectors
void FERN_GetVectorData(LearnBase *LB,u32 *Mask,u8 *Vector)
{
LEARN_TYPE *FernKnParser,*FernKnParserL;
u32 Counter,p32C;
FernKnParser = LB->PatchKnowledge;
Counter = NUM_OF_FERNS;
while (Counter--)
{
s32 Indx;
Indx = *(Vector++);
p32C = ((LB->PatchNumber)>>5);
FernKnParserL = FernKnParser + (Indx * LB->PatchNumber>>5);
while (p32C--) *(Mask++) = *(FernKnParserL++);
FernKnParser += ((1<<NUM_OF_BINTEST) * LB->PatchNumber)>>5;
}
}
void FERN_SetVectorData(LearnBase *LB,u32 *Mask,u8 *Vector)
{
LEARN_TYPE *FernKnParser,*FernKnParserL;
u32 Counter,p32C;
FernKnParser = LB->PatchKnowledge;
Counter = NUM_OF_FERNS;
while (Counter--)
{
s32 Indx;
Indx = *(Vector++);
p32C = ((LB->PatchNumber)>>5);
FernKnParserL = FernKnParser + (Indx * LB->PatchNumber>>5);
while (p32C--) *(FernKnParserL++) = *(Mask++);
FernKnParser += ((1<<NUM_OF_BINTEST) * LB->PatchNumber)>>5;
}
}
u32 FERN_FastDetect_64(LearnBase *LB,u8 *Vector)
{
LEARN_TYPE *FernKnParser;
u32 MASK0,MASK1;
FernKnParser = LB->PatchKnowledge;
MASK0 = MASK1 = 0xffffffff;
for (int Counter = 0 ; Counter < NUM_OF_FERNS ; Counter++)
{
s32 Indx;
Indx = *(Vector++);
Indx <<= 1;
MASK0 &= *(FernKnParser + Indx);
MASK1 &= *(FernKnParser + Indx + 1);
FernKnParser += (((1<<NUM_OF_BINTEST) * LB->PatchNumber)>>5);
if ((MASK0 == 0) && (MASK1 == 0))
return 0;
}
return 1;
}
u32 FERN_FastDetect(LearnBase *LB,u8 *Vector)
{
LEARN_TYPE *FernKnParser;
u32 MASK0;
if (LB->PatchNumber > 32) return FERN_FastDetect_64(LB,Vector);
FernKnParser = LB->PatchKnowledge;
MASK0 = 0xffffffff;
for (int Counter = 0 ; Counter < NUM_OF_FERNS ; Counter++)
{
s32 Indx;
Indx = *(Vector++);
MASK0 &= *(FernKnParser + Indx);
FernKnParser += (((1<<NUM_OF_BINTEST) * LB->PatchNumber)>>5);
if (MASK0 == 0)
return 0;
}
// return MASK0;
// if ((MASK0 & 0xf) && (MASK0 & (0xf<<4)) && (MASK0 & (0xf<<8)) && (MASK0 & (0xf<<12)))
// if ((MASK0 & 0x7) && (MASK0 & (0x7<<3)) && (MASK0 & (0x7<<6)))
if ((MASK0 & 0x7) && (MASK0 & (0x7<<3)) && (MASK0 & (0x7<<6)) /*&& (MASK0 & (0x7<<9))*/)
// if ((MASK0 & 0x7) && (MASK0 & (0x7<<3)) && (MASK0 & (0x7<<6)) && (MASK0 & (0x7<<9)) && (MASK0 & (0x7<<12)))
return 1;
else
return 0;
}
typedef struct Statbase_
{
double StatResult;
double StatResultIntersect[32];
} Statbase;
double FERN_ComputeStat(LearnBase *LB,Statbase *SB)
{
u32 Mask18[(64+NUM_OF_FERNS * (1<<NUM_OF_BINTEST)) >> 5];
u32 Mask18_BC[NUM_OF_FERNS+4];
u32 *M18;
double StatMax;
u32 RealPatchN;
RealPatchN = 12;
StatMax = 0;
memset(Mask18,0,sizeof(Mask18));
memset(SB,0,LB->PatchNumber * sizeof(Statbase));
FERN_GetFullData(LB,Mask18,18);
M18 = Mask18;
for (u32 j = 0 ; j < NUM_OF_FERNS ; j++)
{
u32 BC = 0;
for (u32 k = 0 ; k < (1<<NUM_OF_BINTEST) >> 5 ; k++)
{
BC += GetBitNumber(*M18);
M18++;
}
Mask18_BC[j] = BC;
}
for (u32 i=0;i<RealPatchN;i++)
{
u32 Mask[(64+NUM_OF_FERNS * (1<<NUM_OF_BINTEST)) >> 5];
u32 *M0;
memset(Mask,0,sizeof(Mask));
SB[i].StatResult = 1.0;
FERN_GetFullData(LB,Mask,i);
M0 = Mask;
for (u32 j = 0 ; j < NUM_OF_FERNS ; j++)
{
u32 BC = 0;
for (u32 k = 0 ; k < (1<<NUM_OF_BINTEST) >> 5 ; k++)
{
BC += GetBitNumber(*M0);
M0++;
}
double RES = (double)(BC)/(double)(Mask18_BC[j]);
SB[i].StatResult *= RES;
}
if (SB[i].StatResult > StatMax)
StatMax = SB[i].StatResult;//*/
}
for (u32 i=0;i<RealPatchN;i++)
{
SB[i].StatResult = 0.0;
for (u32 j=0;j<RealPatchN;j++)
{
SB[i].StatResultIntersect[j] = 1.0;
//if (i != j)
{
u32 MaskI[(64+NUM_OF_FERNS * (1<<NUM_OF_BINTEST)) >> 5];
u32 MaskJ[(64+NUM_OF_FERNS * (1<<NUM_OF_BINTEST)) >> 5];
u32 *M0,*M1;
memset(MaskI,0,sizeof(MaskI));
memset(MaskJ,0,sizeof(MaskJ));
FERN_GetFullData(LB,MaskI,i);
FERN_GetFullData(LB,MaskJ,j);
M0 = MaskI;
M1 = MaskJ;
for (u32 f = 0 ; f < NUM_OF_FERNS ; f++)
{
u32 BC = 0;
for (u32 k = 0 ; k < (1<<NUM_OF_BINTEST) >> 5 ; k++)
{
BC += GetBitNumber(*M0 & *M1);
M0++;
M1++;
}
double RES = (double)(BC)/(double)(Mask18_BC[f]);
SB[i].StatResultIntersect[j] *= RES;
}
//if (i != j)
SB[i].StatResult += SB[i].StatResultIntersect[j];
if (SB[i].StatResult > StatMax)
StatMax = SB[i].StatResult;
}
}
}//*/
return StatMax;
}
static float volatile AVERAGE_LEARN = 1.0f;
static float volatile LAST_AVERAGE_LEARN = 1.0f;
static float volatile AVERAGE_LEARND = 1.0f;
static float volatile GMAX = 0;
void FERN_SmearPositiv(LearnBase *LB)
{
/* Smear datas */
for (int i = 0 ; i < LB->ulNumberOfPositivesSamples ; i++)
{
u8 SI[NUM_OF_FERNS];
u8 SJ[NUM_OF_FERNS];
int j = rand()%LB->ulNumberOfPositivesSamples;
memcpy(SI,LB->PositiveSamples + i * NUM_OF_FERNS,NUM_OF_FERNS);
memcpy(SJ,LB->PositiveSamples + j * NUM_OF_FERNS,NUM_OF_FERNS);
memcpy(LB->PositiveSamples + i * NUM_OF_FERNS,SJ,NUM_OF_FERNS);
memcpy(LB->PositiveSamples + j * NUM_OF_FERNS,SI,NUM_OF_FERNS);
}
}
#define FAST_C 0
void FERN_SetPatchBestResponse_Closest(LearnBase *LB,u32 Good_I,u8 *Flags)
{
u8 LocalGLG[NUM_OF_FERNS];
FERN_SetPatchBestResponse_GI(LB, NULL , Good_I,Flags);
for (int R = 0 ; R < NUM_OF_FERNS ; R++)
LocalGLG[R] = (Flags[R]>>1) | (Flags[R]<<7);
FERN_SetPatchBestResponse_GI(LB, NULL , Good_I,LocalGLG);
for (int R = 0 ; R < NUM_OF_FERNS ; R++)
LocalGLG[R] = (Flags[R]>>7) | (Flags[R]<<1);
FERN_SetPatchBestResponse_GI(LB, NULL , Good_I,LocalGLG);
}
void FERN_Finishlearn(LearnBase *LB)
{
u8 *Flags,**FlagsNEG;
if (!LB) return;
u32 SaveSign[NUM_OF_FERNS<<1];
u32 SetSign[NUM_OF_FERNS<<1];
u32 BADMIN_I,BADMIN_V;
u32 BAD_LOWEST = 0;
u32 BAD_LOWEST_I = -1;
FERN_SmearPositiv(LB);
FERN_SmearPositiv(LB);
FERN_SmearPositiv(LB);
static int volatile i;
for (int j = 0 ; j < LB->PatchNumber ; j++)
FERN_ClearAClass(LB,j);
Flags = LB->PositiveSamples;
for (i = 0 ; i < LB->ulNumberOfPositivesSamples; i++)
{
FERN_SetPatchBestResponse_GI(LB, NULL , 18,Flags);
Flags += NUM_OF_FERNS;
}
for (i = 0 ; i < 17; i++)
{
FERN_SetPatchBestResponse_GI(LB, NULL , 18,Flags);
}
// if (LB->ulNumberOfNegativesSamples > 2048) LB->ulNumberOfNegativesSamples = 2048;
#if 1
u32 ToCreate = 0;
for (int M = 0 ; M < 1 ; M ++)
{
Flags = LB->PositiveSamples;
FlagsNEG = LB->NegativeSamples;
//FERN_ClearAClass(LB,0);
u32 Limit;
i = 0;
Limit = LB->ulNumberOfPositivesSamples;
/* for (i = 0 ; i < 8 ; i++)
{
FERN_SetPatchBestResponse_GI(LB, NULL , i,Flags);
Flags += NUM_OF_FERNS<<FAST_C;
}//*/
for (; i < Limit ; i++)
{
//////////////////////////////////////
// Method 1 (VQ)
/*
u32 BestClass = FERN_GetPatchBestResponse_GI(LB, NULL , 1,Flags);
if (LB->LastErrorDetected <= Learn_Error)
{
BestClass = FERN_MergeNearest(LB,BestClass,NUM_OF_FERNS - LB->LastErrorDetected);
FERN_SetPatchBestResponse_GI(LB, NULL , BestClass,Flags);
// Check on positive base
}
Flags += NUM_OF_FERNS<<FAST_C;
///**/
/*
//////////////////////////////////////
// Method 2 (VQ + test over ALL negativs)
BADMIN_I = -1;
BADMIN_V = 0;
// u32 GetBob = FERN_GetPatchBestResponse_GI(LB, NULL , 0,Flags);
// if (LB->LastErrorDetected <= Learn_Error)
if (!FERN_FastDetect(LB,Flags))
{
u32 PRED = FERN_GetPatchBestResponse_GI(LB, NULL , 0,Flags);
if (PRED == -1) PRED = 0;
FERN_GetVectorData(LB,SaveSign,Flags);
BADMIN_V = LB->ulNumberOfNegativesSamples;
for (int j0 = -1 ; (j0 < LB->PatchNumber) || (j0 < 0) ; j0++)
{
int j = (j0 == -1) ? PRED : j0;
u32 BAD = 0;
u32 BaseSet = j>>5;
u32 BaseJump = (LB->PatchNumber>>5);
memcpy(SetSign,SaveSign,sizeof(SetSign));
for (int l = 0 ; l < NUM_OF_FERNS ; l++,BaseSet += BaseJump) SetSign[BaseSet] |= (1<<(j&31));
FERN_SetVectorData(LB,SetSign,Flags);
FlagsNEG = LB->NegativeSamples;
for (int k = 0 ; k < LB->ulNumberOfNegativesSamples >> FAST_C; k++)
{
if (FERN_FastDetect(LB,*FlagsNEG))
BAD++;
FlagsNEG += 1 << FAST_C;
if (BAD >= BADMIN_V) k = LB->ulNumberOfNegativesSamples;
}
if (BAD < BADMIN_V)
{
BADMIN_I = j;
BADMIN_V = BAD;
}
FERN_SetVectorData(LB,SaveSign,Flags);
if (BAD == BAD_LOWEST) j = LB->PatchNumber;
}
BAD_LOWEST = BADMIN_V;
if ((BAD_LOWEST_I == -1) && (BAD_LOWEST))
BAD_LOWEST_I = i;
}
if (BADMIN_I != -1)
{
FERN_SetPatchBestResponse_GI(LB, NULL , BADMIN_I , Flags);
}
if ((i & 127) == 127)
{
AVERAGE_LEARN = 0.0f;
for (int g = 0; g < LB->PatchNumber ; g++)
{
AVERAGE_LEARN += LB->LearnCounter[g];
if (LB->LearnCounter[g]) GMAX = g;
}
AVERAGE_LEARND = (AVERAGE_LEARN - LAST_AVERAGE_LEARN) / (float)128.0f ;
LAST_AVERAGE_LEARN = AVERAGE_LEARN;
AVERAGE_LEARN = AVERAGE_LEARN / (float)(i+1) ;
}
Flags += NUM_OF_FERNS<<FAST_C;
//*/
//////////////////////////////////////
// Method 3 (ULTRA LOW STATS)
//FlagsNEG = LB->NegativeSamples;
/*Flags = *FlagsNEG;
FlagsNEG++;*/
u32 K = FERN_FastDetect(LB,Flags);
if (!K)
{
Statbase SBo[128];
Statbase SB[128];
double StatMin;
u32 SaveSign[NUM_OF_FERNS<<1];
u32 SetSign[NUM_OF_FERNS<<1];
u32 Good_I;
int ovrN = rand()%3;
for (int ovr = 0; ovr < 3; ovr++)
{
if (ovr != ovrN)
{
Good_I = 0;
StatMin = 1000000000000000000.0;
FERN_GetVectorData(LB,SaveSign,Flags);
FERN_ComputeStat(LB,SBo);
for (int j = ovr*3; j < ovr*3+3; j++)
{
memcpy(SetSign,SaveSign,sizeof(SetSign));
u32 BaseSet = j>>5;
u32 BaseJump = (LB->PatchNumber>>5);
for (int l = 0 ; l < NUM_OF_FERNS ; l++,BaseSet += BaseJump) SetSign[BaseSet] |= (1<<(j&31));
FERN_SetVectorData(LB,SetSign,Flags);
double L ;
FERN_ComputeStat(LB,SB);
L = SB[j].StatResult - SBo[j].StatResult;
if (L < StatMin)
{
Good_I = j;
StatMin = L;
}
FERN_SetVectorData(LB,SaveSign,Flags);
}
FERN_SetPatchBestResponse_GI(LB, NULL , Good_I,Flags);
}
}
}
Flags += NUM_OF_FERNS<<FAST_C;
//////////////////////////////////////
// Method 4 (Short)
/* if (!FERN_FastDetect(LB,Flags))
{
if (ToCreate < 10)
FERN_SetPatchBestResponse_GI(LB, NULL , ToCreate++ , Flags);
else
{
u32 GetBob = FERN_GetPatchBestResponse_GI(LB, NULL , 1,Flags);
FERN_SetPatchBestResponse_GI(LB, NULL , GetBob , Flags);
}
}
Flags += NUM_OF_FERNS<<FAST_C;
*/
}
}
#endif
/* for (u32 HH = 0 ; HH < 31-8 ; HH ++)
FERN_MergeNearest(LB,0);*/
u32 LearnCounter[MAX_NUM_OF_PATCH];
memset(LearnCounter,0,sizeof(LearnCounter));
FERN_ClearAClass(LB,18);
FlagsNEG = LB->NegativeSamples;
for (int i = 0 ; i < LB->ulNumberOfNegativesSamples>>FAST_C ; i++)
{
Flags = *FlagsNEG;
if (FERN_FastDetect(LB,Flags))
LearnCounter[FERN_GetPatchBestResponse_GI(LB, NULL , 0,Flags)]++;
FlagsNEG++;
}
/* if (LB->NegativeSamples) free(LB->NegativeSamples);
if (LB->PositiveSamples) free(LB->PositiveSamples);
LB->NegativeSamples = LB->PositiveSamples = NULL;
LB->ulNumberOfPositivesSamples = LB->ulNumberOfNegativesSamples = 0;*/
}
#endif