图像分割——大津法(Otsu)

大津法是一种基于最大类间方差的图像二值化算法,由大津展之在1979年提出。该算法通过寻找最优阈值将图像分割为两个部分,使得两部分之间的方差达到最大。文章涵盖了算法原理、实现代码及效果展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大津法又叫最大类间方差法,是于1979年由日本学者大津展之提出的一种对图像进行二值化的高效算法,是在判别与最小二乘法原理的基础上推导出来的。

算法原理

把直方图在某一阈值处分割为两组,当前分成的两组间方差最大。
假设我们有一张图像,其灰度值为1~m级,灰度值 i 的像素数为 ni
我们可以得到
像素总数 N = ∑ i = 0 m n i N=\sum_{i=0}^{m} n_i N=i=0mni
各灰度级的概率 p i = n i N pi=\frac{n_i}{N} pi=Nni
然后用阈值T将其分为两组 C 0 = ∣ 1 ∽ T ∣ C_0=\mid1\backsim T\mid C0=1T C 1 = ∣ T + 1 ∽ m ∣ C_1=\mid T+1 \backsim m \mid C1=T+1m
我们就可以得到:
C0的概率 w 0 = w ( T ) = ∑ i = 1 T p i w_0=w(T)=\sum_{i=1}^T p_i w0=w(T)=i=1Tpi
C1的概率 w 1 = 1 − w 0 = ∑ i = T + 1 m p i w_1=1-w_0=\sum_{i=T+1}^m p_i w1=1w0=i=T+1mpi
C0的平均值 μ 0 = μ ( T ) w ( T ) = ∑ i = 1 T i ∗ p i w 0 \mu_0=\frac{\mu(T)}{w(T)}=\sum_{i=1}^T \frac{i*p_i}{w_0} μ0=w(T)μ(T)=i=1Tw0ipi
C1的平均值 μ 1 = μ − μ ( T ) 1 − w ( T ) = ∑ i = T + 1 m i ∗ p i w 1 \mu_1=\frac{\mu-\mu(T)}{1-w(T)}=\sum_{i=T+1}^m \frac{i*p_i}{w_1} μ1=1w(T)μμ(T)=i=T+1mw1ipi

其中 μ \mu μ是整个图像的灰度平均值, μ = w 0 μ 0 + w 1 μ 1 \mu=w_0\mu_0+w_1\mu_1 μ=w0μ0+w1μ1
两组间的方差为:
δ 2 = w 0 ( μ 0 − μ ) 2 + w 1 ( μ 1 − μ ) 2 = w 0 w 1 ( μ 1 − μ 0 ) 2 \delta^2=w_0(\mu_0-\mu)^2+w_1(\mu_1-\mu)^2=w_0w_1(\mu_1-\mu_0)^2 δ2=w0(μ0μ)2+w1(μ1μ)2=w0w1(μ1μ0)2
= [ μ w ( T ) − μ ( T ) ] 2 w ( T ) [ 1 − w ( T ) ] = \frac{ [\mu w_(T)-\mu(T)]^2}{w(T)[1-w(T)]} =w(T)[1w(T)][μw(T)μ(T)]2

实现代码:
import cv2
import numpy as np
import matplotlib.pyplot as plt

gray=cv2.imread('lenaGray.bmp',cv2.IMREAD_GRAYSCALE)
cv2.imshow('gray',gray)

N=gray.size
pro=np.array([0]*256)
for i in range(gray.shape[0]):
    for j in range(gray.shape[1]):
        pro[gray[i,j]]+=1
pro=pro/N

T=0
delta=0
thresh=0
while T<=256:
    w0=pro[0:T].sum()
    w1=pro[T+1:256].sum()
    u0=(pro[0:T]*range(1,T+1)).sum()/w0
    u1=(pro[T:256]*range(T+1,257)).sum()/w1
    u=w0*u0+w1*u1
    v=w0*w1*np.square(u1-u0)
    if v>delta:
        delta=v
        thresh=T
    T+=1

otsu=np.zeros(gray.shape,np.uint8)
for i in range(gray.shape[0]):
    for j in range(gray.shape[1]):
        if gray[i,j]>thresh:
            otsu[i,j]=255

cv2.imshow('Otsu',otsu)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果展示

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想上天的狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值