otsu阈值分割算法原理_Opencv从零开始 - [启蒙篇] - 阈值分析

本文介绍了OpenCV中的图像阈值处理,包括固定阈值、自适应阈值和Otsu阈值法。重点讲解了Otsu阈值法的原理,如何通过最大类间方差自动计算最优阈值,适合于双峰图片的二值化处理。
摘要由CSDN通过智能技术生成

这篇文章和大家一起来解读下opencv关于阈值分析这块的知识点,希望能够加深大家对其的理解~


图像阈值

  • ⛳️ 使用固定阈值、自适应阈值和Otsu阈值法”二值化”图像
  • ⛳️ OpenCV函数:cv2.threshold(), cv2.adaptiveThreshold()

简单阈值

当像素值高于阈值时,我们给这个像素赋予一个新值(可能是白色),否则我们给它赋予另外一种颜色(可能是黑色)。这个函数就是 cv2.threshhold()。

294b5e066833da457a2202f05423c211.png

简单阈值

cv2.threshold() 用来实现阈值分割,ret是return value缩写,代表当前的阈值,暂时不用理会。函数有4个参数:

  • 参数1:要处理的原图,一般是灰度图
  • 参数2:设定的阈值
  • 参数3:最大阈值,一般为255
  • 参数4:阈值的方式,主要有5种cv.THRESH_BINARYcv.THRESH_BINARY_INVcv.THRESH_TRUNCcv.THRESH_TOZEROcv.THRESH_TOZERO_INV
import matplotlib.pyplot as plt# 应用5种不同的阈值方法ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)ret, th2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)ret, th3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)ret, th4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)ret, th5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)titles = ['Original', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']images = [img, th1, th2, th3, th4, th5]# 使用Matplotlib显示for i in range(6):    plt.subplot(2, 3, i + 1)    plt.imshow(images[i], 'gray')    plt.title(titles[i], fontsize=8)    plt.xticks([]), plt.yticks([])  # 隐藏坐标轴plt.show()
6ce98291074052714900ce6da8179abd.png

阈值类型

自适应阈值

固定阈值是在整幅图片上应用一个阈值进行分割,它并不适用于明暗分布不均的图片。 cv2.adaptiveThreshold()自适应阈值会每次取图片的一小部分计算阈值,这样图片不同区域的阈值就不尽相同,从而使我们能在亮度不同的情况下得到更好的结果。

img = cv2.imread('sudoku.jpg', 0)#固定阈值ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)#自适应阈值th2 = cv2.adaptiveThreshold(    img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 4)    th3 = cv2.adaptiveThreshold(    img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 17, 6)titles = ['Original', 'Global(v = 127)', 'Adaptive Mean', 'Adaptive Gaussian']images = [img, th1, th2, th3]#显示for i in range(4):    plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')    plt.title(titles[i], fontsize=8)    plt.xticks([]), plt.yticks([])plt.show()
  • 参数1:要处理的原图
  • 参数2:最大阈值,一般为255
  • 参数3:小区域阈值的计算方式☘️ADAPTIVE_THRESH_MEAN_C:小区域内取均值ADAPTIVE_THRESH_GAUSSIAN_C:小区域内加权求和,权重是个高斯核
  • 参数4:阈值方式(跟前面讲的那5种相同)
  • 参数5:小区域的面积,如11就是11*11的小块
  • 参数6:最终阈值等于小区域计算出的阈值再减去此值
b89230a766ec446aac068a23ae4ce498.png

自适应阈值

Otsu阈值

大部分的图像处理任务都需要进行二值化处理,阈值的选取很重要,Otsu阈值法可以自动计算阈值,而且该方法非常适合双峰图片。

这里用到的函数是 cv2.threshold(),但是需要多传入一个参数(flag):cv2.THRESH_OTSU,这时把阈值设置为0。然后算法会找到最优阈值,这个最优阈值就是返回值 retVal。如果不使用 Otsu 二值化,返回的retVal 值与设定的阈值相等。

❓问:什么是双峰图片?

❗答:双峰图片就是指图片的灰度直方图上有两个峰值,直方图就是每个值(0~255)的像素点个数统计。

Otsu算法假设这副图片由前景色和背景色组成,通过统计学方法(最大类间方差)选取一个阈值,将前景和背景尽可能分开。

☘️下面这段代码对比了使用固定阈值和Otsu阈值后的不同结果:

☘️另外,对含噪点的图像,先进行滤波操作效果会更好。

import cv2import matplotlib.pyplot as pltimg = cv2.imread('noisy.jpg', 0)# 固定阈值ret1, th1 = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY)# Otsu阈值ret2, th2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)# 先进行高斯滤波,在使用Otsu阈值blur = cv2.GaussianBlur(img, (5,5), 0)ret3, th3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)# 可视化images = [img, 0, th1, img, 0, th2, blur, 0, th3]titles = ['Original', 'Histogram', 'Global(v=100)',          'Original', 'Histogram', "Otsu's",          'Gaussian filtered Image', 'Histogram', "Otsu's"]for i in range(3):    # 绘制原图    plt.subplot(3, 3, i * 3 + 1)    plt.imshow(images[i * 3], 'gray')    plt.title(titles[i * 3], fontsize=8)    plt.xticks([]), plt.yticks([])    # 绘制直方图plt.hist,ravel函数将数组降成一维    plt.subplot(3, 3, i * 3 + 2)    plt.hist(images[i * 3].ravel(), 256)    plt.title(titles[i * 3 + 1], fontsize=8)    plt.xticks([]), plt.yticks([])    # 绘制阈值图    plt.subplot(3, 3, i * 3 + 3)    plt.imshow(images[i * 3 + 2], 'gray')    plt.title(titles[i * 3 + 2], fontsize=8)    plt.xticks([]), plt.yticks([])plt.show()
d0793140f8acb8c46298a794f6caa788.png

Otsu阈值

PS: 绘制直方图时,使用了numpy中的ravel()函数,它会将原矩阵压缩成一维数组,便于画直方图。

Otsu 算法详解: Otsu阈值法将整幅图分为前景(目标)和背景,以下是一些符号规定:

  • T:分割阈值
  • N0:前景像素点数
  • N1:背景像素点数
  • ω0:前景的像素点数占整幅图像的比例
  • ω1:背景的像素点数占整幅图像的比例
  • μ0:前景的平均像素值
  • μ1:背景的平均像素值
  • μ:整幅图的平均像素值
  • rows×cols:图像的行数和列数 结合下图会更容易理解一些,有一副大小为4×4的图片,假设阈值T为1,那么:

其实很好理解,N_0+N_1N0​+N1​ 就是总的像素点个数,也就是行数乘列数:

e1c91f12eed65fa7f7bce9345ecd4bfc.png

ω_0ω0​和ω_1ω1​是前/背景所占的比例,也就是:

f65b324f464a3bc4df7e4fb46b0b0962.png

整幅图的平均像素值就是:

92904cfec9f75672d00f64faefe32f71.png

此时,我们定义一个前景μ_0μ0​与背景μ_1μ1​的方差gg:

f4abf18f9c7f76ea2c4b38cfc63e54d8.png

将前述的1/2/3公式整合在一起,便是:

136daa063f0148f128f7744d838c06df.png

g 就是前景与背景两类之间的方差,这个值越大,说明前景和背景的差别也就越大,效果越好。

Otsu算法便是遍历阈值T,使得g最大,所以又称为最大类间方差法

基本上双峰图片的阈值T在两峰之间的谷底。

未完待续~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值