OTSU算法:对图像进行二值化的算法
介绍
OTSU算法是一种自适应的阈值确定的方法,又称大津阈值分割法,是最小二乘法意义下的最优分割。
它是按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。
从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景图像的类间方差最大。
应用:是求图像全局阈值的最佳方法,适用于大部分需要求图像全局阈值的场合。
优点:计算简单快速,不受图像亮度和对比度的影响。
缺点:对图像噪声敏感;只能针对单一目标分割;当目标和背景大小比例悬殊、类间方差函数可能呈现双峰或者多峰,这个时候效果不好。
原理
求类间方差:
OTSU算法的假设是存在阈值TH将图像所有像素分为两类C1(小于TH)和C2(大于TH),则这两类像素各自的均值就为m1、m2,图像全局均值为mG。同时像素被分为C1和C2类的概率分别为p1、p2。因此就有:
p1*m1+p2*m2=mG (1)
p1+p2=1 (2)
根据方差的概念,类间方差表达式为:
(3)
我们把上式化简,将式(1)代入式(3),可得:
(4)
其实求能使得上式最大化的灰度级 k 就是OTSU阈值了,很多博客也是这样做的。
其中:
(5)
(6)
(7)
照着公式,遍历0~255个灰度级,求出使式(4)最大的 k 就ok了。
(原文方法见博客:https://blog.csdn.net/weixin_40647819/article/details/90179953)
分割:
这个分割就是二值化,OpenCV给了以下几种方式,很简单,可以参考:
实现
# coding:utf-8
import cv2
from matplotlib import pyplot as pltimage = cv2.imread(r"C:\Users\Administrator\Desktop\picture.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)plt.subplot(131), plt.imshow(image, "gray")
plt.title("source image"), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.hist(image.ravel(), 256)
plt.title("Histogram"), plt.xticks([]), plt.yticks([])
ret1, th1 = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU) # 方法选择为THRESH_OTSU
plt.subplot(133), plt.imshow(th1, "gray")
plt.title("OTSU,threshold is " + str(ret1)), plt.xticks([]), plt.yticks([])
plt.show()
参考博客:https://blog.csdn.net/weixin_40647819/article/details/90179953