1、大津算法OTSU是一种常用的阈值化分割方法,既然是阈值化方法就是需要找到一个阈值,利用这个阈值对图像中所有的像素点进行区分,哪些像素点属于前景,哪些像素点属于背景。
2、如何找到这个阈值呢?OTSU算法中有一个假设,最优的阈值是能够使图像中的前景和背景之间的差最大的那个值,所以大津算法又名最大类间差算法。
3、我们来定义这个类间差(汉字公式,请见谅 ≥???≤):
类间差 = 前景比重 x 背景比重 x (前景均值 - 背景均值)^2
这个比重其实就是该类所拥有的像素个数,均值就是该类所拥有的像素的灰度均值。
4、有了类间差公式后,阈值就直接遍历0~255,不断的计算类间差值,找到最大的类间差值就可以找到最优的阈值了。
python code:
import cv2 as cv
import math
import numpy as np
def otsu_threshold(img):
h=img.shape[0]
w=img.shape[1]
m=h*w # 图像像素点总和
otsuimg=np.zeros((h,w),np.uint8)
threshold_max=threshold=0 # 定义阈值
histogram=np.zeros(256,np.int32) # 初始化各灰度级个数统计参数
probability=np.zeros(256,np.float32) # 初始化各灰度级占图像中的分布的统计参数
for i in range (h):
for j in range (w):
s=img[i,j]
histogram[s]+=1 # 统计灰度级中每个像素在整幅图像中的个数
for k in range (256):
probability[k]=histogram[k]/m # 统计每个灰度级占图像中的分布
for i in range (255):
w0 = w1 = 0 # 定义前景像素点和背景像素点灰度级占图像中的分布
fgs = bgs = 0 # 定义前景像素点灰度级总和and背景像素点灰度级总和
for j in range (256):
if j<=i: # 当前i为分割阈值
w0+=probability[j] # 前景像素点占整幅图像的比例累加
fgs+=j*probability[j]
else:
w1+=probability[j] # 背景像素点占整幅图像的比例累加
bgs+=j*probability[j]
u0=fgs/w0 # 前景像素点的平均灰度
u1=bgs/w1 # 背景像素点的平均灰度
g=w0*w1*(u0-u1)**2 # 类间方差
if g>=threshold_max:
threshold_max=g
threshold=i
print(threshold)
return threshold