OTSU法,专业术语叫最大类间方差法,又叫大津法,这个算法是由一个日本人,叫大津展之(Nobuyuki Otsu)的提出来的。嗯,网上对于这个算法的文章很多,大多从数学方面,公式方面来讲解的。
不过我想用自己的方式来讲解一下。首先这个算法是用于灰度图像的阈值的自动计算法。主要方法是从0-255,搜索每一个像素,假设搜索变量为X,则0-X之间为前景,x-255之间背景。这个好理解。不过在这之前,先要求出直方图,即所有像素在0-255之间的每个灰度值的像素总数。
先讲几个概念,
1. 平均灰度。 平均灰度,就是把所有像素的值全部相加除以像素总数。
(1) 像素总素为图像的长乘宽。
(2) 灰度总值则是每一个像素的灰度值累加。
2. 前景平均灰度。很好理解,即,0-X之间,每一个灰度值的直方图值相乘后累加,再除以直方图值的和。
3. 背景平均灰度。和前景一样。
我举一个简化版的例子。总共五个灰度值:1,2,3,4,5。每一个灰度的总数统计为,2,3,1,3,2。这么写 1(2),2(3),3(1),4(3),5(2);
平均灰度就是:(1*2+2*3+3+4*3+5*2) /(2+3+1+3+2) 前面是总灰度值,后面是总像素值。设3同灰度阈值。
则前景平均灰度为:(1*2+2*3+3) / (2+3+1);
前面则是前景灰度值的总数,后者则是像素个数,背景也是同理。
最后求最大类间方差:
(前景平均灰度-总平均灰度)的平方 *前景百分比+(背景平均灰度-总平均灰度)的平方 *背景景百分比。取最大值。
贴一张网上的算法图:
tnum = image->width*image->height;//像素总数
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
hist[cptr[i*step + j]]++;//直方图
totalgray += cptr[i*step + j];//灰度统计,也可以用直方图来求。
}
}
avg = totalgray / tnum;//总平均灰度。
for (i = 0; i < 256; i++)
{
fSum0 = 0;
bSum1 = 0;
fnum += hist[i];
bnum = tnum - fnum;
if (0 == bnum)
{
break;
}
if (0 == fnum)
{
continue;
}
fp = fnum / tnum;
bp = 1 - fp;
for (j = 0; j <= i; j++)
{
fSum0 += j*hist[j];
}
favg = fSum0 / fnum;
for (j = i + 1; j < 256; j++)
{
bSum1 += j*hist[j];
}
bavg = bSum1 / bnum;
g = fp*(favg - avg)*(favg - avg) + bp*(bavg - avg)*(bavg - avg);
if (tmpg < g)
{
tmpg = g;
T = i;
}
以lena为例,计算得出123为自动阈值。
结果二值化后的图像为:
这个的确是最优效果阈值。
源代码链接: https://download.****.net/download/finger157959/12528142