二值化是什么?就是把一幅图像的所有像素点统一成两个值,例如图像的像素值只包含0和1,或者只包含0和255
一般情况:手动二值化
要二值化,首先我们手动定义一个阈值T,
这个T把小于T的和大于T的像素值就分开了,小于等于T的值都置0,大于T的置为255吧,这样图像就“非黑即白”了
#手动定义阈值
th=128
img[img < th] = 0
img[img >= th] = 255
大津二值化算法:自动定义阈值
大津二值化算法也称作最大类间方差法,是日本学者大津于1979年提出的,最大类间方差法呢我们好理解一点,我们需要一个最佳的T值去把一幅图像分为两类,这两个类之间的方差最大,说明他们的相关性越低,差别越大
具体的原理:
一幅M*N大小的灰度图像被T分为两类,
第一类像素个数占总像素个数的比值:
w
0
w0
w0
第二类像素个数占总像素个数的比值:
w
1
=
1
−
w
0
w1=1-w0
w1=1−w0
第一类平均像素值:
u
0
u0
u0
第二类平均像素值:
u
1
u1
u1
图像总平均值:
u
=
w
0
∗
u
0
+
w
1
∗
u
1
u=w0*u0+w1*u1
u=w0∗u0+w1∗u1
类间方差= w 0 ∗ ( u 0 − u ) 2 + w 1 ∗ ( u 1 − u ) 2 w0*(u0-u)^{2}+w1*(u1-u)^{2} w0∗(u0−u)2+w1∗(u1−u)2
把
u
=
w
0
∗
u
0
+
w
1
∗
u
1
u=w0*u0+w1*u1
u=w0∗u0+w1∗u1带进去,整理得到:
类间方差=
w
0
∗
w
1
∗
(
u
0
−
u
1
)
2
w0* w1*(u_{0}-u_{1})^{2}
w0∗w1∗(u0−u1)2
我们遍历T(0~255),记录下得到类间方差最大的T值,这样就可以把图像二值化了,
python+opencv的大津调用函数:
ret2,th2=cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
或者自己写
def binatization_Ostu(img):
H,W=img.shape
max_t=0
sigma_t=0
for _t in range(0,255):
v0 = img[np.where(img < _t)]
u0 = np.mean(v0) if len(v0) > 0 else 0. #类1的像素平均值
w0 = len(v0) / (H * W) #占总像素个数比例
v1 = img[np.where(img >= _t)]
u1 = np.mean(v1) if len(v1) > 0 else 0.
w1 = 1-w0
variance= w0 * w1 * ((u0 - u1) ** 2)
if sigma>sigma_t:
max_t=_t
sigma_t=sigma
#Binarization
th=max_t
img[img<th]=0
img[img>=th]=255
return img
这种算法在直方图单峰条件下效果比较好,具体的应用后面在学习