大津法(Otsu)是图像处理领域里面较为重要的阈值分割方法,适用于处理双峰图像。但大多数开发人员并不熟悉其原理,因此有必要对其进行详细说明与分析。

opnecv的实例代码链接为:
opencv-python大津法(Otsu)官方说明文档
python代码为:

img = cv2.imread('road.jpg',0)
blur = cv2.GaussianBlur(img,(5,5),0)
# find normalized_histogram, and its cumulative distribution function
hist = cv2.calcHist([blur],[0],None,[256],[0,256])
hist_norm = hist.ravel()/hist.max()
Q = hist_norm.cumsum()
bins = np.arange(256)
print(bins)
fn_min = np.inf
thresh = -1
for i in range(1,256):p1,p2 = np.hsplit(hist_norm,[i]) # probabilitiesq1,q2 = Q[i],Q[255]-Q[i] # cum sum of classesb1,b2 = np.hsplit(bins,[i]) # weights# finding means and variancesm1,m2 = np.sum(p1*b1)/q1, np.sum(p2*b2)/q2v1,v2 = np.sum(((b1-m1)**2)*p1)/q1,np.sum(((b2-m2)**2)*p2)/q2# calculates the minimization functionfn = v1*q1 + v2*q2if fn < fn_min:fn_min = fnthresh = i
# find otsu's threshold value with OpenCV function
ret, otsu = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
print (thresh,ret)

下面对关键代码进行分析:

blur = cv2.GaussianBlur(img,(5,5),0)

用高斯滤波器对图像进行模糊操作,高斯核大小为5✖️5,参考说明,得到模糊后的图像变量blur。

hist = cv2.calcHist([blur],[0],None,[256],[0,256])

这句代码得到了blur图像的灰度直方图,函数calcHist定义可参考说明,得到了代表blur图像灰度分布的对象hist,hist为256行1列的数组,数据类型为numpy.ndarray,每个元素为该位置对应灰度值所对应的像素数,部分灰度值对应的像素数如下图所示:

hist_norm = hist.ravel()/hist.max()
Q = hist_norm.cumsum()

hist_norm代表由每个灰度对应像素数量与某个最大像素数比值构成的数组,shape为[256,1](由于hist.ravel()),新数组Q中的每个元素表示hist_norm中每个元素与前所有元素的累加和。假设图像被阈值TTT所分割,在灰度值小于TTT的区间内(灰度直方图左侧),将灰度值为iii的像素个数定义为P(i)P(i)P(i),在一张图像里的256个灰度值中,像素个数最大的灰度值定义为PmP_mPm​;同理在灰度直方图右侧,分别定义为Q(i),QmQ(i),Q_mQ(i),Qm​。令:p(i)=P(i)/Pmp(i)=P(i)/P_mp(i)=P(i)/Pm​q(i)=Q(i)/Qmq(i)=Q(i)/Q_mq(i)=Q(i)/Qm​
定义:s1=∑i=0Tp(i)s_1=\sum_{i=0}^{T}p(i)s1​=i=0∑T​p(i)s2=∑i=T255q(i)s_2=\sum_{i=T}^{255}q(i)s2​=i=T∑255​q(i)定义平均值:m1=∑i=0i(i∗p(i))/s1m_1=\sum_{i=0}^i(i*p(i))/s_1m1​=i=0∑i​(i∗p(i))/s1​m2=∑i=T255(i∗q(i))/s2m_2=\sum_{i=T}^{255}(i*q(i))/s_2m2​=i=T∑255​(i∗q(i))/s2​定义方差:v1=∑i=0T(i−m1)2∗p(i)/s1v_1=\sum_{i=0}^T(i-m_1)^2*p(i)/s_1v1​=i=0∑T​(i−m1​)2∗p(i)/s1​v2=∑i=T255(i−m2)2q(i)/s2v_2=\sum_{i=T}^{255}(i-m_2)^2q(i)/s_2v2​=i=T∑255​(i−m2​)2q(i)/s2​定义目标函数fn=v1+v2f_n=v_1+v_2fn​=v1​+v2​,大津法认为:最合适的阈值TTT,就是令目标函数fnf_nfn​取最小值的那一个,实现代码段为:

for i in range(1,256):p1,p2 = np.hsplit(hist_norm,[i]) # probabilitiesprint('i', i, 'p1,p2', p1, '---', p2)q1,q2 = Q[i],Q[255]-Q[i] # cum sum of classesb1,b2 = np.hsplit(bins,[i]) # weights# finding means and variancesm1,m2 = np.sum(p1*b1)/q1, np.sum(p2*b2)/q2#v1,v2 = np.sum(((b1-m1)**2)*p1)/q1, np.sum(((b2-m2)**2)*p2)/q2v1,v2 = np.sum(((b1-m1)**2)*p1), np.sum(((b2-m2)**2)*p2)fn = v1 + v2# calculates the minimization function#fn = v1*q1 + v2*q2if fn < fn_min:fn_min = fnthresh = i

至此,Otsu阈值分割法推导完毕。问题:为什么令fnf_nfn​最小的阈值TTT就是最合适的TTT?欢迎大家入群深入交流。

下面我们对其原理进行验证,我们找一张双峰图像,如下图所示:

我们将这张图片的灰度直方图打开,呈现出来如下图所示:
可以看出,灰度直方图呈现出近似双峰图像的特点,灰度值较低处体现的是图像中下方“马路”附近的大片像素,灰度值较高处体现的是图像中上方“蓝天”中的大片像素。我们用大津法对其进行分割,效果如下图所示:
代码:

