INT16 g_ObjectXbuf[MAX_OBJECTSTACK_NUM];
INT16 g_ObjectYbuf[MAX_OBJECTSTACK_NUM];
INT16 g_Region_Num=0;
void Card_Region_Average() //label region
{
INT16 i=0,y=0,x=0;
INT16 sum=0,sum1=0;
INT16 x0,y0,x1,y1;
INT16 AVE=0;
BYTE *pMD;
BYTE *pM;
for(i=0;i<g_Region_Num;i++) //???
{
//1、Get average
sum1=0;
sum=0;
AVE=0;
x0=g_Rect_data[i].x0;
y0=g_Rect_data[i].y0;
x1=g_Rect_data[i].x1;
y1=g_Rect_data[i].y1;
pM =g_pImg+y0*g_ImgWidth;
pMD=g_pHagImg+y0*g_ImgWidth;
for(y=y0;y<y1;y++)
{
for(x=x0;x<=x1;x++)
{
if( 0 != pMD[x] )
{
sum+=pM[x];
sum1++;
}
}
pM +=g_ImgWidth;
pMD+=g_ImgWidth;
}
//2、Get average
if(sum1>0)
{
AVE=sum/sum1;
}else{
AVE=0;
}
pM =g_pImg +y0*g_ImgWidth;
pMD=g_pHagImg+y0*g_ImgWidth;
for(y=y0;y<=y1;y++)
{
for(x=x0;x<=x1;x++)
{
if(0<*(pMD+x)&&(AVE+10)<*(pM+x))//???
{
*(pMD+x)=0;
}
}
pM +=g_ImgWidth;
pMD+=g_ImgWidth;
}
}
}
/*===================================================================================
function: Card_Rectangle
input : void
output : void
return : void
====================================================================================*/
void Card_Rectangle()
{
INT32 pb,pf;
INT16 x,y,n,yy,xx;
INT16 x0,x1,y0,y1;
INT16 numm=0;
INT16 sum=0;
INT16 Py[8]={-1,-1,-1, 0,0, 1,1,1};
INT16 Px[8]={-1, 0, 1,-1,1,-1,0,1};
BYTE middle_data;
BYTE Pixel_Neighborhood[8];
BYTE *pMD;
BYTE *pM;
//step 1
pMD=g_pHagImg+g_ImgWidth;
for(y=1;y<g_ImgHeight-1;y++)
{
for(x=1;x<g_ImgWidth-1;x++)
{
if( 0 == pMD[x] )
{
continue;
}
pM=pMD+x;
//=================================================
x0=x;
x1=x;
y0=y;
y1=y;
yy=y;
xx=x;
pb=0;
pf=1;
//=================================================
*pM=254;
while(pb<=pf)
{
//========================================
if(xx<x0)
{
x0=xx;
}else if(xx>x1)
{
x1=xx;
}
if(yy<y0)
{
y0=yy;
}else if(yy>y1)
{
y1=yy;
}
//=========================================
for(n=0;n<8;n++)
{
Pixel_Neighborhood[n]=*(pM+Py[n]*g_ImgWidth+Px[n]);
if(255==Pixel_Neighborhood[n])
{
xx=xx+Px[n];
yy=yy+Py[n];
if(xx>=0&&xx<g_ImgWidth&&yy>=0&&yy<g_ImgHeight)
{
sum++;
*(pM+Py[n]*g_ImgWidth+Px[n])=254;
pM=pM+Py[n]*g_ImgWidth+Px[n]; //next target point
pf++;
break;//jump for
}
}
}
//===========================================
pb++;//quit condition
}
if(numm<Max_len&&sum>4)
{
g_Rect_data[numm].x0=x0;
g_Rect_data[numm].y0=y0;
g_Rect_data[numm].x1=x1;
g_Rect_data[numm].y1=y1;
numm++;
}
sum=0;
}
pMD+=g_ImgWidth;
}
g_Region_Num=numm;
}
/*===================================================================================
function: Second_Search_Rectangle
input : void
output : void
return : void
====================================================================================*/
void Second_Search_Rectangle()
{
INT16 i=0,y=0,x=0;
INT16 m=0;
INT16 x0,y0,x1,y1;
BYTE *pMD,*pM;
BOOL Top=FALSE,Down=FALSE,Left=FALSE,Right=FALSE;
pMD=g_pHagImg;
for(i=0;i<g_Region_Num;i++)
{
//1、top
//====================================================
x0=g_Rect_data[i].x0;
y0=g_Rect_data[i].y0;
x1=g_Rect_data[i].x1;
y1=g_Rect_data[i].y1;
pM=pMD+y0*g_ImgWidth;
for(y=y0;y<=y1;y++)
{
for(x=x0;x<=x1;x++)
{
if(*(pM+x)>0)
{
Top=TRUE;
break;
}
}
if(FALSE!=Top)
{
g_Rect_data[i].y0=y;
break;
}
pM+=g_ImgWidth;
}
//======================================================
//2、down
//======================================================
pM=pMD+y1*g_ImgWidth;
for(y=y1;y>=y0;y--)
{
for(x=x0;x<=x1;x++)
{
if(*(pM+x)>0)
{
Down=TRUE;
break;
}
}
if(FALSE!=Down)
{
g_Rect_data[i].y1=y;
break;
}
pM-=g_ImgWidth;
}
//========================================================
//3、left
//========================================================
for(x=x0;x<=x1;x++)
{
for(y=y0;y<=y1;y++)
{
if(*(pMD+y*g_ImgWidth+x)>0)
{
Left=TRUE;
break;
}
}
if(FALSE!=Left)
{
g_Rect_data[i].x0=x;
break;
}
}
//==========================================================
//4、right
//==========================================================
for(x=x1;x>=x0;x--)
{
for(y=y0;y<=y1;y++)
{
if(*(pMD+y*g_ImgWidth+x)>0)
{
Right=TRUE;
break;
}
}
if(FALSE!=Right)
{
g_Rect_data[i].x1=x;
break;
}
}
//=========================================================
//=========================================================
if(FALSE==Top||FALSE==Down||FALSE==Left||FALSE==Right)
{
pM=pMD+y0*g_ImgWidth;
for(y=y0;y<=y1;y++)
{
for(x=x0;x<=x1;x++)
{
*(pM+x)=0;
}
pM+=g_ImgWidth;
}
for(m=i+1;m<g_Region_Num;m++)
{
g_Rect_data[i].x0=g_Rect_data[m].x0;
g_Rect_data[i].y0=g_Rect_data[m].y0;
g_Rect_data[i].x1=g_Rect_data[m].x1;
g_Rect_data[i].y1=g_Rect_data[m].y1;
}
g_Region_Num--;
}
//========================================================
}
}
/*===================================================================================
function: Card_RegionGrow
input : void
output : void
return : void
====================================================================================*/
void Card_RegionGrow(void)
{
Card_Point current;
INT16 i,y,x,sum=0,num1=0,AVE=0;
INT16 x0,y0,x1,y1;
INT16 T=0;
BYTE *pMD;
BYTE *pM;
BYTE *pM1;
BYTE *pM2;
BOOL Top=FALSE,Down=FALSE,Left=FALSE,Right=FALSE;
BOOL Flag=FALSE;
pMD=g_pHagImg; //Last step
pM=g_pImg; //pM Image
for(i=0;i<g_Region_Num;i++)
{
x0=g_Rect_data[i].x0;
y0=g_Rect_data[i].y0;
x1=g_Rect_data[i].x1;
y1=g_Rect_data[i].y1;
current.x0=x0;
current.y0=y0;
//==================================================
pM1=pMD+y0*g_ImgWidth;
pM2=pM +y0*g_ImgWidth;
for(y=y0;y<=y1;y++)
{
for(x=x0;x<=x1;x++)
{
if(*(pM1+x)>0)
{
sum+=*(pM2+x);
num1+=1;
if(num1==1)
{
current.x0=x;
current.y0=y;
}
}
}
pM1+=g_ImgWidth;
pM2+=g_ImgWidth;
}
if(num1>0)//select T
{
AVE=sum/num1;
T=AVE+20;
}else{
AVE=0;
T=0;
}
//=====================================================
num1=0;
sum=0;
//1、top
//=======================================================
for(x=x0;x<=x1;x++)
{
for(y=y0;y<=y1;y++)
{
if(*(pMD+y*g_ImgWidth+x)>0)
{
current.x0=x;
current.y0=y;
Top=TRUE;
break;
}
}
if(Top==TRUE)
{
Seed_Grow_Core(current,pMD,pM,T);
}
Top=FALSE;
}
//========================================================
//2、down
//========================================================
for(x=x0;x<=x1;x++)
{
for(y=y1;y>=y0;y--)
{
if(*(pMD+y*g_ImgWidth+x)>0)
{
current.x0=x;
current.y0=y;
Down=TRUE;
break;
}
}
if(Down==TRUE)
{
Seed_Grow_Core(current,pMD,pM,T);
}
Down=FALSE;
}
//========================================================
//3、left
//========================================================
pM1=pMD;
for(y=y0;y<=y1;y++)
{
for(x=x0;x<=x1;x++)
{
if(*(pM1+x)>0)
{
current.x0=x;
current.y0=y;
Left=TRUE;
break;
}
}
if(Left==TRUE)
{
Seed_Grow_Core(current,pMD,pM,T);
}
Left=FALSE;
pM1+=g_ImgWidth;
}
//======================================================
//4、right
//======================================================
pM1=pMD;
for(y=y0;y<=y1;y++)
{
for(x=x1;x>=x0;x--)
{
if(*(pM1+x)>0)
{
current.x0=x;
current.y0=y;
Right=TRUE;
break;
}
}
if(Right==TRUE)
{
Seed_Grow_Core(current,pMD,pM,T);
}
Right=FALSE;
pM1+=g_ImgWidth;
}
//=======================================================
}
//===========================================================
}
/*===================================================================================
function: Seed_Grow_Core
input : void
output : void
return : void
====================================================================================*/
void Rect_Filter()
{
BOOL Flag=TRUE;
BYTE *pMD;
pMD=g_pHagImg;
#if 0
CString strPath;
CDib mydib;
char buf1[1024];
strPath.Format("%s\\Recog_RCline", g_CardPicPathName);
if(!File_Is_Exist(strPath) )
{
_mkdir( strPath );
}
sprintf(buf1,"%s\\1%s",strPath,g_CardPicFileName);
mydib.rWidth=g_ImgWidth;
mydib.Width=g_ImgWidth;
mydib.Height=g_ImgHeight;
mydib.WriteGrayBmp(buf1, pMD);
#endif
//=========================================================================
Flag=RidLineX_Z(pMD,g_ImgWidth,g_ImgHeight,2);
if(FALSE==Flag)
{
return;
}
#if 0
char buf2[1024];
sprintf(buf2,"%s\\2%s",strPath,g_CardPicFileName);
mydib.WriteGrayBmp(buf2, pMD);
#endif
//==========================================================================
Flag=RidLineY_Z(pMD,g_ImgWidth,g_ImgHeight,2);
if(FALSE==Flag)
{
return;
}
#if 0
char buf3[1024];
sprintf(buf3,"%s\\3%s",strPath,g_CardPicFileName);
mydib.WriteGrayBmp(buf3, pMD);
#endif
//==========================================================================
}
/*=====================================================================================
function: Seed_Grow_Core
input : void
output : void
return : void
====================================================================================*/
void Seed_Grow_Core(Card_Point current,BYTE *pMD,BYTE *pM,INT16 T)
{
INT32 START=0,END=0;
INT16 xx=0,yy=0,m=0;
INT16 Fx,Fy;
INT16 Dx[]={-1,0,1,0};
INT16 Dy[]={0,1,0,-1};
INT16 B,S;
START=0;
END=0;
g_OCR_ObjectXbuf[START]=current.x0;
g_OCR_ObjectYbuf[START]=current.y0;
Fx=current.x0;
Fy=current.y0;
//============================================================================
while(START<=END)
{
current.x0=g_OCR_ObjectXbuf[START];
current.y0=g_OCR_ObjectYbuf[START];
for(m=0;m<4;m++)
{
xx = current.x0+Dx[m];
yy = current.y0+Dy[m];
if(xx>=0&&xx<g_ImgWidth&&yy>=0&&yy<g_ImgHeight\
&&xx>=(Fx-Radius)&&xx<=(Fx+Radius)&&yy>=(Fy-Radius)&&yy<=(Fy+Radius))
{
B=*(pMD+yy*g_ImgWidth+xx);
S=*(pM +yy*g_ImgWidth+xx);
if(S<=T&&B==0)
{
if(END<Max_Point)
{
g_OCR_ObjectXbuf[END]=xx;
g_OCR_ObjectYbuf[END]=yy;
END++;
}else{
START=END+1;
break;
}
*(pMD+yy*g_ImgWidth+xx)=255;
}
}
}
START++;
}
//=============================================================================
}
/*===================================================================
function: RidLineX
input : Source Image X position filter
output : Result Image
====================================================================*/
BOOL RidLineX_Z(BYTE *pD,int w,int h,int dx)
{
INT16 x,y;
INT16 x0,x1;
BYTE *pMD,*pMD0,*pMF;
if(pD==NULL)
{
return FALSE;
}
if(w<(dx<<1))
{
return FALSE;
}
if(dx<2)
{
return FALSE;
}
pMD=pD;
for(y=0;y<h;y++)
{
pMD0=pMD;
pMD+=g_ImgWidth;
for(x=0;x<w;x++)
{
//Search First Point
x0=-1;
for(;x<w;x++)
{
if( 0 != *pMD0 )
{
pMF=pMD0;
x0=x;
break;
}
pMD0++;
}
if(x0<0)
{
break;
}
//Search End Point
x1=w-1;
for(;x<w;x++)
{
if( 0 == *pMD0)
{
x1=x-1;
break;
}
pMD0++;
}
if( (x1-x0+1) >= dx )
{
continue;
}
memset(pMF, 0, x1-x0+1);
}
}
return TRUE;
}
/*===================================================================
function: RidLineX
input : Source Image X position filter
output : Result Image
====================================================================*/
BOOL RidLineY_Z(BYTE *pD,int w,int h,int dy)
{
INT16 x,y;
INT16 y0,y1,m;
BYTE *pM,*pMD,*pMF;
if(pD==NULL&&w>g_ImgWidth&&h>g_ImgHeight&&w<=0&&h<=0&&dy<=0)
{
return FALSE;
}
if(h<(dy<<1))
{
return FALSE;
}
//==================================================================
pMD=pD;
for(x=0;x<w;x++)
{
pM=pMD;
for(y=0;y<h;y++)
{
//=============================================
//y0
y0=-1;
for(;y<h;y++)
{
if(0!=*pM)
{
y0=y;
pMF=pM;
break;
}
pM+=g_ImgWidth;
}
if(y0<0)
{
break;
}
//=============================================
//=============================================
//y1
y1=-1;
for(;y<h;y++)
{
if(0==*pM)
{
y1=y;
break;
}
pM+=g_ImgWidth;
}
if(y1<0)
{
if((h-y0)<dy)
{
for(m=y0;m<h;m++)
{
*pMF =0;
pMF+=g_ImgWidth;
}
}
}
else
{
if((y1-y0)<dy)
{
for(m=y0;m<y1;m++)
{
*pMF =0;
pMF+=g_ImgWidth;
}
}
}
//=============================================
}
pMD+=1;
}
//==================================================================
return TRUE;
}
/*===================================================================
function: Card_S_Sobel
input : Parameter rows is height,Parameter cols is width
output : Result Image
====================================================================*/
void Card_S_Sobel(BYTE *in,INT16 rows,INT16 cols,BYTE *out)
{
INT32 i=0;
INT16 H, O, V, Or;
INT16 i00, i01,i02;
INT16 i10, i12;
INT16 i20, i21, i22;
INT16 w = cols;
for (i = 0; i < cols*(rows-2) - 2; i++)
{
i00=*(in+i);
i01=*(in+i +1);
i02=*(in+i +2);
i10=*(in+i+w);
i12=*(in+i+w+2);
i20=*(in+i+w+w);
i21=*(in+i+w+w+1);
i22=*(in+i+w+w+2);
H = - i00 - 2*i01 - i02 +
+ i20 + 2*i21 + i22;
V = - i00 + i02
- 2*i10 + 2*i12
- i20 + i22;
O =(ABS(H)>ABS(V))?ABS(H):ABS(V);
if(O>206)
{
*(out+i)=100;
}
}
}