大津法图像分割 python手写算法 没用cv2
先记录一下,等写完作业再补充…def OTSU(img):# 类间方差g初始最小g_raw = -1# 要返回的阈值T_return = 0# 获得图像大小M_N = img.shape[0]*img.shape[1]bigest = img.max()# 大津阈值算法for T in range(bigest):# 获取阈值大于T和小于T的两个列表array1 = img[im
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和w1
w0 = len(array0)/M_N # 公式1
w1 = len(array1)/M_N # 公式2
# 算出μ0和μ1 这里需要特判除数为0
if len(array0) == 0:
mu0 = 0
else:
mu0 = sum(array0)/len(array0) # 公式3
if len(array1) == 0:
mu1 = 0
else:
mu1 = sum(array1)/len(array1) # 公式4
# 算出g
g=w0*w1*math.pow((mu0-mu1),2) # 公式6
if g > g_raw:
g_raw = g
T_return = T
return 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

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐
所有评论(0)