几种灰度图二值化处理的典型算法及vc++实现的代码

1、大律法

                      大津法又称最大类间方差法。对图像,记t为前景与背景的分割阈值,前景点数占图像比例为 w0, 平均灰度为u0;背景点数占图像比例为w1,平均灰度为u1。图像的总平均灰度为:u=w0*u0+w1*u1。从最小灰度值到最大灰度值遍历t,        当t使 得值      g=w0*(u0-u)2 +w1*(u1-u)2 最大时t即为分割的最佳阈值。阈值t分割出的前景和背景两部分构成了整幅图像,而前景取值u0,概率为w0,背景取值u1,概率为w1,总均值为u,根据 方差的定义即得该式。因方差是灰度分布均匀性的一种度量,方差值越大,说明构成图像的两部分差别越大,当部分目标错分为背景或部分背景错分为目标都会导致 两部分差别变小,因此使类间方差最大的分割意味着错分概率最小。直接应用大津法计算量较大,因此我们在实现时采用了等价的公式g=w0*w1*(u0- u1)2 。

实现的代码:

               BOOL OSTUThreshold(unsigned char *image1,   LONG   lWidth,   LONG   lHeight)   
 {
int a;
//得到灰度直方图,灰度的最大值和最小值
int i,j,t;
long lCount[256];                //各个灰度值的计数
int lMaxgrayvalue=0;
int lMingrayvalue=255;
int lThreshold; //阈值
long lLineBytes; //图像每行的字节数
lLineBytes=WIDTHBYTES(lWidth);
for(a=0;a<256;a++)
{
lCount[a]=0;
}
for(i=0;i{
for(j=0;j{
    //各个灰度值的计数
lCount[image1[i*lLineBytes+j]]++;
}
}
for(i=0;i<256;i++)
{
if (lCount[i]!=0)
{
lMingrayvalue=i;
break;

}
for(i=255;i>=0;i--)
{
if(lCount[i]!=0)
{
lMaxgrayvalue=i;
break;
}
}


       //通过所有的灰度值找到阈值
float lMeangrayvalue1,lMeangrayvalue2;     //两个区域的平均灰度值
float w1,w2;       //前后两区灰度的百分比
float G;    //方差
float tempG=0;
int lP1,lP2,lS1,lS2;    //前景,后景点数
for(t=lMingrayvalue;t<=lMaxgrayvalue;t++)
{
lP1=0;
lP2=0;
lS1=0;
lS2=0;
for(a=lMingrayvalue;a<=t;a++)
{
lP1+=lCount[a]*a;
lS1+=lCount[a];
}
lMeangrayvalue1=(float) lP1/lS1;
w1=(float) lS1/(lHeight*lWidth);
for(a=t;a{
lP2+=lCount[a]*a;
lS2+=lCount[a];
}
      lMeangrayvalue2=(float) lP2/lS2;
w2=1-w1;
G=w1*w2*(lMeangrayvalue1-lMeangrayvalue2)*(lMeangrayvalue1-lMeangrayvalue2);
if(G>tempG)
{
tempG=G;
lThreshold=t;
}
}
for(i=0;i{
for (j=0;j{
if (image1[i*lLineBytes+j]>lThreshold)
{
image1[i*lLineBytes+j]=255;
}
else
{
image1[i*lLineBytes+j]=0;
}
}
}
return TRUE;
 }


2、迭代法

     

(1).  求出图象的最大灰度值和最小灰度值,分别记为Zl和Zk,令初始阈值为:

                               
    (2).  根据阈值TK将图象分割为前景和背景,分别求出两者的平均灰度值Z0和ZB:

                                     

                                     


          式中,Z(i,j)是图像上(i,j)点的象素值,N(i,j)是(i,j)点的权值,一般取1。

(3)

                               
    (4).  若TK=TK+1,则所得即为阈值,否则转2,迭代计算。

实现代码:

                 BOOL OSTUThreshold(unsigned char *image1,   LONG   lWidth,   LONG   lHeight)   
 {
int a;
//得到灰度直方图,灰度的最大值和最小值
int i,j,t;
long lCount[256];                //各个灰度值的计数
int lMaxgrayvalue=0;
int lMingrayvalue=255;
int lThreshold; //阈值
long lLineBytes; //图像每行的字节数
lLineBytes=WIDTHBYTES(lWidth);
for(a=0;a<256;a++)
{
lCount[a]=0;
}
for(i=0;i{
for(j=0;j{
    //各个灰度值的计数
lCount[image1[i*lLineBytes+j]]++;
}
}
for(i=0;i<256;i++)
{
if (lCount[i]!=0)
{
lMingrayvalue=i;
break;

}
for(i=255;i>=0;i--)
{
if(lCount[i]!=0)
{
lMaxgrayvalue=i;
break;
}
}


       //通过所有的灰度值找到阈值
float lMeangrayvalue1,lMeangrayvalue2;     //两个区域的平均灰度值
float w1,w2;       //前后两区灰度的百分比
float G;    //方差
float tempG=0;
int lP1,lP2,lS1,lS2;    //前景,后景点数
for(t=lMingrayvalue;t<=lMaxgrayvalue;t++)
{
lP1=0;
lP2=0;
lS1=0;
lS2=0;
for(a=lMingrayvalue;a<=t;a++)
{
lP1+=lCount[a]*a;
lS1+=lCount[a];
}
lMeangrayvalue1=(float) lP1/lS1;
w1=(float) lS1/(lHeight*lWidth);
for(a=t;a{
lP2+=lCount[a]*a;
lS2+=lCount[a];
}
      lMeangrayvalue2=(float) lP2/lS2;
w2=1-w1;
G=w1*w2*(lMeangrayvalue1-lMeangrayvalue2)*(lMeangrayvalue1-lMeangrayvalue2);
if(G>tempG)
{
tempG=G;
lThreshold=t;
}
}
for(i=0;i{
for (j=0;j{
if (image1[i*lLineBytes+j]>lThreshold)
{
image1[i*lLineBytes+j]=255;
}
else
{
image1[i*lLineBytes+j]=0;
}
}
}
return TRUE;
 }


未完待续。。。。。

你可能感兴趣的:(几种灰度图二值化处理的典型算法及vc++实现的代码)