import cv2
import numpy as np
from numpy.core.fromnumeric import shape
from PIL import Image
#plotly
import plotly as py
import plotly.graph_objs as goimg = cv2.imread('road.jpg',0)
img1 = np.ravel(img)
print('type', type(img1), img1.shape, img1)
pyplt = py.offline.plot
data = [go.Histogram(x=img1, histnorm = 'probability')]
ret, th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
print('ret', ret, cv2.THRESH_BINARY_INV, cv2.THRESH_OTSU
pyplt(data)
self.show_img(img, 'road')
self.show_img(th2, 'th2')

将cv2函数计算得到的阈值和我自己计算的阈值打印出来,均为157,说明大津法计算正确。

【opencv-python】大津法(Otsu)阈值分割原理深入分析相关推荐

  1. otsu阈值分割算法原理_大津法---OTSU算法

    简介: 大津法(OTSU)是一种确定图像二值化分割阈值的算法,由日本学者大津于1979年提出.从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景 ...

  2. 【图像处理】——图像的二值化操作及阈值化操作(固定阈值法(全局阈值法——大津法OTSU和三角法TRIANGLE)和自适应阈值法(局部阈值法——均值和高斯法))

    目录 一.二值化的概念(实际上就是一个阈值化操作) 1.概念: 2.实现方法 3.常用方法 二.阈值类型 1.常见阈值类型(主要有五种类型) (1)公式描述 (2)图表描述 2.两种特殊的阈值算法(O ...

  3. 【机器视觉学习笔记】大津法/Otsu最大类间方差法 最佳阈值处理(C++)

    目录 概念 C++源码 OtsuThreshold 主函数 效果 完整源码 平台:Windows 10 20H2 Visual Studio 2015 OpenCV 4.5.3 本文所用源码修改自C+ ...

  4. 【智能车】图像二值化算法--大津法OTSU

    图像二值化算法–大津法OTSU 大津算法是一种图像二值化算法,作用是确定将图像分成黑白两个部分的阈值. 大津法是针对灰度值进行阈值分割二值化,如果是彩色图像的话需要先转化成灰度图再进行计算. 方差越大 ...

  5. 最大类间方差法(大津法OTSU)原理

    算法介绍 最大类间方差法是1979年由日本学者大津提出的,是一种自适应阈值确定的方法,又叫大津法,简称OTSU,是一种基于全局的二值化算法,它是根据图像的灰度特性,将图像分为前景和背景两个部分.当取最 ...

  6. 算法001:大津法OTSU学习记录

    OTSU算法 一.大津法主要的工作是什么? 大多数时候,我们需要获取到一幅图像中的特定目标.如果可以根据像素值将图像进行合理的分割,例如全局阈值分割那样,找到一个阈值TTT,大于阈值TTT的赋予一个像 ...

  7. 图像分割之大津法Otsu

    中文网上大津法的介绍很多,但是大多数给出的代码不是最优的而且存在分母为零的问题. 基本概念 大津法(简称Otsu)由1979年由日本学者大津提出的,是一种自适应阈值确定的方法,相关文献链接.它是根据图 ...

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

    大津法又叫最大类间方差法,是于1979年由日本学者大津展之提出的一种对图像进行二值化的高效算法,是在判别与最小二乘法原理的基础上推导出来的. 算法原理 把直方图在某一阈值处分割为两组,当前分成的两组间 ...

  9. java大津法确定阈值,大津法(最大类间阈值法)

    大津法又叫最大类间方差法.最大类间阈值法(OTSU).它的基本思想是,用一个阈值将图像中的数据分为两类,一类中图像的像素点的灰度均小于这个阈值,另一类中的图像的像素点的灰度均大于或者等于该阈值.如果这 ...

最新文章

  1. 适用于CUDA GPU的Numba 随机数生成
  2. 跟我学爬虫-1-爬虫简介
  3. 在配置文件(.settings、.config)中存储自定义对象
  4. bg和fg指令(整理)以及 Linux中Ctrl+C、Ctrl+D等按键操作进程相关命令
  5. 为什么说红外热成像测温设备是2020年最火的弱电设备?
  6. More Effective C# Item3 : 运行时检查泛型参数的类型并提供特定的算法
  7. MYSQL中group_concat有长度限制!默认1024
  8. 20150310+SVN版本控制-01
  9. 【QT】QT从零入门教程(六):QDockWidget停靠窗口
  10. jenkins 忘记密码或认证配置出错后解决办法
  11. Java面试通关要点汇总整理
  12. CentOS 6.3下Samba服务器的安装与配置【转载】
  13. java 打包运行环境_Jar 打包 EXE文件,可以脱离java环境运行 Jsmooth的使用
  14. 苹果机查看macOS版本号
  15. LoRa开发|LoRa模组AT指令开发
  16. 猿如意|初识CSDN的开发者工具合集
  17. android 瀑布流 的实现
  18. JavaSE编码实操
  19. Vue中的过滤器(管道)
  20. 普通table表格样式大全

热门文章

  1. 对你的 REST API 进行保护的正确办法
  2. 使用SpringBoot实现QQ邮箱发送验证码校验、注册的步骤详解(配图)
  3. OpenCV中的图像处理 —— 图像梯度+Canny边缘检测+图像金字塔
  4. 计算机应用基础大纲2019,《计算机应用基础》教学大纲20199
  5. 股神巴菲特对股市本质的形象解释
  6. 探索脑电情绪分类(EEG)项目的总结篇
  7. mac系统 SSH配置
  8. 43页县域农业大数据运营服务中心方案介绍
  9. Spring boot 使用mina
  10. 值得收藏的十个销售类网站(整理),给想做销售的人用