#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<SX; DSTSave = DST; LBase = SizeY & ~(((2<GetBase() + (LBase + (ILocal>>1)) * MapSRC->PITCH; SRC2 = MapSRC->GetBase() + (LBase + (ILocal>>1) + (1<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<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<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<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<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<SubWindowShift ? Local.SX : 1<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<MODE_CYCLIQUE,FLAGS->INVERSE); // 2) */ } if (!(FLAGS->INVERSE)) { /* Divide 0° and 45° by 2 */ //MAP16_HOUGHDivide0And45(&Local,(1<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<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); }