大津算法
方法
在大津算法中,我们穷举搜索能使类内方差最小的阈值,定义为两个类的方差的加权和:
权重 ω ω -->i{\displaystyle \omega _{i}} 是被阈值 t{\displaystyle t} 分开的两个类的概率,而 σ σ -->i2{\displaystyle \sigma _{i}^{2}} 是这两个类的方差。
大津证明了最小化类内方差和最大化类间方差是相同的:
用类概率 ω ω -->i{\displaystyle \omega _{i}} 和类均值 μ μ -->i{\displaystyle \mu _{i}} 来表示。
类概率 ω ω -->1(t){\displaystyle \omega _{1}(t)} 用阈值为 t{\displaystyle t} 的直方图计算:
而类均值 μ μ -->1(t){\displaystyle \mu _{1}(t)} 为:
其中 x(i){\displaystyle x(i)} 为第 i{\displaystyle i} 个直方图面元中心的值。 同样的,你可以对大于 t{\displaystyle t} 的面元求出右侧直方图的 ω ω -->2(t){\displaystyle \omega _{2}(t)} 与 μ μ -->2{\displaystyle \mu _{2}}。
类概率和类均值可以迭代计算。这个想法会产生一个有效的算法。
大津算法得出了0:1范围上的一个阈值。这个阈值用于图像现的像素强度的动态范围。例如,若图像只包含155到255之间的像素强度,大津阈值0.75会映射到灰度阈值230(而不是192,因为图像包含的像素不是0–255全范围的)。常见的摄影图像往往包含全范围的像素强度,就会让这一点有争论,但其他应用会对这点区别很敏感。
算法
计算每个强度级的直方图和概率
设置 ω ω -->i(0){\displaystyle \omega _{i}(0)} 和 μ μ -->i(0){\displaystyle \mu _{i}(0)} 的初始值
遍历所有可能的阈值 t=1… … -->{\displaystyle t=1\ldots } 最大强度
所需的阈值对应于最大的 σ σ -->b2(t){\displaystyle \sigma _{b}^{2}(t)}
你可以计算两个最大值(和两个对应的)。σ σ -->b12(t){\displaystyle \sigma _{b1}^{2}(t)} 是最大值而 σ σ -->b22(t){\displaystyle \sigma _{b2}^{2}(t)} 是更大的或相等的最大值
所需的阈值 = threshold1+threshold22{\displaystyle {\frac {{\text{threshold}}_{1}+{\text{threshold}}_{2}}{2}}}
JavaScript实现
注:输入参数total是给定图像中的像素数。输入参数histogram是灰度图像不同灰度级(典型的8位图像)的256元直方图。此函数输出图像的阈值。
functionotsu(histogram,total){varsum=0;for(vari=1;i256;++i)sum+=i*histogram[i];varsumB=0;varwB=0;varwF=0;varmB;varmF;varmax=0.0;varbetween=0.0;varthreshold1=0.0;varthreshold2=0.0;for(vari=0;i256;++i){wB+=histogram[i];if(wB==0)continue;wF=total-wB;if(wF==0)break;sumB+=i*histogram[i];mB=sumB/wB;mF=(sum-sumB)/wF;between=wB*wF*(mB-mF)*(mB-mF);if(between>=max){threshold1=i;if(between>max){threshold2=i;}max=between;}}return(threshold1+threshold2)/2.0;}
MATLAB实现
total为给定图像中的像素数。 histogramCounts为灰度图像不同灰度级(典型的8位图像)的256元直方图。 level为图像的阈值(double)。
functionlevel =otsu(histogramCounts, total)%% OTSU automatic thresholding methodsumB=0;wB=0;maximum=0.0;threshold1=0.0;threshold2=0.0;sum1=sum((1:256).*histogramCounts.");% the above code is replace with this single lineforii=1:256wB=wB+histogramCounts(ii);if(wB==0)continue;endwF=total-wB;if(wF==0)break;endsumB=sumB+ii*histogramCounts(ii);mB=sumB/wB;mF=(sum1-sumB)/wF;between=wB*wF*(mB-mF)*(mB-mF);if(between>=maximum)threshold1=ii;if(between>maximum)threshold2=ii;endmaximum=between;endendlevel=(threshold1+threshold2)/(2);end
另一种方法是用向量化方法(可以很容易地转换为便于GPU处理Python矩阵数组版本)
function[threshold_otsu] =Thredsholding_Otsu( Image)%Intuition:%(1)pixels are divided into two groups%(2)pixels within each group are very similar to each other % Parameters:% t : threshold % r : pixel value ranging from 1 to 255% q_L, q_H : the number of lower and higher group respectively% sigma : group variance% miu : group mean% Author: Lei Wang% Date : 22/09/2013% References : Wikepedia, % for multi children Otsu method, please visit : aring% This is my original worknbins=256;counts=imhist(Image,nbins);p=counts/sum(counts);fort=1:nbinsq_L=sum(p(1:t));q_H=sum(p(t+1:end));miu_L=sum(p(1:t).*(1:t)")/q_L;miu_H=sum(p(t+1:end).*(t+1:nbins)")/q_H;sigma_b(t)=q_L*q_H*(miu_L-miu_H)^2;end[~,threshold_otsu]=max(sigma_b(:));end
该实现有一点点冗余的计算。但由于大津算法快速,这个实现版本是可以接受,并且易于理解的。因为在一些环境中,如果使用向量化的形式,可以更快地运算循环。大津二值化法使用架构最小的堆-孩子标签(heap-children label)可以很容易地转变成多线程的方法。
免责声明:以上内容版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。感谢每一位辛勤著写的作者,感谢每一位的分享。
- 有价值
- 一般般
- 没价值