/*===================================================================================
function: OTSU_Algorithm
input : image data
output : threshold value
return : void
====================================================================================*/
void OTSU_Algorithm()//OTSU algorithm
{
INT16 i;
INT16 j;
INT16 NUM=4; //block num 4*4
INT16 h=g_ImgHeight/NUM;
INT16 w=g_ImgWidth/NUM;
INT16 h_src=g_ImgHeight/NUM;
INT16 w_src=g_ImgWidth/NUM;
INT32 GrayHistogram[256];//program start
BYTE *src=g_pImg;
INT16 nPixel;
INT16 m=0,n=0;
float u0,u1;
float w0,w1;
int nCount0;
int nT,nBestT;
float fVaria,fMaxVaria = 0;
int nSum=h*w;
INT16 ww=g_ImgWidth- w*(NUM-1); //edge's block width
INT16 hh=g_ImgHeight-h*(NUM-1); //edge's block height
INT16 ii=0,jj=0;
for(m=0;m<NUM;m++)
{
for(n=0;n<NUM;n++)
{
if(3==m&&3!=n)
{
w=ww;
h=h_src;
}else if(3!=m&&3==n)
{
h=hh;
w=w_src;
}else if(3==m&&3==n)
{
w=ww;
h=hh;
}else{
w=w_src;
h=h_src;
}
for(int i=0;i<256;i++)//initialization
{
GrayHistogram[i]=0;
}
for(i=0;i<h;i++)//core step
{
for(j=0;j<w;j++)
{
ii=i+m*h_src;
jj=j+n*w_src;
nPixel=src[ii*g_ImgWidth+jj]; //statistics point
GrayHistogram[nPixel]++;
}
}
for(nT=0;nT<256;nT++)//core part
{
//compute C0 part
u0 = 0;
nCount0=0;
for(i=0;i<=nT;i++)
{
u0+=i*GrayHistogram[i]; //compute average
nCount0+=GrayHistogram[i];
}
u0 /=nCount0;
w0 =(float)nCount0*1.0/nSum;
//compute C1 part
u1 = 0;
for(i=nT+1;i<256;i++)
{
u1+=i*GrayHistogram[i]; //compute average
}
w1 = 1-w0;
//compute variance
fVaria =w0*w1*(u0-u1)*(u0-u1);
if(fVaria>fMaxVaria)
{
fMaxVaria=fVaria;
nBestT =nT;
}
}
for(i=0;i<h;i++)//core step
{
for(j=0;j<w;j++)
{
ii=i+m*h_src;
jj=j+n*w_src;
nPixel=src[ii*g_ImgWidth+jj]; //statistics point
if(nPixel<nBestT)
{
src[ii*g_ImgWidth+jj]=0;
}else{
src[ii*g_ImgWidth+jj]=255;
}
GrayHistogram[nPixel]++;
}
}
fMaxVaria=0;
nBestT=0;
}
}
}
/*===================================================================================
function: Seed_S_Find
input : image data,seed point
output : image
return : void
====================================================================================*/
struct stCardRectangle Seed_S_Find(BYTE *src,BYTE *Middle_Img,INT16 x,INT16 y)
{
INT16 Step_Path=20;
INT16 x0=0,y0=0,x1=0,y1=0,xx=0,yy=0;
INT16 i,j,num;
BOOL No_Seed=FALSE,Top=TRUE,Down=TRUE,Left=TRUE,Right=TRUE;
BYTE Seed_Value=src[y*g_ImgWidth+x],Seed_New;//seed point value
//Current_Line
//1、right search
for(i=x;i<(x+Step_Path);i++)
{
if(i<g_ImgWidth)
{
Seed_New=src[y*g_ImgWidth+i];
if(ABS((Seed_New-Seed_Value))<4)
{
Middle_Ims[y*g_ImgWidth+i]=255;
x1=i;
}else{
break;
}
}else{
x1=g_ImgWidth-1;
break;
}
}
//2、left search
for(i=x;i>=(x-Step_Path);i--)
{
if(i>=0)
{
Seed_New=src[y*g_ImgWidth+i];
if(ABS((Seed_New-Seed_Value))<4)
{
Middle_Ims[y*g_ImgWidth+i]=255;
x0=i;
}else{
break;
}
}else{
x0=0;
break;
}
}
y0=y;
y1=y;
xx=0;
yy=0;
for(num=1;num<Step_Path;num++)
{
//1、top
yy=0;
if(FALSE!=Top)
{
if((y-num)<0)
{
y0=0;
Top=FALSE;
}
for(i=x-num;i<=x+num;i++)
{
if(i>=0&&i<g_ImgWidth)
{
Seed_New=src[(y-num)*g_ImgWidth+i];
if(ABS((Seed_New-Seed_Value))<4)
{
Middle_Ims[(y-num)*g_ImgWidth+i]=255;
yy+=1;
}
}
}
if(yy>1)
{
yy=0;
y0=y-num;
}else{
Top=FALSE;
yy=0;
}
}
//2、down
yy=0;
if(FALSE!=Down)
{
if((y+num)>(g_ImgHeight-1))
{
y1=g_ImgHeight-1;
Down=FALSE;
}
for(i=x-num;i<=x+num;i++)
{
if(i>=0&&i<g_ImgWidth)
{
Seed_New=src[(y+num)*g_ImgWidth+i];
if(ABS((Seed_New-Seed_Value))<4)
{
Middle_Ims[(y+num)*g_ImgWidth+i]=255;
yy+=1;
}
}
}
if(yy>1)
{
yy=0;
y1=y+num;
}else{
yy=0;
Down=FALSE;
}
}
//3、left
xx=0;
if(FALSE!=Left)
{
if((x-num)<0)
{
x0=0;
Left=FALSE;
}
for(i=y-num;i<=(y+num);i++)
{
if(i>=0&&i<g_ImgHeight)
{
Seed_New=src[i*g_ImgWidth+x-num];
if(ABS((Seed_New-Seed_Value))<4)
{
Middle_Ims[i*g_ImgWidth+x-num]=255;
xx+=1;
}
}
}
if(xx>1)
{
xx=0;
if(x0>(x+num))
{
x0=x+num;
}
}else{
xx=0;
Left=FALSE;
}
}
//4、right
xx=0;
if(FALSE!=Right)
{
if((x+num)>(g_ImgWidth-1))
{
x1=g_ImgWidth-1;
Right=FALSE;
}
for(i=y-num;i<=y+num;i++)
{
if(i>=0&&i<g_ImgHeight)
{
Seed_New=src[i*g_ImgWidth+x+num];
if(ABS((Seed_New-Seed_Value))<4)
{
Middle_Ims[i*g_ImgWidth+x+num]=255;
xx+=1;
}
}
}
if(xx>1)
{
xx=0;
if(x1<(x+num))
{
x1=x+num;
}
}else{
xx=0;
Right=FALSE;
}
}
}
struct stCardRectangle re;
re.x0=x0;
re.y0=y0;
re.x1=x1;
re.y1=y1;
return re;
}
/*===================================================================
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)=255;
}else{
*(out+i)=0;
}
}
}