图像分割——大津法(Otsu)

大津法又叫最大类间方差法,是于1979年由日本学者大津展之提出的一种对图像进行二值化的高效算法,是在判别与最小二乘法原理的基础上推导出来的。

算法原理

把直方图在某一阈值处分割为两组,当前分成的两组间方差最大。
假设我们有一张图像,其灰度值为1~m级,灰度值 i 的像素数为 ni
我们可以得到
像素总数

N

=

i

=

0

m

n

i

N=\sum_{i=0}^{m} n_i

N=i=0mni
各灰度级的概率

p

i

=

n

i

N

pi=\frac{n_i}{N}

pi=Nni
然后用阈值T将其分为两组

C

0

=

1

T

C_0=\mid1\backsim T\mid

C0=∣1T

C

1

=

T

+

1

m

C_1=\mid T+1 \backsim m \mid

C1=∣T+1m
我们就可以得到:
C0的概率

w

0

=

w

(

T

)

=

i

=

1

T

p

i

w_0=w(T)=\sum_{i=1}^T p_i

w0=w(T)=i=1Tpi
C1的概率

w

1

=

1

w

0

=

i

=

T

+

1

m

p

i

w_1=1-w_0=\sum_{i=T+1}^m p_i

w1=1w0=i=T+1mpi
C0的平均值

μ

0

=

μ

(

T

)

w

(

T

)

=

i

=

1

T

i

p

i

w

0

\mu_0=\frac{\mu(T)}{w(T)}=\sum_{i=1}^T \frac{i*p_i}{w_0}

μ0=w(T)μ(T)=i=1Tw0ipi
C1的平均值

μ

1

=

μ

μ

(

T

)

1

w

(

T

)

=

i

=

T

+

1

m

i

p

i

w

1

\mu_1=\frac{\mu-\mu(T)}{1-w(T)}=\sum_{i=T+1}^m \frac{i*p_i}{w_1}

μ1=1w(T)μμ(T)=i=T+1mw1ipi

其中

μ

\mu

μ是整个图像的灰度平均值,

μ

=

w

0

μ

0

+

w

1

μ

1

\mu=w_0\mu_0+w_1\mu_1

μ=w0μ0+w1μ1
两组间的方差为:

δ

2

=

w

0

(

μ

0

μ

)

2

+

w

1

(

μ

1

μ

)

2

=

w

0

w

1

(

μ

1

μ

0

)

2

\delta^2=w_0(\mu_0-\mu)^2+w_1(\mu_1-\mu)^2=w_0w_1(\mu_1-\mu_0)^2

δ2=w0(μ0μ)2+w1(μ1μ)2=w0w1(μ1μ0)2

=

[

μ

w

(

T

)

μ

(

T

)

]

2

w

(

T

)

[

1

w

(

T

)

]

= \frac{ [\mu w_(T)-\mu(T)]^2}{w(T)[1-w(T)]}

=w(T)[1w(T)][μw(T)μ(T)]2

实现代码:

import cv2
import numpy as np
import matplotlib.pyplot as plt

gray=cv2.imread('lenaGray.bmp',cv2.IMREAD_GRAYSCALE)
cv2.imshow('gray',gray)

N=gray.size
pro=np.array([0]*256)
for i in range(gray.shape[0]):
    for j in range(gray.shape[1]):
        pro[gray[i,j]]+=1
pro=pro/N

T=0
delta=0
thresh=0
while T<=256:
    w0=pro[0:T].sum()
    w1=pro[T+1:256].sum()
    u0=(pro[0:T]*range(1,T+1)).sum()/w0
    u1=(pro[T:256]*range(T+1,257)).sum()/w1
    u=w0*u0+w1*u1
    v=w0*w1*np.square(u1-u0)
    if v>delta:
        delta=v
        thresh=T
    T+=1

otsu=np.zeros(gray.shape,np.uint8)
for i in range(gray.shape[0]):
    for j in range(gray.shape[1]):
        if gray[i,j]>thresh:
            otsu[i,j]=255

cv2.imshow('Otsu',otsu)
cv2.waitKey(0)
cv2.destroyAllWindows()

效果展示

在这里插入图片描述


版权声明:本文为weixin_44227356原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>