参考:
[otsu (大津算法)]
一、背景
在理想情况下,直方图在代表目标和背景的两个峰值之间有一个深而尖的谷,因此可以在这个山谷的底部选择阈值。
然而,对于大多数真实的图片,往往很难准确地探测谷底,尤其是在山谷平坦、宽阔、充满噪音、或两个山峰高度极不相等时,往往没有可追踪的山谷。
二、方法
一种非参数无监督的图像阈值自动选取方法。通过判别准则选择最优阈值,即最大化灰度值中所得类的可分性。程序很简单,利用只有零和灰度直方图的一阶累积矩。
它是按图像的灰度特性,将图像分成背景和目标2部分。背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致2部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。
三、实现过程:
Python3.6
1.统计图像灰度直方图hist数组
2.计算图像最大类间方差
3.根据计算出的最佳阈值进行二值化操作
Python代码如下:
#coding:utf-8
import cv2
import numpy as np
from matplotlib import pyplot as plt
image = cv2.imread("c:\\users\\hualili\\Desktop\\2.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()
效果图如下: