Otsu算法——基于类间方差最大化的自动阈值选择方法

Otsu algorithm

大津法是由日本学者大津展之(Nobuyuki Otsu)于1979年提出的,一种基于类间方差最大化的自动阈值选择方法。

一、核心原理

其基本思想是将图像分为前景和背景两部分,通过寻找一个阈值,使得这两部分的类间方差最大。类间方差越大,说明两部分之间的差异越大,分割效果越好。这种方法在图像直方图呈现双峰时效果最好,因为此时前景和背景的像素分布较为明显。

二、计算步骤

Otsu 是一种基于类间方差最大化的自动阈值选择方法,步骤如下:

  1. 计算直方图:统计图像中每个灰度级的像素数量。

  2. 遍历阈值:尝试所有可能的阈值 t(0 到 255)。

  3. 计算类间方差:将图像分为前景(灰度 ≤ t)和背景(灰度 > t),计算两者的类间方差:
    σ 2 = ω 0 ω 1 ( μ 0 − μ 1 ) 2 \sigma^2 = \omega_0\omega_1{(\mu_0 - \mu_1)}^2 σ2=ω0ω1(μ0μ1)2
    其中 ω0,ω1 为前景/背景像素数占图像总像素数比例,μ0,μ1 为前景/背景像素平均灰度。

    • 全局平均灰度
      平均灰度是所有像素值的算术平均值。
      μ 全局 = 1 N ∑ i = 0 255 i × h ( i ) \mu_{全局} = \frac{1}{N}\sum_{i=0}^{255}i×h(i) μ全局=N1i=0255i×h(i)
      N:图像总像素数。
      h(i):灰度级 i 的像素数。

    • 前景平均灰度(像素值 ≤ t)
      μ 0 = 1 N 0 ∑ i = 0 t i × h ( i ) \mu_0 = \frac{1}{N_0}\sum_{i=0}^{t}i×h(i) μ0=N01i=0ti×h(i)
      N 0 = ∑ i = 0 t h ( i ) N_0 = \sum_{i=0}^{t}h(i) N0=i=0th(i):前景像素总数。

    • 背景平均灰度(像素值 > t)
      μ 1 = 1 N 1 ∑ i = t + 1 255 i × h ( i ) \mu_1 = \frac{1}{N_1}\sum_{i=t+1}^{255}i×h(i) μ1=N11i=t+1255i×h(i)
      N 1 = ∑ i = t + 1 255 h ( i ) N_1 = \sum_{i=t+1}^{255}h(i) N1=i=t+1255h(i):背景像素总数。

  4. 选择最佳阈值:使类间方差最大的 t 即为最佳阈值。

三、 适用场景与限制

  • 适用场景:图像直方图呈现双峰分布(前景和背景对比明显)。

  • 优势:无需手动设定阈值,自适应性强;时间复杂度为 O(L)(L 为灰度级数,通常为256),适用于实时处理。

  • 限制:对噪声敏感,图像噪声会破坏直方图的双峰特性,导致阈值偏移;光照不均时效果差,需配合预处理(如 CLAHE)或使用自适应阈值(如 cv2.adaptiveThreshold)提升效果。

四、OpenCV中的函数

retval, dst = cv2.threshold(
    src,      # 输入图像(必须为灰度图)
    thresh,   # 手动设定阈值(当使用 Otsu 时此值被忽略)
    maxval,   # 超过阈值后赋予的像素值
    cv2.THRESH_BINARY + cv2.THRESH_OTSU      # 阈值化类型(决定如何处理像素值)
)
  • 返回值
  1. retval
    • 由 Otsu 算法自动计算出的最佳阈值(类型为 float
  2. dst
    • 阈值化后的二值图像(与输入同尺寸,像素值为 0 或 255)
  • cv2.THRESH_BINARY + cv2.THRESH_OTSU

    1. cv2.THRESH_BINARY 的作用
      • 定义二值化的基本规则:像素值= { 255 i f 像素 > 阈值 0 o t h e r w i s e \begin{cases} 255 & if\quad像素>阈值 \\ 0 & otherwise \end{cases} {2550if像素>阈值otherwise
      • 单独使用时会要求手动指定阈值(例如 thresh=127)。
    2. cv2.THRESH_OTSU 的作用
      • 自动计算图像的最佳阈值(基于最大化类间方差),但本身不定义如何应用阈值。
      • 必须与基础阈值类型(如 BINARY)组合使用,才能完成完整的二值化操作。
    3. 组合的底层逻辑——OpenCV 的标志位设计
      • 阈值类型被编码为位掩码(bitmask),例如:
        • cv2.THRESH_BINARY = 0(二进制 0000
        • cv2.THRESH_OTSU = 8(二进制 1000
      • 使用 +| 组合这些标志,OpenCV 可解析为同时启用两种行为。

五、示例

  • 原图
    在这里插入图片描述

  • 代码

    import cv2
    import matplotlib.pyplot as plt
    
    # 读取彩色图像并转换为灰度图
    img = cv2.imread('tree.png')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    # 应用Otsu阈值分割
    threshold, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    
    # 创建画布和子图布局
    plt.figure(figsize=(15, 6))
    
    # 绘制灰度直方图
    plt.subplot(1, 2, 1)
    plt.hist(gray.ravel(), bins=256, range=(0, 256), color='gray', alpha=0.7)
    plt.axvline(x=threshold, color='red', linestyle='--', linewidth=2,
                label=f'Threshold = {int(threshold)}')
    plt.title('Grayscale Histogram with Otsu Threshold')
    plt.xlabel('Pixel Intensity')
    plt.ylabel('Frequency')
    plt.legend()
    
    # 绘制二值化图像
    plt.subplot(1, 2, 2)
    plt.imshow(binary, cmap='gray')
    plt.title('Binary Image after Otsu Thresholding')
    plt.axis('off')
    
    # 显示结果
    plt.tight_layout()
    plt.show()
    
  • 效果图
    在这里插入图片描述

我是终须有梦,如有错误,欢迎指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值