Otsu大津算法公式推导及python实现

article/2025/9/16 3:15:59

目录

前言

一、类间平方差是什么?

二、公式推导及实现

1.求类间平方差

2.opencv-python编程实现

2.1 引入图像并灰度化

 2.2 查看灰度值的分布情况

2.3 求全局平均阈值

2.4 求最大类间方差

3.算法的验证

总结


前言

        OTSU(大津算法)是一种用于图像分割过程中,自动计算出一个最佳全局阈值的算法。简单来说就是通过最大类间平方差的方法来区分图像前景及背景。至于其优缺点适用范围网上资源很丰富不再过多赘述。

        然后...还想表达的就是作者是个在读研究生,算是个刚踏入机器视觉领域的新手,写这篇文章的目的一方面是想分享自己的一点想法,请各位大佬提出宝贵意见,另一方面是希望通过这种方式来记录自己的成长...

        最后,在公式推导和编程的过程中参考了两篇文章,原文链接如下:

OTSU算法(大津法—最大类间方差法)原理及实现_小武的博客-CSDN博客

(原理)

https://blog.csdn.net/sinat_29018995/article/details/114175427?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163341713716780262563154%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163341713716780262563154&biz_id=0&utm_medium=distribute.pc_search_result.none-​​​​​​task-blog-2~all~sobaiduend~default-2-114175427.pc_search_ecpm_flag&utm_term=otsu%E9%98%88%E5%80%BC%E5%88%86%E5%89%B2%E7%AE%97%E6%B3%95python&spm=1018.2226.3001.4187

(python代码)


一、类间平方差是什么?

        OTSU算法的核心就是类间平方差,类间平方差的想法非常简单,其实就是将图像的阈值划分为两个区域寻找这两个区域阈值间的最大方差,因为寻找出这两个区域阈值间的最大方差,就代表着这两个部分灰度值的差异最大,那么我们就可以将这个最大方差对应的阈值作为最终阈值将前景于背景区分开来。

二、公式推导及实现

1.求类间平方差

        为了更好的帮助大家理解Otsu算法,作者在这里引入一张图来解释各个参数代表的含义。

         这张图结合Otsu算法理解如下:

        首先假设存在一个阈值TH将整幅图(灰度值为0~255)分为了两个部分,第一部分是小于假定阈值TH的那部分。其中,这一部分的平均灰度值为m1,而这一部分在整幅图中出现的概率为P1。第二部分就是大于假定阈值TH的那部分。同理,这部分的平均灰度值为m2,出现的概率为P2。而M则是全局的平均阈值。(这幅图是为了理解而画,真实情况可能并非如此,要具体情况具体分析。)

        那么我们可以尝试去列一下上述参数的公式。首先是m1,m1可以想象为从0到假定阈值TH处每个灰度值与该灰度值出现的频率(或者频数)的乘积再除以该区域的总频率,就是它的平均阈值。可以这样写:

m1 = \frac{1}{p_{1}}\sum_{i=0}^{k}p_{i}i                                                               (1)

        其中:

                k——假定阈值TH

                i——灰度值

                p_{i}——每个灰度值出现的频率

                p_{1}——0~k区域每个灰度值出现概率的总和

        同理m2可以写成:

                                                             (2)

         其中:

                L:图像的像素级,通常都是255

                p2: k+1~L区域每个灰度值出现概率的总和

        上述公式提到的也可以根据其含义列出表达式:

                                                                      (3)

                                                                  (4)

        那么全局的平均阈值可以写为:

  

​                                                                 (5)

        且有:

                                                                    (6)

       根据类间方差的概念列出类间方差表达式:

                                            (7)

       类间方差公式列出后,想要表达的内容就很清楚了,只要求出类间方差的最大值,就代表此时最大值对应的灰度值就是两个区域灰度值差异最大的那个值,并将这个值作为阈值。

        那么我们接下来要做的就是如何编程去实现这一过程。

2.opencv-python编程实现

        在介绍编程实现过程中,为大家逐步展示思路和编程,最后会统一列出供大家参考。

2.1 引入图像并灰度化

        这一步就是常规的引入图片,并转为灰度图。

