1、大津算法OTSU是一種常用的閾值化分割方法,既然是閾值化方法就是需要找到一個閾值,利用這個閾值對圖像中所有的像素點(diǎn)進(jìn)行區(qū)分,哪些像素點(diǎn)屬于前景,哪些像素點(diǎn)屬于背景。
2、如何找到這個閾值呢?OTSU算法中有一個假設(shè),最優(yōu)的閾值是能夠使圖像中的前景和背景之間的差最大的那個值,所以大津算法又名最大類間差算法。
3、我們來定義這個類間差(漢字公式,請見諒 ≥???≤):
類間差 = 前景比重 x 背景比重 x (前景均值 - 背景均值)^2
這個比重其實(shí)就是該類所擁有的像素個數(shù),均值就是該類所擁有的像素的灰度均值。
4、有了類間差公式后,閾值就直接遍歷0~255,不斷的計算類間差值,找到最大的類間差值就可以找到最優(yōu)的閾值了。
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 # 圖像像素點(diǎn)總和
otsuimg=np.zeros((h,w),np.uint8)
threshold_max=threshold=0 # 定義閾值
histogram=np.zeros(256,np.int32) # 初始化各灰度級個數(shù)統(tǒng)計參數(shù)
probability=np.zeros(256,np.float32) # 初始化各灰度級占圖像中的分布的統(tǒng)計參數(shù)
for i in range (h):
for j in range (w):
s=img[i,j]
histogram[s]+=1 # 統(tǒng)計灰度級中每個像素在整幅圖像中的個數(shù)
for k in range (256):
probability[k]=histogram[k]/m # 統(tǒng)計每個灰度級占圖像中的分布
for i in range (255):
w0 = w1 = 0 # 定義前景像素點(diǎn)和背景像素點(diǎn)灰度級占圖像中的分布
fgs = bgs = 0 # 定義前景像素點(diǎn)灰度級總和and背景像素點(diǎn)灰度級總和
for j in range (256):
if j<=i: # 當(dāng)前i為分割閾值
w0+=probability[j] # 前景像素點(diǎn)占整幅圖像的比例累加
fgs+=j*probability[j]
else:
w1+=probability[j] # 背景像素點(diǎn)占整幅圖像的比例累加
bgs+=j*probability[j]
u0=fgs/w0 # 前景像素點(diǎn)的平均灰度
u1=bgs/w1 # 背景像素點(diǎn)的平均灰度
g=w0*w1*(u0-u1)**2 # 類間方差
if g>=threshold_max:
threshold_max=g
threshold=i
print(threshold)
return threshold