【opencv-python】大津法(Otsu)阈值分割原理深入分析
大津法(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)/Pmq(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∑Tp(i)s2=∑i=T255q(i)s_2=\sum_{i=T}^{255}q(i)s2=i=T∑255q(i)定义平均值:m1=∑i=0i(i∗p(i))/s1m_1=\sum_{i=0}^i(i*p(i))/s_1m1=i=0∑i(i∗p(i))/s1m2=∑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)/s1v2=∑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)阈值分割原理深入分析相关推荐
- otsu阈值分割算法原理_大津法---OTSU算法
简介: 大津法(OTSU)是一种确定图像二值化分割阈值的算法,由日本学者大津于1979年提出.从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景 ...
- 【图像处理】——图像的二值化操作及阈值化操作(固定阈值法(全局阈值法——大津法OTSU和三角法TRIANGLE)和自适应阈值法(局部阈值法——均值和高斯法))
目录 一.二值化的概念(实际上就是一个阈值化操作) 1.概念: 2.实现方法 3.常用方法 二.阈值类型 1.常见阈值类型(主要有五种类型) (1)公式描述 (2)图表描述 2.两种特殊的阈值算法(O ...
- 【机器视觉学习笔记】大津法/Otsu最大类间方差法 最佳阈值处理(C++)
目录 概念 C++源码 OtsuThreshold 主函数 效果 完整源码 平台:Windows 10 20H2 Visual Studio 2015 OpenCV 4.5.3 本文所用源码修改自C+ ...
- 【智能车】图像二值化算法--大津法OTSU
图像二值化算法–大津法OTSU 大津算法是一种图像二值化算法,作用是确定将图像分成黑白两个部分的阈值. 大津法是针对灰度值进行阈值分割二值化,如果是彩色图像的话需要先转化成灰度图再进行计算. 方差越大 ...
- 最大类间方差法(大津法OTSU)原理
算法介绍 最大类间方差法是1979年由日本学者大津提出的,是一种自适应阈值确定的方法,又叫大津法,简称OTSU,是一种基于全局的二值化算法,它是根据图像的灰度特性,将图像分为前景和背景两个部分.当取最 ...
- 算法001:大津法OTSU学习记录
OTSU算法 一.大津法主要的工作是什么? 大多数时候,我们需要获取到一幅图像中的特定目标.如果可以根据像素值将图像进行合理的分割,例如全局阈值分割那样,找到一个阈值TTT,大于阈值TTT的赋予一个像 ...
- 图像分割之大津法Otsu
中文网上大津法的介绍很多,但是大多数给出的代码不是最优的而且存在分母为零的问题. 基本概念 大津法(简称Otsu)由1979年由日本学者大津提出的,是一种自适应阈值确定的方法,相关文献链接.它是根据图 ...
- 图像分割——大津法(Otsu)
大津法又叫最大类间方差法,是于1979年由日本学者大津展之提出的一种对图像进行二值化的高效算法,是在判别与最小二乘法原理的基础上推导出来的. 算法原理 把直方图在某一阈值处分割为两组,当前分成的两组间 ...
- java大津法确定阈值,大津法(最大类间阈值法)
大津法又叫最大类间方差法.最大类间阈值法(OTSU).它的基本思想是,用一个阈值将图像中的数据分为两类,一类中图像的像素点的灰度均小于这个阈值,另一类中的图像的像素点的灰度均大于或者等于该阈值.如果这 ...
最新文章
- 适用于CUDA GPU的Numba 随机数生成
- 跟我学爬虫-1-爬虫简介
- 在配置文件(.settings、.config)中存储自定义对象
- bg和fg指令(整理)以及 Linux中Ctrl+C、Ctrl+D等按键操作进程相关命令
- 为什么说红外热成像测温设备是2020年最火的弱电设备?
- More Effective C# Item3 : 运行时检查泛型参数的类型并提供特定的算法
- MYSQL中group_concat有长度限制!默认1024
- 20150310+SVN版本控制-01
- 【QT】QT从零入门教程(六):QDockWidget停靠窗口
- jenkins 忘记密码或认证配置出错后解决办法
- Java面试通关要点汇总整理
- CentOS 6.3下Samba服务器的安装与配置【转载】
- java 打包运行环境_Jar 打包 EXE文件,可以脱离java环境运行 Jsmooth的使用
- 苹果机查看macOS版本号
- LoRa开发|LoRa模组AT指令开发
- 猿如意|初识CSDN的开发者工具合集
- android 瀑布流 的实现
- JavaSE编码实操
- Vue中的过滤器(管道)
- 普通table表格样式大全