常用二值化方法:双峰法、P参数法、最大类间方差法(Otsu,大津法)、最大熵阈值法、迭代法(最佳阈值法)。

二值化方法可以划分为全局阈值法局部阈值法,其中全局阈值法包括:大津法、

1、大津法

大津法(OTSU)是一种确定图像二值化分割阈值的算法,由日本学者大津于1979年提出。从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景图像的类间方差最大。
它被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响,因此在数字图像处理上得到了广泛的应用。它是按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。
应用:是求图像全局阈值的最佳方法,应用不言而喻,适用于大部分需要求图像全局阈值的场合。
优点:计算简单快速,不受图像亮度和对比度的影响。
缺点:对图像噪声敏感;只能针对单一目标分割;当目标和背景大小比例悬殊、类间方差函数可能呈现双峰或者多峰,这个时候效果不好。

参考:OTSU算法(大津法—最大类间方差法)原理及实现

 

 

 

1. opencv 简单阈值 cv2.threshold
2. opencv 自适应阈值 cv2.adaptiveThreshold (自适应阈值中计算阈值的方法有两种:mean_c 和 guassian_c ,可以尝试用下哪种效果好)
3. Otsu's 二值化(最大类间方差法、大津法)

例子:
来自 : OpenCV-Python 中文教程

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('scratch.png', 0)
# global thresholding
ret1, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# Otsu's thresholding
th2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
# Otsu's thresholding
# 阈值一定要设为 0 !
ret3, th3 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# plot all the images and their histograms
images = [img, 0, th1, img, 0, th2, img, 0, th3]
titles = [
    'Original Noisy Image', 'Histogram', 'Global Thresholding (v=127)',
    'Original Noisy Image', 'Histogram', "Adaptive Thresholding",
    'Original Noisy Image', 'Histogram', "Otsu's Thresholding"
]
# 这里使用了 pyplot 中画直方图的方法, plt.hist, 要注意的是它的参数是一维数组
# 所以这里使用了( numpy ) ravel 方法,将多维数组转换成一维,也可以使用 flatten 方法
# ndarray.flat 1-D iterator over an array.
# ndarray.flatten 1-D array copy of the elements of an array in row-major order.
for i in range(3):
    plt.subplot(3, 3, i * 3 + 1), plt.imshow(images[i * 3], 'gray')
    plt.title(titles[i * 3]), plt.xticks([]), plt.yticks([])
    plt.subplot(3, 3, i * 3 + 2), plt.hist(images[i * 3].ravel(), 256)
    plt.title(titles[i * 3 + 1]), plt.xticks([]), plt.yticks([])
    plt.subplot(3, 3, i * 3 + 3), plt.imshow(images[i * 3 + 2], 'gray')
    plt.title(titles[i * 3 + 2]), plt.xticks([]), plt.yticks([])
plt.show()

4. skimage niblack阈值
5. skimage sauvola阈值 (主要用于文本检测)

例子:

https://scikit-image.org/docs/dev/auto_examples/segmentation/plot_niblack_sauvola.html

import matplotlib
import matplotlib.pyplot as plt

from skimage.data import page
from skimage.filters import (threshold_otsu, threshold_niblack,
                             threshold_sauvola)


matplotlib.rcParams['font.size'] = 9


image = page()
binary_global = image > threshold_otsu(image)

window_size = 25
thresh_niblack = threshold_niblack(image, window_size=window_size, k=0.8)
thresh_sauvola = threshold_sauvola(image, window_size=window_size)

binary_niblack = image > thresh_niblack
binary_sauvola = image > thresh_sauvola

plt.figure(figsize=(8, 7))
plt.subplot(2, 2, 1)
plt.imshow(image, cmap=plt.cm.gray)
plt.title('Original')
plt.axis('off')

plt.subplot(2, 2, 2)
plt.title('Global Threshold')
plt.imshow(binary_global, cmap=plt.cm.gray)
plt.axis('off')

plt.subplot(2, 2, 3)
plt.imshow(binary_niblack, cmap=plt.cm.gray)
plt.title('Niblack Threshold')
plt.axis('off')

