【图像处理】 最大类间方差算法(Otus算法)
Otsu算法的原理
最大类间方差法(Otus算法),可以自动的选取二值化的阈值。
它的原理如下:
- 假设一副灰度图有 L L L个灰度级,即 [ 1 , 2 , 3 , . . . L ] [1,2,3,...L] [1,2,3,...L] ,灰度级为 i i i的像素点有 n i n_i ni个,那么总的像素点个数 N = n 1 + n 2 + . . . + n l N = n_1 + n_2 +...+n_l N=n1+n2+...+nl。那么一个像素点灰度级为 i i i的概率为: p i = n i N ( p i > 0 , ∑ i = 1 L p i = 1 ) p_i = \dfrac{n_i}{N} (p_i>0,\displaystyle\sum_{i = 1}^{L}p_i = 1) pi=Nni(pi>0,i=1∑Lpi=1)。
- 现在假设通过一个灰度级 k k k将这些像素点划分为两类 C 0 C_0 C0和 C 1 C_1 C1, [ 1 , 2 , . . . k ] [1,2,...k] [1,2,...k]是 C 0 C_0 C0,二值化为 0 0 0。 [ k + 1 , k + 2 , . . . L ] [k+1,k+2,...L] [k+1,k+2,...L]是 C 1 C_1 C1,二值化为 255 255 255。Otsu算法就是自动的找到这个算法认为的最优的阈值 k k k。
-
C
0
C_0
C0和
C
1
C_1
C1两类,每一类出现的概率以及各类的平均灰度级分别由下面的式子给出:
ω 0 = P r ( C 0 ) = C 0 类出现的概率 = ∑ i = 1 k p i = ω ( k ) \omega_0=P_r(C_0)=C_0类出现的概率=\displaystyle\sum_{i = 1}^{k}p_i = \omega(k) ω0=Pr(C0)=C0类出现的概率=i=1∑kpi=ω(k)
ω 1 = P r ( C 1 ) = C 1 类出现的概率 = ∑ i = k + 1 L p i = 1 − ω ( k ) \omega_1=P_r(C_1)=C_1类出现的概率=\displaystyle\sum_{i = k+1}^{L}p_i =1- \omega(k) ω1=Pr(C1)=C1类出现的概率=i=k+1∑Lpi=1−ω(k)
μ 0 = ∑ i = 1 k i ∗ P r ( i ∣ C 0 ) = ∑ i = 1 k i ∗ p i ω 0 = C 0 类的平均灰度级 = μ ( k ) ω ( k ) \mu_0=\displaystyle\sum_{i = 1}^{k}i*P_r( i|C_0)=\displaystyle\sum_{i = 1}^{k}i* \dfrac{p_i}{\omega_0}=C_0类的平均灰度级=\dfrac{\mu(k)}{\omega(k)} μ0=i=1∑ki∗Pr(i∣C0)=i=1∑ki∗ω0pi=C0类的平均灰度级=ω(k)μ(k)
μ 1 = ∑ i = k + 1 L i ∗ P r ( i ∣ C 1 ) = ∑ i = k + 1 L i ∗ p i ω 1 = C 1 类的平均灰度级 = μ T − μ ( k ) 1 − ω ( k ) \mu_1=\displaystyle\sum_{i = k+1}^{L}i*P_r( i|C_1)=\displaystyle\sum_{i = k+1}^{L}i* \dfrac{p_i}{\omega_1}=C_1类的平均灰度级=\dfrac{\mu_T-\mu(k)}{1-\omega(k)} μ1=i=k+1∑Li∗Pr(i∣C1)=i=k+1∑Li∗ω1pi=C1类的平均灰度级=1−ω(k)μT−μ(k)
其中:
μ ( k ) = ∑ i = 1 k i ∗ p i \mu(k)=\displaystyle\sum_{i = 1}^{k}i*p_i μ(k)=i=1∑ki∗pi,是 1 到 k 1到k 1到k的平均灰度级。
μ T = ∑ i = 1 L i ∗ p i \mu_T=\displaystyle\sum_{i = 1}^{L}i*p_i μT=i=1∑Li∗pi,是整幅图的平均灰度级。 - 容易验证:
ω 0 μ 0 + ω 1 μ 1 = μ T \omega_0\mu_0+\omega_1\mu_1=\mu_T ω0μ0+ω1μ1=μT, ω 0 + ω 1 = 1 \omega_0+\omega_1=1 ω0+ω1=1 -
C
0
C_0
C0和
C
1
C_1
C1各自的类内方差如下:
σ 0 2 = ∑ i = 1 k ( i − μ 0 ) 2 P r ( i ∣ C 0 ) = ∑ i = 1 k ( i − μ 0 ) 2 p i ω 0 \sigma_0^2=\displaystyle\sum_{i = 1}^{k}(i-\mu_0)^2P_r(i|C_0)=\displaystyle\sum_{i = 1}^{k}(i-\mu_0)^2\dfrac{p_i}{\omega_0} σ02=i=1∑k(i−μ0)2Pr(i∣C0)=i=1∑k(i−μ0)2ω0pi
σ 1 2 = ∑ i = k + 1 L ( i − μ 1 ) 2 P r ( i ∣ C 1 ) = ∑ i = k + 1 L ( i − μ 1 ) 2 p i ω 1 \sigma_1^2=\displaystyle\sum_{i = k+1}^{L}(i-\mu_1)^2P_r(i|C_1)=\displaystyle\sum_{i = k+1}^{L}(i-\mu_1)^2\dfrac{p_i}{\omega_1} σ12=i=k+1∑L(i−μ1)2Pr(i∣C1)=i=k+1∑L(i−μ1)2ω1pi - 所以整幅图片的类内方差,两个类的类间方差,图片的总方差,分别如下:
σ W 2 = 整幅图片的类内方差 = ω 0 σ 0 2 + ω 1 σ 1 2 \sigma_W^2=整幅图片的类内方差=\omega_0\sigma_0^2+\omega_1\sigma_1^2 σW2=整幅图片的类内方差=ω0σ02+ω1σ12
σ B 2 = 两个类的类间方差 = ω 0 ( μ 0 − μ T ) 2 + ω 1 ( μ 1 − μ T ) 2 \sigma_B^2=两个类的类间方差=\omega_0(\mu_0-\mu_T)^2+\omega_1(\mu_1-\mu_T)^2 σB2=两个类的类间方差=ω0(μ0−μT)2+ω1(μ1−μT)2
跟据4.中两个等式,可以将 σ B 2 \sigma_B^2 σB2化简为 ω 0 ω 1 ( μ 1 − μ 0 ) 2 \omega_0\omega_1(\mu_1-\mu_0)^2 ω0ω1(μ1−μ0)2
σ T 2 = 图片的总方差 = ∑ i = 1 L ( i − μ T ) 2 p i \sigma_T^2=图片的总方差=\displaystyle\sum_{i = 1}^{L}(i-\mu_T)^2p_i σT2=图片的总方差=i=1∑L(i−μT)2pi - 因为 σ T 2 \sigma_T^2 σT2与 k k k无关。 σ W 2 \sigma_W^2 σW2是二阶统计(类方差),而 σ B 2 \sigma_B^2 σB2是一阶统计(类均值)。所以 σ B 2 \sigma_B^2 σB2,即类间方差是最简单的判断 k k k选取好坏的评判标准。
- 所以Otus算法遍历 k k k,最后选取使 σ B 2 \sigma_B^2 σB2最大的 k k k作为阈值。
opencv中的Otsu算法
_, img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 在python opencv的二值化函数cv.threshold中,通过最后的参数选择使用Otus算法
# 第一个输入是输入的灰度图像
# 第二个参数是阈值,因为这个由算法自动选择,所以填0
# 第三个参数是最大值,即大于阈值的像素点都等于这个值,小于阈值的都是0
# 第一个返回值就是所取的阈值,如果不用Otus算法,第一个返回值也是我们选取的阈值
# 第二个返回值是二值图
结语
如果您有修改意见或问题,欢迎留言或者通过邮箱和我联系。
如果我的文章对您有帮助,转载请注明出处。