文章目录
- 1. 基本概念
- 2. 公式
- 2.1 后景像素比w0
- 2.2 前景像素比w1
- 2.3 后景平均灰度u0
- 2.4 前景平均灰度u1
- 2.5 公式汇合
- 3. 代码
1. 基本概念
用大津法最终会得到一个阈值,使用该阈值将图像进行二值化。大于这个阈值的,像素值变成1;小于阈值的,像素值变成0。 原本图像的像素范围是从0~255,大津法的思想很简单,就是遍历这256个阈值,对每个阈值,都进行一次二值化。最终看哪个阈值下二值化的结果最合适。接下来就介绍遍历的公式。
2. 公式
这里我将像素值为1的称作前景,像素值为0的称作后景。
大津法的最终公式为很多小的计算拼起来的,如下
2.1 后景像素比w0
ω 0 = 后景像素数量 图像宽 ∗ 图像高 (1) \omega_0= \frac{后景像素数量}{图像宽 *图像高}\tag{1} ω0=图像宽∗图像高后景像素数量(1)
2.2 前景像素比w1
ω 1 = 前景像素数量 图像宽 ∗ 图像高 (2) \omega_1= \frac{前景像素数量}{图像宽 *图像高}\tag{2} ω1=图像宽∗图像高前景像素数量(2)
2.3 后景平均灰度u0
μ 0 = ∑ a l l 后景像素的值 后景像素数量 (3) \mu_0 =\frac{ \sum_{all}后景像素的值}{后景像素数量}\tag{3} μ0=后景像素数量∑all后景像素的值(3)
2.4 前景平均灰度u1
μ 1 = ∑ a l l 前景像素的值 前景像素数量 (4) \mu_1 =\frac{ \sum_{all}前景像素的值}{前景像素数量}\tag{4} μ1=前景像素数量∑all前景像素的值(4)
2.5 公式汇合
根据式1~4,可以得到(5)
μ = ω 0 ∗ μ 0 + ω 1 ∗ μ 1 、 (5) \mu = \omega_0*\mu_0 + \omega_1*\mu_1 、\tag{5} μ=ω0∗μ0+ω1∗μ1、(5)
其中 μ \mu μ是图像的平均灰度
而大津法的公式为
g = ω 0 ∗ ( μ 0 − μ ) 2 + ω 1 ∗ ( μ 1 − μ ) 2 (6) g = \omega_0*(\mu_0-\mu)^2 + \omega_1*(\mu_1-\mu)^2 \tag{6} g=ω0∗(μ0−μ)2+ω1∗(μ1−μ)2(6)
将(5)带(6),可以得到(7)
g = ω 0 ω 1 ( μ 0 − μ 1 ) 2 (7) g = \omega_0\omega_1(\mu_0-\mu_1)^2 \tag{7} g=ω0ω1(μ0−μ1)2(7)
3. 代码
代码部分中,上述的公式都会体现出来。已经被注释所标注。
import numpy as np
import math'''
Summary:大津阈值分割
Paramaters:img - 输入的灰度图像 是二维矩阵
'''
def OTSU(img):# 类间方差g初始最小g_raw = -1# 要返回的阈值T_return = 0# 获得图像大小M_N = img.shape[0]*img.shape[1]# 大津阈值算法for T in range(256):# 获取阈值大于T和小于T的两个列表array0 = img[img<T] array1 = img[img>T]# 算出w0和w1w0 = len(array0)/M_N # 公式1w1 = len(array1)/M_N # 公式2# 算出μ0和μ1 这里需要特判除数为0if len(array0) == 0:mu0 = 0else:mu0 = sum(array0)/len(array0) # 公式3if len(array1) == 0:mu1 = 0else:mu1 = sum(array1)/len(array1) # 公式4# 算出gg=w0*w1*math.pow((mu0-mu1),2) # 公式6if g > g_raw:g_raw = gT_return = Treturn T_return
使用该图进行测试,效果如下所示
import cv2# 读取图片
img = Image.open('2.png')
# 转换成灰度图
img=img.convert('L')
# 转换成array
arr = np.array(img)
# # 获得最佳域值分割
T = OTSU(arr)
print(T)
# 根据阈值进行二值分割
arr[arr>T] = 255
arr[arr<T] = 0
# 展示分割结果
pil_image=Image.fromarray(arr)
pil_image