import cv2
import cv2 as cv
import numpy as np
#coding:utf-8img = cv.imread("C:/C1.jpg")
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)

 2.2 查看灰度值的分布情况

        Opencv-python中有个Api是查看灰度直方图分布的,我们可以直接调用:

hist,bins  = np.histogram(gray.ravel(),bins = 255,density=True)

        hist:当density = True时是输出的灰度值出现的频率。

        bins:bins = 255就是将输入的数据划分为255个区域,即256个数,对应着0~255灰度值空间。

        此时我们需要观察这个灰度值的划分情况。

print("hist:",hist.shape)
print("hist:",hist)
print("bins",bins.shape)
print("bins",bins)

        在这里,通过上述的代码查看一下hist和bins的大小及类型。

 (输出数据局部图)

        通过查看bins的数据类型,作者意识到输入的图像不存在灰度值为0的地方,所以导致灰度分布是从1~255的,并且bins和hist的对应关系解读为:灰度值为1~1.99的概率为3,41011212e-05。所以如果我接下来想用hist中的频率与0~255灰度值做乘积算均值是不现实的。那么需要写一段代码,创建一个数组让灰度值为不从0开始,而取1~1.99的中间值1.5~255来确保准确性。

g = []
for i in range(1,256):p = (i + i +1)/2if i == 255:p = 255g.append(p)
g = np.array(g)

2.3 求全局平均阈值

        由公式(5)可以写出全局平均阈值的代码:

M = np.sum(np.dot(hist, g))

2.4 求最大类间方差

        求出了全局平均阈值,至于要在求出m1,m2,p1,p2就可以解决问题了。那么m1,m2我们根据公式(1)、(2)的思路去写。首先要做一个循环,因为我们只是假设存在一个阈值,但并不知道这个阈值具体是多少,但是我们知道他肯定存在于0~255之间,所以m1这个区域就在0~n中,同理m2这个区域就在n~255中,具体见代码。这样计算后将其代入公式(7)中,通过一个判断语句找出最大类间方差值,此时这个最大类间方差值对应的n就是我们要找的阈值。

max =0
for n in range(0,256):m1 = np.sum(np.dot(hist[0:n],g[0:n]))/np.sum(hist[0:n])m2 = np.sum(np.dot(hist[n:256], g[n:256]))/np.sum(hist[n:256])score = sum(hist[0:n])*((m1 - MG))**2 + sum(hist[n:256])*((m2 - MG))**2if max < score:max = scorethreshold = n
print("OTSU",threshold)

3.算法的验证

import cv2
import cv2 as cv
import numpy as np
#coding:utf-8img = cv.imread("C:/C1.jpg")
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
hist,bins  = np.histogram(gray.ravel(),bins = 255,density=True)#输出0~255灰度等级分布概率
#查看hist长度
print("hist:",hist.shape)
print("hist:",hist)
print("bins",bins.shape)
print("bins",bins)
#创建像素级数组
g = []
for i in range(1,256):p = (i + i +1)/2if i == 255:p = 255g.append(p)
g = np.array(g)
print("g",g.shape)
print("g:",g)
#全局平均阈值 这里除pi没有意义 因为全局总pi=1
M = np.sum(np.dot(hist, g))
print("MG:",MG)
max =0
for n in range(0,256):m1 = np.sum(np.dot(hist[0:n],g[0:n]))/np.sum(hist[0:n])m2 = np.sum(np.dot(hist[n:256], g[n:256]))/np.sum(hist[n:256])score = sum(hist[0:n])*((m1 - MG))**2 + sum(hist[n:256])*((m2 - MG))**2if max < score:max = scorethreshold = n
print("OTSU",threshold)
#调用大津算法
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
print("threshold value %s" % ret) 
cv.imshow("threshold", binary) #显示二值化图像
#调用阈值实验
ret ,result = cv.threshold(gray,threshold,255,cv.THRESH_BINARY)
cv.imshow("result",result)
print("threshold", result)
cv.imshow("orignal", img)
cv2.waitKey()

        由于图像是参与项目当中的图像不便展示,给大家看看最后我写的代码的阈值和调用Otsu二值的阈值对比吧。 

        其中,OTSU是调用API计算的结果,threshold value是自己写的代码计算的结果,总体来讲问题不大。 


