JD2022-TU1/main/extern/Camcam/LIBS/Trackeur/FAST_HOUGHT.cpp

730 lines
15 KiB
C++
Raw Blame History

#include "SCENE.h"
#include "HOUGH.H"
#define BACKFILTERING
#define POWERACC_SHIFT 8
#ifdef BACKFILTERING
#define POWERACC() CurrentV += ((s32)*SRC) << POWERACC_SHIFT;
#define POWERDEC() {CurrentV /= 3;/*(CurrentV >> 2) + (CurrentV >> 4) ;CurrentV += (CurrentV >> 4);*/};
#define POWERAFFECT() {*SRC = (s16)((((s32)*SRC)<<0) - (*DST>>POWERACC_SHIFT-0));}
#else
#define POWERACC() CurrentV += ((s32)*SRC) << POWERACC_SHIFT;
#define POWERDEC() {CurrentV /= 3;};
#define POWERAFFECT() {*SRC -= (s16)(*DST>>POWERACC_SHIFT);*SRC <<= 0;}
#endif
s32 MAP16_Threshold(MAP16 *MapDST,u32 Value)
{
s16 *LAST,*DST;
s32 Max = 0;
if (!Value) return 0;
/* MM H */
DST = MapDST->GetBase();
for (u32 SizeY = 0; SizeY < MapDST->SY;SizeY ++)
{
s32 CX = 0;
LAST = DST + MapDST->SX;
while (DST < LAST)
{
if (abs(*DST) > Value)
{
Max++;
/*if (*DST > 0)
*DST = 500;
else
*DST = -500;//*/
} else
*DST = 0;//*/
CX++;
DST++;
}
DST += MapDST->PITCH - MapDST->SX;
}
Max = (float)Max * 100.0f / ((float)MapDST->SX * (float)MapDST->SY);
return Max;
}
void MAP16_FastHoughQuadran_V(MAP16 *MapSRC,MAP16 *MapDST,u32 Po2,u32 InverseMode)
{
s16 *SRC,*SRC2,*DST,*LAST,*LASTY;
DST = MapDST->GetBase() ;
s32 Max = (s32)MapDST->SY & ~((1<<Po2)-1);
for (s32 SizeY = 0; SizeY < Max;SizeY += 2)
{
u32 Index2;
u32 ILocal,LBase;
s16 *DSTSave;
LAST = DST + MapDST->SX;
DSTSave = DST;
LBase = SizeY & ~(((2<<Po2))-1);
ILocal = SizeY - LBase;
SRC = MapSRC->GetBase() + (LBase + (ILocal>>1)) * MapSRC->PITCH;
SRC2 = MapSRC->GetBase() + (LBase + (ILocal>>1) + (1<<Po2)) * MapSRC->PITCH;
Index2 = ILocal>>1;
while (DST < LAST)
{
if (InverseMode)
{
*DST = (*SRC + SRC2[Index2])>>0;
Index2 ++;
Index2 &= MapSRC->SX-1;
*(DST + MapDST->PITCH) = (*SRC + SRC2[Index2])>>0;
} else
{
*DST = (*SRC + SRC2[Index2])>>1;
Index2 ++;
Index2 &= MapSRC->SX-1;
*(DST + MapDST->PITCH) = (*SRC + SRC2[Index2])>>1;
}
DST++;
SRC++;
}
DST+=MapDST->PITCH-MapDST->SX;
DST+=MapDST->PITCH;
}
}
void MAP16_SwapLines(s16 *pSrc,s16 *pDst,s32 Lenght)
{
while (Lenght--)
{
s16 Swp;
Swp = *pSrc;
*(pSrc++) = *pDst;
*(pDst++) = Swp;
}
}
void MAP16_RotateLine(s16 *pSrc,s32 Rot,s32 Lenght,u32 CyclicMode)
{
s16 CpyL[2048];
// In place shift 16 bits horizontaly
memcpy(CpyL,pSrc,Lenght*2);
memcpy(pSrc,CpyL+Rot,(Lenght-Rot)*2);
if (CyclicMode)
memcpy(pSrc+(Lenght-Rot),CpyL,Rot*2);
else
{
s16 Value = 0;
s32 Counter = Rot;
pSrc+=(Lenght-Rot);
//Value = *pSrc;
while (Counter--) *(pSrc++) = Value;
}
}
void MAP16_FastHoughQuadran_Inplace(MAP16 *MapDST,u32 Po2,u32 Cyclemode,u32 Invert)
{
s16 *DST,*DST2,*LAST;
s32 Max = (s32)MapDST->SY & ~((1<<Po2)-1);
/* 1 Shift Lines ***************************************************************************/
s32 VPos = 2<<Po2;
if (VPos>2)
{
DST = MapDST->GetBase() ;
for (s32 SizeY = 0; SizeY < MapDST->SY;SizeY++)
{
s32 LocalPos = SizeY & (VPos-1);
LocalPos ^= (VPos-1);
if (LocalPos > (VPos>>1))
{
LocalPos-=VPos>>1;
MAP16_RotateLine(DST,LocalPos,MapDST->SX,Cyclemode);
}
DST += MapDST->PITCH;
}
}
/* 2 Swap lines *************************************************************************** */
VPos = 4;
while (VPos <= 2<<Po2)
{
LAST = MapDST->GetBase() + MapDST->PITCH * MapDST->SY;
DST = MapDST->GetBase() ;
DST2 = DST + MapDST->PITCH * ((VPos>>1)-1);
for (s32 SizeY = 0; SizeY < MapDST->SY;SizeY++)
{
s32 LocalPos = SizeY & (VPos-1);
if ((LocalPos < VPos>>1) && (LocalPos & 1))/* Swap Lines */MAP16_SwapLines(DST,DST2,MapDST->SX);
DST += MapDST->PITCH;
DST2 += MapDST->PITCH;
//if (DST2 >= LAST) SizeY = MapDST->SY;
}
VPos <<= 1;
}
/* 3 Radon trans *************************************************************************/
DST = MapDST->GetBase() ;
for (s32 SizeY = 0; SizeY < Max;SizeY += 2)
{
s16 A,B,DSTSave0,DSTSave1;
LAST = DST + MapDST->SX -1;
DST2 = DST + MapDST->PITCH;
if (Cyclemode)
{
DSTSave0 = *(DST);
DSTSave1 = *(DST2);
} else
{
DSTSave0 = 0;
DSTSave1 = 0;
}
if (1)
{
while (DST < LAST)
{
A = (*(DST2) + *(DST) ) ;
B = (*(DST2) + *(DST+1) ) ;
*(DST2++) = A>>1;
*(DST++) = B>>1;
}
A = (*(DST2) + *(DST)) ;
B = (DSTSave0 + *(DST2));
*(DST2++) = A>>1;
*(DST++) = B>>1;
} else
{
while (DST < LAST)
{
A = (*(DST2) + *(DST) ) - (*(DST+1));
B = (*(DST2) + *(DST+1) ) - (*(DST));
*(DST2++) = A>>1;
*(DST++) = B>>1;
}
A = (*(DST2) + *(DST)) - (DSTSave0);
B = (DSTSave0 + *(DST2))-(DSTSave1);
*(DST2++) = A>>1;
*(DST++) = B>>1;
}
DST+=MapDST->PITCH-MapDST->SX;
DST+=MapDST->PITCH;
}
}
void MAP16_HOUGHPostFilter(MAP16 *MapSRC,HOUGHParram *pFlags)
{
s16 *LAST,*SRC;
s32 *DST;
s32 Accum[2048];
/* MM H */
for (u32 SizeY = 0; SizeY < MapSRC->SY ;SizeY ++)
{
s32 CurrentV;
if (pFlags->POSTFILTERING)
{
DST = Accum;
SRC = MapSRC->GetBase()+SizeY*MapSRC->PITCH;
LAST = SRC + MapSRC->SX;
memset(DST, 0 , sizeof(Accum[0]) * (MapSRC->SX+1));
CurrentV = 0;
#ifdef BACKFILTERING
while (SRC < LAST)
{
POWERACC();
POWERDEC();
*DST += CurrentV;
SRC++;
DST++;
}
SRC -= MapSRC->SX;
DST -= MapSRC->SX;
while (SRC < LAST)
{
POWERDEC();
*DST += CurrentV;
SRC++;
DST++;
}
#else
SRC += MapSRC->SX;
DST += MapSRC->SX;
#endif
CurrentV = 0;
LAST -= MapSRC->SX;
while (SRC > LAST)
{
SRC--;
DST--;
POWERACC();
POWERDEC();
*DST += CurrentV;
}
SRC += MapSRC->SX;
DST += MapSRC->SX;
while (SRC > LAST)
{
SRC--;
DST--;
POWERDEC();
*DST += CurrentV;
}
LAST += MapSRC->SX;
while (SRC < LAST)
{
POWERAFFECT();
SRC++;
DST++;
}
SRC = MapSRC->GetBase()+SizeY*MapSRC->PITCH;
SRC[0] = 0;
SRC[1] = 0;
SRC[2] = 0;
SRC[3] = 0;
SRC[MapSRC->SX-1] = 0;
SRC[MapSRC->SX-2] = 0;
SRC[MapSRC->SX-3] = 0;
SRC[MapSRC->SX-4] = 0;
}
if (pFlags->COMPUTE_LAPLACIAN)
{
DST = Accum;
SRC = MapSRC->GetBase()+SizeY*MapSRC->PITCH;
LAST = SRC + MapSRC->SX;
*(DST) = 0;//(*(SRC + MapSRC->SX - 1) + *(SRC + 1))>>1;
*(DST + MapSRC->SX - 1) = 0;//(*(SRC + MapSRC->SX - 2) + *(SRC))>>1;
DST++;
SRC++;
while (SRC < LAST-1)
{
*DST = (*(SRC -1) + *(SRC + 1))>>1;
SRC++;
DST++;
}
SRC -= MapSRC->SX - 1;
DST -= MapSRC->SX - 1;
while (SRC < LAST)
{
*SRC -= *DST;
if (*SRC > pFlags->LimitUp) *SRC = pFlags->LimitUp;
if (*SRC < -pFlags->LimitUp) *SRC = -pFlags->LimitUp;
*SRC <<= pFlags->PRE_LAPLACIAN_SHIFT;
SRC++;
DST++;
}
SRC -= MapSRC->SX;
DST -= MapSRC->SX;
}
}
}
//#pragma optimize("",off)
void MAP16_HOUGHCosEnvellppe(MAP16 *MapSRC,HOUGHParram *pFlags)
{
s16 *LAST,*SRC;
s32 *DST;
float Factor[2048];
u32 Size = 1<<pFlags->SubWindowShift;
if (Size > MapSRC->SY) Size = MapSRC->SY;
for (int i = 0 ; i < Size ; i ++)
{
Factor[i] = (1.0f - cos(2.0f * 3.1415927f * ((float)i / (float)Size))) / 2.0f;
}
/* MM H */
SRC = MapSRC->GetBase();
for (u32 SizeY = 0; SizeY < MapSRC->SY ;SizeY ++)
{
LAST = SRC+MapSRC->SX;
float fFactor = Factor[SizeY & ((1<<pFlags->SubWindowShift)-1)] ;
while (SRC < LAST)
{
*(SRC++) = (s16)((float)*SRC*fFactor);
}
SRC += MapSRC->PITCH - MapSRC->SX;
}
}
void MAP16_HOUGHZeroCrossing(MAP16 *MapSRC, s32 ZC)
{
s16 *LAST,*SRC;
s32 *DST;
s32 Accum[2048];
/* MM H */
for (u32 SizeY = 0; SizeY < MapSRC->SY ;SizeY ++)
{
DST = Accum + 2;
SRC = MapSRC->GetBase()+SizeY*MapSRC->PITCH;
Accum[1] = SRC[MapSRC->SX];
Accum[0] = SRC[MapSRC->SX - 1];
Accum[MapSRC->SX + 2] = SRC[0];
Accum[MapSRC->SX + 3] = SRC[1];
LAST = SRC + MapSRC->SX;
while (SRC < LAST)
{
*DST = *SRC;
SRC++;
DST++;
}
SRC -= MapSRC->SX;
DST -= MapSRC->SX;
while (SRC < LAST)
{
if (*SRC > ZC)
{
if ((*(DST+1)<-ZC) || (*(DST-1)<-ZC)
//|| (*(DST+2)<0) || (*(DST-2)<0)
)
{}
else
*SRC = 0;
} else
if (*SRC < -ZC)
{
if ((*(DST+1)>ZC) ||(*(DST-1)>ZC)
//|| (*(DST+2)>0) ||(*(DST-2)>0)
)
{}
else
*SRC = 0;
} else
*SRC = 0;
SRC++;
DST++;
}
SRC -= MapSRC->SX;
DST -= MapSRC->SX;
}
}
void MAP16_HOUGHDivide0And45(MAP16 *MapSRC,u32 SubWindow)
{
s16 *LAST,*SRC;
SRC = MapSRC->GetBase();
for (u32 SizeY = 0; SizeY < MapSRC->SY ;SizeY ++, SRC += MapSRC->PITCH)
{
if (((SizeY & SubWindow) == 0) || ((SizeY & SubWindow) == SubWindow))
{
LAST = SRC + MapSRC->SX;
while (SRC < LAST)
{
*(SRC++)>>=1;
}
SRC -= MapSRC->SX;
}
}
}
void FAST_HOUGH(MAP16 *pSrc,MAP16 *pTmp,HOUGHParram *FLAGS)
{
MAP16 Local;
if (FLAGS->INVERSE)
{
pSrc->SX >>= 1;
pSrc->SY >>= 1;
/* Clean */
if (FLAGS->CLEAN)
{
Local = *pSrc; Local.staticBase = 1;
Local.MoveBase(Local.SX);
Local.SY<<=1;
MAP16_FLIP_V(&Local);
Local = *pSrc;
Local.SX<<=1;
MAP16_FLIP_V(&Local);
}
} else
{
if (FLAGS->COMPUTE_O2) MAP16_XO2(pSrc);
pSrc->SX >>= 1;
if (FLAGS->COMPUTE_O2) MAP16_YO2(pSrc);
pSrc->SY >>= 1;
if (FLAGS->SEPARATE_QUADRANTS)
{
Local = *pSrc; Local.staticBase = 1;
Local.MoveBase(pSrc->SX);
MAP16_BLUR_CopyTransposeFAST(pSrc,&Local);
Local.MoveBase(-pSrc->SX);
pSrc->SX <<= 1;
Local.SX <<= 1;
Local.MoveBase(pSrc->SY * pSrc->PITCH);
MAP16_CopyFlipV(pSrc,&Local);
pSrc->SX >>= 1;
Local.SX >>= 1;
}
}
if (pTmp)
{
if (!FLAGS->INPLACE) MAP16_Set(pTmp,0);
pTmp->SX>>=1;
pTmp->SY>>=1;
}
for (u32 QCounter = 0 ; QCounter < 4 ; QCounter ++ )
{
Local = *pSrc; Local.staticBase = 1;
if (QCounter & 1) Local.MoveBase(Local.SX);
if (QCounter & 2) Local.MoveBase(Local.SY*Local.PITCH);
s32 MAXLIM = Local.SX <= 1<<FLAGS->SubWindowShift ? Local.SX : 1<<FLAGS->SubWindowShift;
if (FLAGS->INVERSE)
{
MAP16_FLIP_H(&Local);
if (FLAGS->CLEAN)
{
/* Clean */
if (MAXLIM == Local.SX) MAP16_BLUR_ScissorX_Inplace(&Local,Local.SY/2);//*/
MAP16_FLIP_V(&Local);
}
}
else
{
if (FLAGS->POSTFILTERING || FLAGS->COMPUTE_LAPLACIAN)
{
MAP16_HOUGHPostFilter(&Local,FLAGS);
#ifdef BACKFILTERING
/*MAP16_BLUR_ScissorX_Inplace(&Local,-(s32)Local.SY);
MAP16_BLUR_CopyTransposeFAST(&Local,pTmp);
MAP16_HOUGHPostFilter(pTmp,FLAGS);
MAP16_BLUR_CopyTransposeFAST(pTmp,&Local);
MAP16_BLUR_ScissorX_Inplace(&Local,(s32)Local.SY);//*/
/*
MAP16_BLUR_CopyTransposeFAST(&Local,pTmp);
MAP16_HOUGHPostFilter(pTmp,FLAGS);
MAP16_BLUR_CopyTransposeFAST(pTmp,&Local);
//*/
#endif
}
if (FLAGS->COMPUTE_ENVELLOPPE) MAP16_HOUGHCosEnvellppe(&Local,FLAGS);
if (!FLAGS->SEPARATE_QUADRANTS) MAP16_FLIP_H(&Local);
}
if (FLAGS->COMPUTE)
{
if (!FLAGS->INPLACE && pTmp)
for (u32 Counter = 0; 1<<Counter < MAXLIM ; Counter+=2)
{
MAP16_Set(pTmp,0);
MAP16_FastHoughQuadran_V(&Local,pTmp,Counter,0); // 2
if (1<<(Counter+1) < MAXLIM)
MAP16_FastHoughQuadran_V(pTmp,&Local,Counter+1,0); // 4
else
MAP16_Copy(pTmp,&Local);
}
else
for (u32 Counter = 0; 1<<Counter < MAXLIM; Counter++)
MAP16_FastHoughQuadran_Inplace(&Local,Counter,FLAGS->MODE_CYCLIQUE,FLAGS->INVERSE); // 2) */
}
if (!(FLAGS->INVERSE))
{
/* Divide 0<> and 45<34> by 2 */
//MAP16_HOUGHDivide0And45(&Local,(1<<FLAGS->SubWindowShift)-1);
if (FLAGS->ZeroCrossing1) MAP16_HOUGHZeroCrossing(&Local,FLAGS->ZeroCrossing1);
if (FLAGS->Treshold) MAP16_Threshold(&Local,FLAGS->Treshold);
if (FLAGS->CLEAN)
{
/* Clean */
MAP16_FLIP_V(&Local);
if (MAXLIM == Local.SX) MAP16_BLUR_ScissorX_Inplace(&Local,Local.SY/2);//*/
}
} else
{
if (FLAGS->ZeroCrossing2) MAP16_HOUGHZeroCrossing(&Local,FLAGS->ZeroCrossing2);
}
if ((FLAGS->INVERSE) && (!(QCounter & 2)))
{
if (FLAGS->MERGE_QUADRANTS) MAP16_FLIP_V(&Local);
}
}
if (pTmp)
{
pTmp->SX<<=1;
pTmp->SY<<=1;
}
if (FLAGS->INVERSE)
{
if (FLAGS->MERGE_QUADRANTS)
{
pSrc->SX <<= 1;
Local = *pSrc; Local.staticBase = 1;
Local.MoveBase(Local.SY*Local.PITCH);
MAP16_Add(&Local,pSrc);
pSrc->SX >>= 1;
Local.SX >>= 1;
pSrc->MoveBase(pSrc->SX);
MAP16_BLUR_CopyTransposeFAST(pSrc,&Local);
pSrc->MoveBase(-pSrc->SX);
MAP16_Add(&Local,pSrc);
MAP16_FLIP_H(pSrc);
MAP16_FLIP_V(pSrc);//*/
}
pSrc->SY <<= 1;
pSrc->SX <<= 1;
if (FLAGS->COMPUTE_E2)
{
MAP16_XE2(pSrc);
MAP16_YE2(pSrc);
}
} else
{
/* Clean */
if (FLAGS->CLEAN)
{
Local = *pSrc; Local.staticBase = 1;
Local.SX<<=1;
MAP16_FLIP_V(&Local);
Local = *pSrc; Local.staticBase = 1;
Local.MoveBase(Local.SX);
Local.SY<<=1;
MAP16_FLIP_V(&Local);
}
pSrc->SY <<= 1;
pSrc->SX <<= 1;
}
}
void FAST_HOUGH_DEENTERLACE(MAP16 *MapDST,MAP16 *pTmp,u32 Po2)//*/
{
s16 *LAST,*BIGLAST,*TMP,*DST;
/* MM H */
BIGLAST = MapDST->GetBase() + MapDST->SY * MapDST->PITCH;
TMP = pTmp->GetBase();
DST = MapDST->GetBase();
for (u32 Counter = 0 ; Counter < 1<<Po2 ; Counter ++)
{
DST = MapDST->GetBase() + Counter * MapDST->PITCH;
while (DST < BIGLAST)
{
s32 CX = 0;
LAST = DST + MapDST->SX;
while (DST < LAST)
{
*(TMP++) = *(DST++);
}
DST += (MapDST->PITCH << Po2) - MapDST->SX;
TMP += pTmp->PITCH - pTmp->SX;
}
}
MAP16_Copy(pTmp,MapDST);
}
void HOUGH_Filtering(MAP16 *MapDST)
{
s16 *LAST,*DST,*DST2;
s16 Hysteresys[2048];
s16 HystereBlur[2048];
MAP16_Shift(MapDST,1);
static u32 Deperd = 32;
static u32 Tresh = 20;
/* MM H */
memset(Hysteresys , 0 , sizeof(Hysteresys));
DST = MapDST->GetBase();
for (u32 SizeY = 0; SizeY < MapDST->SY;SizeY ++)
{
u32 Index = 0;
LAST = DST + MapDST->SX;
while (DST < LAST)
{
if (abs(*DST) > Tresh)
{
Hysteresys[Index] = Deperd;
Hysteresys[(Index + 1)& (MapDST->SX-1)] = Deperd;
Hysteresys[(Index + MapDST->SX - 1)& (MapDST->SX-1)] = Deperd;
}
Index++;
DST++;
}
Index = 0;
DST -= MapDST->SX;
while (DST < LAST)
{
if (Hysteresys[Index]) *DST |= 1;
HystereBlur[Index] = Hysteresys[Index] + Hysteresys[Index] + Hysteresys[(Index + 1)& (MapDST->SX-1)] + Hysteresys[(Index + MapDST->SX - 1) & (MapDST->SX-1)];
HystereBlur[Index] >>= 2;
if (HystereBlur[Index]) HystereBlur[Index] --;
Index++;
DST++;
}
memcpy(Hysteresys,HystereBlur,MapDST->SX*sizeof(Hysteresys[0]));
DST += MapDST->PITCH - MapDST->SX;
}
DST = MapDST->GetBase() + (MapDST->SY-1) * MapDST->PITCH;
for (u32 SizeY = 0; SizeY < MapDST->SY;SizeY ++)
{
u32 Index = 0;
LAST = DST + MapDST->SX;
while (DST < LAST)
{
if (abs(*DST) > Tresh)
{
Hysteresys[Index] = Deperd;
Hysteresys[(Index + 1)& (MapDST->SX-1)] = Deperd;
Hysteresys[(Index + MapDST->SX - 1)& (MapDST->SX-1)] = Deperd;
}
Index++;
DST++;
}
Index = 0;
DST -= MapDST->SX;
while (DST < LAST)
{
if (Hysteresys[Index]) *DST |= 1;
HystereBlur[Index] = Hysteresys[Index] + Hysteresys[Index] + Hysteresys[(Index + 1)& (MapDST->SX-1)] + Hysteresys[(Index + MapDST->SX - 1) & (MapDST->SX-1)];
HystereBlur[Index] >>= 2;
if (HystereBlur[Index]) HystereBlur[Index] --;
Index++;
DST++;
}
memcpy(Hysteresys,HystereBlur,MapDST->SX*sizeof(Hysteresys[0]));
DST -= MapDST->SX;
DST -= MapDST->PITCH;
}
DST = MapDST->GetBase();
for (u32 SizeY = 0; SizeY < MapDST->SY;SizeY ++)
{
u32 Index = 0;
LAST = DST + MapDST->SX;
while (DST < LAST)
{
if (!(*DST & 1))
{
*DST = 0;
}
DST++;
}
DST += MapDST->PITCH - MapDST->SX;
}
MAP16_Shift(MapDST,-1);
}