【老文新发】Otsu大津法详解及python实现

news2025/1/21 15:25:56

原文:A Threshold Selection Method from Gray-Level Histograms
A Fast Algorithm for Multilevel Thresholding

前言

大津法包含两个重要的概念:类间方差(between-class variance)类内方差(within-class variance)

两者的详细关系推导可后文。

大津法又称为最大类间方差法是有原因的。因为这个算法的目的就是最大化类间方差,且这个最优阈值一定存在。

大津法作为阈值自动分割的经典算法,其思想很巧妙,值得学习。

大津法推导

在这里插入图片描述
如图所示,右边分割分明,其类间的差异大,区分明显,所以其类间方差更大。

大津法就是要实现这个过程。

我们先做图像的直方图,统计每个很小像素区间包含的像素个数。

即将图像像素值分为 [ 1 , 2 , 3 , …. , L] 个区间。用 n i n_{i} ni 表示各个水平像素值的像素个数,总像素个数与 n i n_{i} ni关系为:
N = n 1 + n 2 + … + n L N=n_1+n_2+\ldots+n_L N=n1+n2++nL
像元个数 n i ni ni 比上总像元数 N 即可得到某个像素区间出现的频率,定义 p i pi pi
p i = n i / N i , p i ≥ 0 , ∑ i = 1 L p i = 1 p_i=n_i / N_i, p_i \geq 0, \sum_{i=1}^L p_i=1 pi=ni/Ni,pi0,i=1Lpi=1
根据原文,是利用一个阈值 k 把图像分为两类 C 0 、 C 1 。 k ∈ [ 1 , 2 , 3 , … . , L ] C0 、C1。k∈[ 1 , 2 , 3 , …. , L] C0C1k[1,2,3,.,L]
我们分别求出这个阈值前后的局部频率之和,定义如下:
C 0 = [ 1 , k ] C 1 = [ k + 1 , L ] w 0 = Pr ⁡ ( C 0 ) = ∑ i = 1 k p i = w ( k ) w 1 = Pr ⁡ ( C 1 ) = ∑ i = k + 1 L p i = 1 − w ( k ) \begin{gathered} C_0=[1, k] \\ C_1=[k+1, L] \\ w_0=\operatorname{Pr}\left(C_0\right)=\sum_{i=1}^k p_i=w(k) \\ w_1=\operatorname{Pr}\left(C_1\right)=\sum_{i=k+1}^L p_i=1-w(k) \end{gathered} C0=[1,k]C1=[k+1,L]w0=Pr(C0)=i=1kpi=w(k)w1=Pr(C1)=i=k+1Lpi=1w(k)
则灰度图像频率直方图的总的数学期望和 C0 、C1的数学期望如下:
u 0 = ∑ i = 1 k i ∗ Pr ⁡ ( i ∣ C 0 ) = ∑ i = 1 k i ∗ p i / w 0 = u ( k ) w ( k ) u 1 = ∑ i = k + 1 L i ∗ Pr ⁡ ( i ∣ C 1 ) = ∑ i = k + 1 L i ∗ p i / w 1 = u T − u ( k ) 1 − w ( k ) u T = u ( L ) = ∑ i = 1 L i ∗ p i \begin{gathered} u_0=\sum_{i=1}^k i * \operatorname{Pr}\left(i \mid C_0\right)=\sum_{i=1}^k i * p_i / w_0=\frac{u(k)}{w(k)} \\ u_1=\sum_{i=k+1}^L i * \operatorname{Pr}\left(i \mid C_1\right)=\sum_{i=k+1}^L i * p_i / w_1=\frac{u_T-u(k)}{1-w(k)} \\ u_T=u(L)=\sum_{i=1}^L i * p_i \end{gathered} u0=i=1kiPr(iC0)=i=1kipi/w0=w(k)u(k)u1=i=k+1LiPr(iC1)=i=k+1Lipi/w1=1w(k)uTu(k)uT=u(L)=i=1Lipi
上式各个变量之间的关系如下:
w 0 u 0 + w 1 u 1 = u T w 0 + w 1 = 1 w_0 u_0+w_1 u_1=u_T \quad w_0+w_1=1 w0u0+w1u1=uTw0+w1=1
期望有了,计算一下对应的方差:
σ 0 2 = ∑ i = 1 k ( i − u 0 ) 2 Pr ⁡ ( i ∣ C 0 ) = ∑ i = 1 k ( i − u 0 ) 2 p i / w 0 σ 1 2 = ∑ i = k + 1 L ( i − u 1 ) 2 Pr ⁡ ( i ∣ C 1 ) = ∑ i = k + 1 L ( i − u 1 ) 2 p i / w 0 σ T 2 = ∑ i = 1 L ( i − u T ) 2 p i \begin{gathered} \sigma_0^2=\sum_{i=1}^k\left(i-u_0\right)^2 \operatorname{Pr}\left(i \mid C_0\right)=\sum_{i=1}^k\left(i-u_0\right)^2 p_i / w_0 \\ \sigma_1^2=\sum_{i=k+1}^L\left(i-u_1\right)^2 \operatorname{Pr}\left(i \mid C_1\right)=\sum_{i=k+1}^L\left(i-u_1\right)^2 p_i / w_0 \\ \sigma_T^2=\sum_{i=1}^L\left(i-u_T\right)^2 p_i \end{gathered} σ02=i=1k(iu0)2Pr(iC0)=i=1k(iu0)2pi/w0σ12=i=k+1L(iu1)2Pr(iC1)=i=k+1L(iu1)2pi/w0σT2=i=1L(iuT)2pi
根据文献:Introduction to statistical pattern recognition,260-267。类内误差、类间误差、总误差有如下关系:
类内误差 σ w 2 = w 0 σ 0 2 + w 1 σ 1 2 类内误差 \sigma_w^2=w_0 \sigma_0^2+w_1 \sigma_1^2 类内误差σw2=w0σ02+w1σ12
类间误差 σ b 2 = w 0 ( u 0 − u T ) 2 + w 1 ( u 1 − u T ) 2 类间误差\sigma_b^2=w_0\left(u_0-u_T\right)^2+w_1\left(u_1-u_T\right)^2 类间误差σb2=w0(u0uT)2+w1(u1uT)2

总误差 σ w 2 + σ b 2 = σ T 2 总误差\sigma_w^2+\sigma_b^2=\sigma_T^2 总误差σw2+σb2=σT2
注意:总误差是与阈值k无关的,但类间误差和类内误差是与阈值k相关的函数
σ b 2 = w 0 ( u 0 − u T ) 2 + w 1 ( u 1 − u T ) 2 = w 0 ( u 0 − ( w 0 u 0 + w 1 u 1 ) ) 2 + w 1 ( u 1 − ( w 0 u 0 + w 1 u 1 ) ) 2 = w 0 w 1 ( u 1 − u 0 ) 2 \begin{gathered} \sigma_b^2=w_0\left(u_0-u_T\right)^2+w_1\left(u_1-u_T\right)^2 \\ =w_0\left(u_0-\left(w_0 u_0+w_1 u_1\right)\right)^2+w_1\left(u_1-\left(w_0 u_0+w_1 u_1\right)\right)^2 \\ =w_0 w_1\left(u_1-u_0\right)^2 \end{gathered} σb2=w0(u0uT)2+w1(u1uT)2=w0(u0(w0u0+w1u1))2+w1(u1(w0u0+w1u1))2=w0w1(u1u0)2
然后再分别把w0,u1,u0带入,可得到:
σ b 2 = [ u T w ( k ) − u ( k ) ] 2 w ( k ) [ 1 − w ( k ) ] \sigma_b^2=\frac{\left[u_T w(k)-u(k)\right]^2}{w(k)[1-w(k)]} σb2=w(k)[1w(k)][uTw(k)u(k)]2

则求解最大类间误差为:
σ b 2 ( k ∗ ) = max ⁡ 1 ≤ k < L σ b 2 ( k ) \sigma_b^2\left(k^*\right)=\max _{1 \leq k<L} \sigma_b^2(k) σb2(k)=1k<Lmaxσb2(k)

由上述 σ b 2 \sigma_b^2 σb2 的分母可以发现, w ( k ) w(k) w(k) 可以取到 1 也可以取到0,因此在边界上 σ b 2 \sigma_b^2 σb2 可以无穷大,而在开基 ( 0 , 1 ) (0,1) (0,1) 则类间方差有限,因此在定义域
S ∗ = k : w 0 w 1 = w ( k ) [ 1 − w ( k ) ] > 0 S^*=k: w_0 w_1=w(k)[1-w(k)]>0 S=k:w0w1=w(k)[1w(k)]>0
因此必定存在一个阈值k使得两类类间方差最大。
以下是python代码实现:

def otsu(gray_img):
    n_count = gray_img.size

    gray_img_array = gray_img.flatten()
    index = np.flatnonzero(gray_img_array)
    gray_img_data = gray_img_array[index]
    
    threshold_t = 0
    max_g = 0
    
    t = np.linspace(start=-1, stop=1, num=256)
    # 遍历每一个灰度层
    for i in range(len(t)):
    	# 使用numpy直接对数组进行运算
        n0 = gray_img_data[np.where(gray_img_data < t[i])]
        n1 = gray_img_data[np.where(gray_img_data >= t[i])]
        w0 = len(n0) / n_count
        w1 = len(n1) / n_count
        u0 = np.mean(n0) if len(n0) > 0 else 0.
        u1 = np.mean(n1) if len(n0) > 0 else 0.
        
        g = w0 * w1 * (u0 - u1) ** 2
        if g > max_g:
            max_g = g
            threshold_t = t[i]
    print('类间方差最大阈值:', threshold_t)
    gray_img[gray_img < threshold_t] = 0
    gray_img[gray_img >= threshold_t] = 1
    return gray_img

这个在opencv中已经有实现,可以直接调用

import cv2
t, otsu = cv2.threshold(img, 0, 255, cv2>THRESH_BINARY + cv2.THRESH_OTSU)

多分类最大类间方差法

根据以上公式类推到多分类的最大类间方差法,假设有 m − 1 \mathrm{m}-1 m1 个阈值 { t 1 , t 2 , … , t M − 1 } \{\mathrm{t} 1, \mathrm{t} 2, \ldots, \mathrm{tM}-1\} {t1,t2,,tM1} 将图像分为 M \mathrm{M} M 类, C 1 C_1 C1 C 2 … C M C_2 \ldots C_M C2CM 。 则存在一组阈值 { t 1 ∗ , t 2 ∗ , … , t M − 1 ∗ } \left\{t 1^*, \mathrm{t} 2^*, \ldots, \mathrm{tM}-1^*\right\} {t1,t2,,tM1} 使得
{ t 1 ∗ , t 2 ∗ , … , t M − 1 ∗ } = Arg ⁡ Max ⁡ { σ B 2 ( t 1 , t 2 , … , t M − 1 ) } , 1 ≤ t 1 < … < t M − 1 < L \begin{aligned} \left\{\mathrm{t}_1 *, \mathrm{t}_2 *, \ldots, \mathrm{t}_{\mathrm{M}-1} *\right\}= & \operatorname{Arg} \operatorname{Max}\left\{\sigma_{\mathrm{B}}{ }^2\left(\mathrm{t}_1, \mathrm{t}_2, \ldots, \mathrm{t}_{\mathrm{M}-1}\right)\right\}, \\ & 1 \leq \mathrm{t}_1<\ldots<\mathrm{t}_{\mathrm{M}-1}<\mathrm{L} \end{aligned} {t1,t2,,tM1}=ArgMax{σB2(t1,t2,,tM1)},1t1<<tM1<L

成立
其中:
σ B 2 = ∑ k = 1 M ω k ( μ k − μ T ) 2 ω k = ∑ i ∈ C k p i , μ k = ∑ i ∈ C k i p i / ω ( k ) . \begin{aligned} \sigma_{\mathrm{B}}{ }^2 & =\sum_{k=1}^{\mathrm{M}} \omega_{\mathrm{k}}\left(\mu_{\mathrm{k}}-\mu_{\mathrm{T}}\right)^2 \\ \omega_{\mathrm{k}} & =\sum_{\mathrm{i} \in \mathrm{Ck}} \mathrm{p}_{\mathrm{i}}, \\ \mu_{\mathrm{k}} & =\sum_{\mathrm{i} \in \mathrm{Ck}} \mathrm{i} \mathrm{p}_{\mathrm{i}} / \omega(\mathrm{k}) . \end{aligned} σB2ωkμk=k=1Mωk(μkμT)2=iCkpi,=iCkipi/ω(k).

因为
∑ k = 1 M ω k = 1 μ T = ∑ k = 1 M ω k μ k . \begin{gathered} \sum_{k=1}^{\mathrm{M}} \omega_{\mathrm{k}}=1 \\ \mu_{\mathrm{T}}=\sum_{k=1}^{\mathrm{M}} \omega_{\mathrm{k}} \mu_{\mathrm{k}} . \end{gathered} k=1Mωk=1μT=k=1Mωkμk.
因此
σ B 2 ( t 1 , t 2 , … , t M − 1 ) = ∑ k = 1 M ω k μ k 2 − μ T 2 \sigma_{\mathrm{B}}{ }^{2}\left(\mathrm{t}_{1}, \mathrm{t}_{2}, \ldots, \mathrm{t}_{\mathrm{M}-1}\right)=\sum_{k=1}^{\mathrm{M}} \omega_{\mathrm{k}} \mu_{\mathrm{k}}^{2}-\mu_{\mathrm{T}}{ }^{2} σB2(t1,t2,,tM1)=k=1Mωkμk2μT2