总结

        这是我第一尝试研究算法,虽然大津算法很简单,但奈何作者资质平庸仍花了很久时间才完成公式的纸质推导与opencv-python的编程实现,期间也看到了很多优质的文章,日后也会继续努力去学习。总体来说,虽然研究的这个算法意义不大,但是也改变了我以前一看公式就头疼的毛病,这次的成功也提高了以后研究算法的信心,起码认真钻研就会有所回报。加油吧

        最后的最后,希望各位大佬能够给予批评指正,学生一定认真听从改正!


http://chatgpt.dhexx.cn/article/x57jx0Mu.shtml

相关文章

OTSU算法原理

OTSU算法原理及实现&#xff1a; 最大类间方差是由日本学者大津(Nobuyuki Otsu)于1979年提出&#xff0c;是一种自适应的阈值确定方法。算法假设图像像素能够根据阈值&#xff0c;被分成背景[background]和目标[objects]两部分。然后&#xff0c;计算该最佳阈值来区分这两类像素…

大津阈值分割算法(OTSU处理图像)

1.算法原理简述 对于图像I(x,y)&#xff0c;前景(即目标)和背景的分割阈值记作T&#xff0c;属于前景的像素点数占整幅图像的比例记为ω0&#xff0c;其平均灰度μ0&#xff1b;背景像素点数占整幅图像的比例为ω1&#xff0c;其平均灰度为μ1。图像的总平均灰度记为μ&#xf…

[图像处理]14.分割算法比较 OTSU算法+自适应阈值算法+分水岭

参考文献&#xff1a; OTSU阈值分割孔洞填充海陆分离_SwordKii的博客-CSDN博客 drawContours函数_普通网友的博客-CSDN博客_drawcontours R329-opencv阈值分割算法——自适应阈值_Third Impact的博客-CSDN博客_opencv自适应阈值分割 分水岭算法的python实现及解析_进不去的…

OTSU算法 (大津算法)理解代码

OTSU算法&#xff1a;对图像进行二值化的算法 介绍 OTSU算法是一种自适应的阈值确定的方法&#xff0c;又称大津阈值分割法&#xff0c;是最小二乘法意义下的最优分割。 它是按图像的灰度特性&#xff0c;将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景…

Pr-快速上手-基本操作-教程

视频链接: Pr教程 视频设计到的知识点: 视频的剪辑bgm的管理添加字幕及弹幕的添加鬼畜视频的制作发布教程

Pr常用操作技巧

操作技巧持续更新中 1.premiere如何裁剪视频尺寸 视频尺寸怎么修改 1.将premiere左下角的视频素材直接向右拖动到编辑区中 2.鼠标左键单击视频,然后选择上方的【效果】 3.这时,页面左侧将弹出效果的菜单栏,依次选择效果→视频效果→变换→裁剪 4.鼠标左键按住【裁剪】不放,直接…

Premiere: 基本操作

1、首先进入编辑模式&#xff0c;使得视频能加效果 2、这时候能找到视频的效果添加&#xff0c;这里有视频的水平翻转&#xff0c;高斯模糊等&#xff0c;需要什么效果直接&#xff0c;把该效果抓到视频上就可以。

PR的入门基础教程

提示&#xff1a;这里只记述作者学习PR入门基础教程视频后的总结 文章目录 常用视频概念第1天学习总结第2天学习总结第3天学习总结 常用视频概念 第1天学习总结 第2天学习总结 第3天学习总结

Adobe Premiere Pro快速入门教程

简介&#xff1a; 适用于纯新手零基础&#xff0c;看完本教程即可完成常用视频编辑技巧。 采用Adobe Premiere Pro 2020版本 windows10操作系统 一、制作 照片音频字幕的视频 目标&#xff1a;把三张图片和一个音乐做成带字幕的视频。&#xff08;素材请自行准备&#xff0…

使用pr的8大技巧

许多小伙伴是通过pr这个软件进行素材剪辑的&#xff0c;当我们面对许多素材需要剪辑的时候&#xff0c;往往被这些素材弄得头昏脑涨&#xff0c;剪辑拼接的费时费力&#xff0c;最后出来的成品效果也不太好&#xff0c;下面就告诉大家一些pr使用的技巧&#xff0c;来提升我们的…