plt.subplot(2, 2, 4)
plt.imshow(binary_sauvola, cmap=plt.cm.gray)
plt.title('Sauvola Threshold')
plt.axis('off')

plt.show()

结果如下:

6. IntegralThreshold (主要用于文本检测)
使用方法: 运行下面网址的util.py文件
https://github.com/Liang-yc/IntegralThreshold
结果图:

 

迭代方法:

默认方式是通过迭代方法来求取阈值T,通过假设阈值T来分割图像为两部分,对各个部分求取均值M1与M2假设T' = (M1+M2) 不等于T则令T= T'然后继续迭代直到两者相等。

Huang阈值分割法:

方法来自于Huang L-K & Wang M-JJ模式识别论文《ImageThresholding By minimizing the measure of fuzziness》具体可以自己看论文。

InterModes阈值分割:

该方法假设直方图是一个双峰模式的直方图,对直方图使用平滑滤波迭代多次,知道只剩下两个最大的峰J与K则阈值为T=(J+K)/2, 如果图像形成直方图只会有一个单峰或者有大片平坦区域的时候,该方法不太适合。

IsoData阈值分割:

该方法基于Ridler, TW&Calvard的论文《Picture thresholding using an iterative selection method》该方法通过给定一个随机阈值假设127把图像分为对象与背景进行分割,计算两部分的均值,不断迭代,直到阈值大于复合均值为止。最终阈值为:阈值 = (背景像素均值+对象像素均值)/2。感兴趣可以自己看Paper。

Li阈值分割:

基于Li的最小交叉熵阈值迭代方法,感兴趣者可以看论文《Minimum CrossEntropy Thresholding》了解更多细节。

MaxEntropy(最大熵值分割):

基于Kapur-Sahoo-Wong的《Maximum Entropy thresholdingmethod》方法实现该算法,ImageJ Fiji中已经实现。

均值方法分割:

使用灰度图像计算所有像素值的均值作为阈值实现图像二值化分割方法。

MinError(最小错误):

迭代算法基于Kittler与Illingworth的最小错误阈值分割方法,初始开始迭代的阈值为均值。除了ImageJ中已有实现,此方法在MATLAB中也有实现。

Minimum(最小阈值):

该方法类似于中间帧模式(InterModes),都是假设直方图有两个波峰,通过均值平滑滤波最终得到两个本地最大的波峰,阈值等于yt-1>yt<=yt+1。该方法主要用于细胞图像分析,相关论文见《TheAnalysis of cell images》。MATLAB中同样也实现了该方法。

Moments(几何矩阈值):

该方法是根据Tsai.W的论文《Moment-preserving thresholding: anew approach》

Otsu阈值

Otsu主要是图像直方图进行阈值分类,从0~255之间,然后求它们的最小内方差对应直方图灰度索引值作为阈值实现图像二值化,OpenCV中已经实现,而且是OpenCV2.x全局阈值二值化方法。

Percentile阈值

该方法假设前景像素ptile=0.5,然后对直方图按照灰度强度从0~255作为每个阈值分割通过迭代寻找最小比重值,最终得到阈值T。

RenyiEntropy(雷尼熵阈值分割)

跟最大熵值方法类似,唯一不同是用Renyi熵计算公式取代广义熵值公式。

 

最大熵值为:

 

其中q取值不同决定阈值不同。通常q取1或者2。

Shanbhag(阈值分割)

该方法同样是基于直方图熵值实现的阈值分割方法。具体可以参考《Utilization of information measure as a means of image thresholding》了解原理。

Triangle(三角阈值分割)

该方法是假设直方图只有一个波峰(单峰直方图)使用如下方法求得最大距离对应的直方图灰度值即为阈值。OpenCV在其3.x版本中已经实现该方法。

 

Yen(阈值分割)

该方法是基于直方图数据的最大相关条件实现的二值图像分割方法。

16种方法Java源代码实现下载地址:

https://github.com/fiji/Auto_Threshold

 

 

参考:python图像处理二值化方法

参考:图像二值化方法汇总介绍

 

 

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