μ T \mu \mathrm{T} μT 与间值无关,因此求上式的最大值可转为:
{ t 1 ∗ , t 2 ∗ , … , t M − 1 ∗ } = Arg ⁡ Max ⁡ { ( σ B ′ ) 2 { { t 1 , t 2 , … , t M − 1 } } 1 ≤ t 1 < … < t M − 1 < L ( σ B ) 2 = ∑ k = 1 M ω k μ k 2 \begin{array}{c} \left\{\mathrm{t}_{1}^{*}, \mathrm{t}_{2}^{*}, \ldots, \mathrm{t}_{\mathrm{M}-1}^{*}\right\}=\operatorname{Arg} \operatorname{Max}\left\{\left(\sigma_{\mathrm{B}}{ }^{\prime}\right)^{2}\left\{\left\{\mathrm{t}_{1}, \mathrm{t}_{2}, \ldots, \mathrm{t}_{\mathrm{M}-1}\right\}\right\}\right. \\ 1 \leq \mathrm{t}_{1}<\ldots<\mathrm{t}_{\mathrm{M}-1}<\mathrm{L} \\ \left(\sigma_{\mathrm{B}}\right)^{2}=\sum_{k=1}^{\mathrm{M}} \omega_{\mathrm{k}} \mu_{\mathrm{k}}{ }^{2} \end{array} {t1,t2,,tM1}=ArgMax{(σB)2{{t1,t2,,tM1}}1t1<<tM1<L(σB)2=k=1Mωkμk2

类间方差、类内方差和总方差关系

https://blog.csdn.net/qq_42164483/article/details/119064535
https://blog.csdn.net/m0_38024332/article/details/104226806
以上这两篇博文讲的也很详细,内容有所参考,欢迎访问阅读。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1268795.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux地址空间随机化

ASLR(Address Space Layout Randomization)在2005年被引入到Linux的内核 kernel 2.6.12 中&#xff0c;早在2004年就以补丁的形式引入。内存地址的随机化&#xff0c;意味着同一应用多次执行所使用内存空间完全不同&#xff0c;也意味着简单的缓冲区溢出攻击无法达到目的。 1.…

LeetCode(39)赎金信【哈希表】【简单】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 赎金信 1.题目 给你两个字符串&#xff1a;ransomNote 和 magazine &#xff0c;判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以&#xff0c;返回 true &#xff1b;否则返回 false 。 magazine 中的每个字…

深度学习毕设项目 基于生成对抗网络的照片上色动态算法设计与实现 - 深度学习 opencv python

文章目录 1 前言1 课题背景2 GAN(生成对抗网络)2.1 简介2.2 基本原理 3 DeOldify 框架4 First Order Motion Model 1 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩的要求&am…

哈希_快乐数

//编写一个算法来判断一个数 n 是不是快乐数。 // // 「快乐数」 定义为&#xff1a; // // // 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。 // 然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到 1。 // 如果…

智能优化算法应用:基于闪电搜索算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于闪电搜索算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于闪电搜索算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.闪电搜索算法4.实验参数设定5.算法结果6.参考…

vue项目运行时,报错:ValidationError: webpack Dev Server Invalid Options

在运行vue项目中&#xff0c;遇到报错&#xff1a;ValidationError: webpack Dev Server Invalid Options&#xff0c;如下图截图&#xff1a; 主要由于vue.config.js配置文件错误导致的&#xff0c;具体定位到proxy配置代理不能为空&#xff0c;导致运行项目报错&#xff0c;需…

一些好用的12款前端小插件

1. cropper.js Cropper.js 2.0 是一系列用于图像裁剪的 Web 组件。 官网地址&#xff1a;https://fengyuanchen.github.io/cropperjs/v2/zh/ 2. Vditor Vditor是一款浏览器端的 Markdown 编辑器&#xff0c;支持所见即所得、即时渲染&#xff08;类似 Typora&#xff09;和分…

001 基于51单片机的交通灯设计

001 基于51单片机的交通灯设计 东西向绿灯亮若干秒&#xff0c;黄灯闪烁 5 次后红灯亮&#xff0c; 红灯亮后&#xff0c; 南北向由红灯变为绿灯&#xff0c;若干秒后南北向黄灯闪烁 5 此后变红灯&#xff0c;东西向变绿灯&#xff0c;如此重复 准备工作 keilproteus 完成最…

【笔记】windows+pytorch:部署一下stable diffusion和NeRF

之前都是 *nix 环境使用 pytorch&#xff0c;这次尝试了一下windows。 我们来部署下流行性高的stable diffusion和我觉得实用性比stable diffusion高多了的NeRF Stable Diffusion 其实&#xff0c;我也不知道要写啥&#xff0c;都是按照步骤做就好了&#xff0c;后面等有时间…

Java数据结构之《直接插入排序》问题

一、前言&#xff1a; 这是怀化学院的&#xff1a;Java数据结构中的一道难度中等的一道编程题(此方法为博主自己研究&#xff0c;问题基本解决&#xff0c;若有bug欢迎下方评论提出意见&#xff0c;我会第一时间改进代码&#xff0c;谢谢&#xff01;) 后面其他编程题只要我写完…

const 和 constexpr 深入学习

在 C 中&#xff0c;const 和 constexpr 都可以用来修饰对象和函数。修饰对象时&#xff0c;const 表示它是常量&#xff0c;而 constexpr 表示它是一个常量表达式。常量表达式必须在编译时期被计算1。修饰函数时&#xff0c;const 只能用于非静态成员的函数&#xff0c;而 con…

低功耗蓝牙模块在医疗保健领域中的创新应用

医疗保健领域一直在追求更先进的技术&#xff0c;以提高医疗服务的效率和质量。低功耗蓝牙技术的崭新应用为医疗设备的互联性和数据传输提供了可靠的解决方案。本文将深入研究低功耗蓝牙模块在医疗保健领域中的应用&#xff0c;重点关注其在可穿戴设备、远程医疗监测和患者数据…

YOLOv8 代码部署

一、获取代码 YOLOv8官方GitHub网址 https://github.com/ultralytics/ultralytics 获取YOLOv8代码压缩包 二、虚拟环境配置 这个就不写了&#xff0c;装个Anaconda&#xff0c;网上教程很多 三、PyCharm安装与配置&#xff08;可选&#xff09; 这个也不写了&#xff0c;…

springboot实现邮箱发送功能

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 邮箱效果图一、pom配置二、页面编写三、配置yml四、邮件工具类五、测试发送 邮箱效果图 1.可以利用在出现问题进行邮箱提醒 2.编写html 用于在邮箱中展示的样式 提示…

基于yolov2深度学习网络的打电话行为检测系统matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1、YOLOv2网络原理 4.2、基于YOLOv2的打电话行为检测 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 .................................…

MEFLUT: Unsupervised 1D Lookup Tables for Multi-exposure Image Fusion

Abstract 在本文中&#xff0c;我们介绍了一种高质量多重曝光图像融合&#xff08;MEF&#xff09;的新方法。我们表明&#xff0c;曝光的融合权重可以编码到一维查找表&#xff08;LUT&#xff09;中&#xff0c;该表将像素强度值作为输入并产生融合权重作为输出。我们为每次…

后端项目连接数据库-添加MyBatis依赖并检测是否成功

一.在pom.xml添加Mybatis相关依赖 在Spring Boot项目中&#xff0c;编译时会自动加载项目依赖&#xff0c;然后使用依赖包。 需要在根目录下pom.xml文件中添加Mybatis依赖项 <!-- Mybatis整合Spring Boot的依赖项 --> <dependency><groupId>org.mybatis.s…

【数据结构】——堆排序

前言&#xff1a;我们已经学习了堆以及实现了堆&#xff0c;那么我们就来给堆进行排序。我们怎么来进行排序呢&#xff1f;这一次我们就来解决这个问题。 如果我们堆排序要求排序&#xff0c;我们是建立大堆还是小堆呢&#xff0c;如果我们建的小堆的话&#xff0c;那我们在排序…

[PyTorch][chapter 3][李宏毅深度学习-偏差,方差,过拟合,欠拟合]

前言&#xff1a; 这章的目的主要是通过诊断错误的来源,通过错误的来源去优化,挑选模型。 通过本章掌握 过拟合(overfitting)和欠拟合(underfitting)出现原因及解决方案. 目录&#xff1a; 1 概述 2 方差,偏差现象 3 过拟合和欠拟合 4 模型选择 5 概率论回顾 一 概…