Premiere 零基础快速上手教程

关注并星标“高级农民工” 回复“视频”可获取视频剪辑软件和教程 在前几天的文章中&#xff0c;我分享了几款主流视频剪辑软件&#xff1a; 最主流的视频剪辑软件 简单来说就是&#xff0c;手机端用「剪映」这一款 app 就够&#xff0c;当你熟练到发现手机剪视频不方便&#x…

pr基础学习笔记

pr基础学习笔记&#xff08;正题&#xff09; 推荐几个小技巧 1.快速插入 2.快速移动小片段 2. 另&#xff1a;移动Ctrl是多轨移动移动CtrlAlt是单轨移动3.如何去除两个片段之间的空档&#xff1f; 4.两种选择工具的比较 附&#xff1a; pr快捷键 应用程序 选择工具…

pr基础入门

一、快速认识 PR 主界面并导入素材 修改 名称、位置&#xff0c;其他不用变&#xff0c;点击确定 进入界面如下&#xff1a; 认识、添加必要 窗口 导入素材方法 1.直接将文件拖入pr中 2.导入媒体以开始&#xff0c;部分右键创建 素材箱 进入素材箱&#xff0c;右键选择导入&a…

PR(基础剪辑)

一.剪辑步骤&#xff1a; 1.先粗剪后精剪&#xff1a; 粗剪&#xff1a; 精剪&#xff1a; 二. 常用键&#xff1a; 1. i&#xff1a;设置素材的起点 o&#xff1a;设置素材的终点 &#xff08;在预览素材时&#xff09; 2.快速浏览素材&#xff1a; l&#xff1a;按一次常速…

Pr 入门系列之十:基本图形

在 Pr 中&#xff0c;文字&#xff08;包括字幕&#xff09;以及形状等被归类为图形 Graphics。 一个图形剪辑里可包含多个文本图层、形状图层以及其它媒体文件等图形元素。 提示&#xff1a; 1、图形剪辑不会出现在项目面板中&#xff0c;除非升级为源图。 2、与 Ps 一样&…

PR(Adobe Premiere Pro)软件基础知识

一、基础参数设置 时长 时长为视频时间的长度。基本单位为秒。但是在PR软件中&#xff0c;有更为精准的时间单位计算为帧&#xff0c;也就是把1秒分为若干份&#xff0c;一份就是一帧&#xff0c;一帧也就可以理解为一张图片。所以在PR软件中视频显示的时间长度表述为 时&…

Premiere基础操作

一&#xff1a;设置缓存 二&#xff1a;ctrI导入素材 三&#xff1a;导入图像序列 四&#xff1a;打开吸附。 打开吸附后素材会对齐。 五&#xff1a;按~键可以全屏窗口。 六&#xff1a;向前选择轨道工具。 在时间线上点击&#xff0c;向前选中时间线上素材。向后选择轨道工具…

pr剪视频基本操作

1 打开pr 2 导入设置 1&#xff09;双击左下角“项目”窗口&#xff0c;导入准备好的视频 2&#xff09;建立一个序列 点击文件 -> 新建 -> 序列 设置自定义序列 3 修建编辑 1&#xff09;双击视频素材&#xff0c;在预览框&#xff08;源&#xff09;中可以点击播放或…

【PR】零基础快速入门教程

【PR】零基础快速入门教程 PR&#xff08;Premiere&#xff09;能做什么&#xff1f;PR欢迎界面及新建项目工作区及窗口说明导入文件建立序列视频剪辑添加字幕导出视频 使用软件&#xff1a;Premiere2020 新年卷起来&#xff0c;写文章已近不能满足与我了&#xff0c;我要向着更…

PR基础知识

什么是帧&#xff0c;什么叫帧速率&#xff0c;什么叫方形像素&#xff0c;什么叫场序…… 1、时长 时长为视频时间的长度&#xff0c;基本单位为秒。但是在PR软件中&#xff0c;有更为精准的时间单位计算为帧&#xff0c;也就是把1秒分为若干份&#xff0c;一份就是一帧&…