目录
1 简单阈值
ret, dst = threshold(src, thresh, maxval, type)
- ret: retVal(返回值),在Otsu‘s中会用到
- dst: 目标图像
- src: 原图像,只能输入单通道图像,通常来说为灰度图
- thresh: 阈值
- maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
- type:阈值类型,包含以下5种类型:
若原图直方图如下:

二进制阈值化:cv2.THRESH_BINARY ,大于阈值取maxval,小于取0

反二进制阈值化:cv2.THRESH_BINARY_INV ,大于阈值取0,小于取maxval

截断阈值化:cv2.THRESH_TRUNC ,大于阈值全取阈值大小,小于则不变

阈值化0:cv2.THRESH_TOZERO ,大于阈值取原值,小于取0

反阈值化0:cv2.THRESH_TOZERO_INV ,大于阈值取0,小于取原值

例如:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('test12.jpg', 0)
ret, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO_INV)
titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in range(6):
plt.subplot(2, 3, i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
选用不同的原图,效果如下:
从外到内:

从左到右:

2 自适应阈值
cv2.adaptiveThreshold(src, maxVal, adaptiveMethold, thresholdType, blockSize, C, dst)
- src: 原图像,只能输入单通道图像,通常来说为灰度图
- maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
- adaptiveMethold: 阈值的计算方法,包含以下2种类型:
cv2.ADAPTIVE_THRESH_MEAN_C, 阈值取自相邻区域的平均值
cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 阈值取值相邻区域的加权和,权重为一个高斯窗口
- thresholdType:二值化操作的类型,与固定阈值函数相同,包含5种类型,同上一节。
- blockSize: 图片中分块的大小
- C :阈值计算方法中的常数项
- dst:目标图像
例如:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('test13.jpg', 0)
img = cv2.medianBlur(img, 5) # 中值滤波
ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# 11 为 Block size, 2 为 C 值
th2 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
th3 = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
titles = ['Original Image',
'Global Thresholding (v = 127)', 'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
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])
plt.xticks([]), plt.yticks([])
plt.show()
结果如下:

3 Otsu's二值化
Otsu’s Binarization是一种基于直方图的二值化方法,它需要和threshold函数配合使用。
在第一部分中我们提到过 retVal,当我们使用 Otsu 二值化时会用到它。 那么它到底是什么呢? 在使用全局阈值时,我们就是随便给了一个数来做阈值,那我们怎么知道
我们选取的这个数的好坏呢?答案就是不停的尝试。如果是一副双峰图像(简 单来说双峰图像是指图像直方图中存在两个峰)呢?我们岂不是应该在两个峰之间的峰谷选一个值作为阈值?这就是 Otsu 二值化要做的。简单来说就是对 一副双峰图像自动根据其直方图计算出一个阈值。(对于非双峰图像,这种方法 得到的结果可能会不理想)。 这里用到到的函数还是cv2.threshold(),但是需要多传入一个参数flag:cv2.THRESH_OTSU。这时要把阈值设为 0。然后算法会找到最优阈值,这个最优阈值就是返回值 retVal。如果不使用 Otsu 二值化,返回的 retVal 值与设定的阈值相等。
Otsu过程:
1. 计算图像直方图;
2. 设定一阈值,把直方图强度大于阈值的像素分成一组,把小于阈值的像素分成另外一组;
3. 分别计算两组内的偏移数,并把偏移数相加;
4. 把0~255依照顺序多为阈值,重复1-3的步骤,直到得到最小偏移数,其所对应的值即为结果阈值。
例如:下面的例子中,输入图像是一副带有噪声的图像。第一种方法,我们设
127 为全局阈值。第二种方法,我们直接使用 Otsu 二值化。第三种方法,我 们首先使用一个9x9 的高斯核除去噪音,然后再使用 Otsu 二值化。看看噪音去除对结果的影响有多大吧。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('test14.jpg', 0)
# global thresholding
ret1, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# Otsu's thresholding
ret2, th2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# Otsu's thresholding after Gaussian filtering
# (9,9)为高斯核的大小,8 为标准差
blur = cv2.GaussianBlur(img, (9, 9), 8)
# 阈值一定要设为 0!
ret3, th3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# plot all the images and their histograms
images = [img, 0, th1, img, 0, th2, blur, 0, th3]
titles = ['Original Noisy Image', 'Histogram', 'Global Thresholding (v=127)', 'Original Noisy Image',
'Histogram', "Otsu's Thresholding", 'Gaussian filtered 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()
结果如下:

本文详细介绍了图像处理中的阈值技术,包括简单阈值、自适应阈值和Otsu's二值化方法。通过实例展示了不同阈值类型的效果,如二进制、反二进制、截断、阈值化0和反阈值化0,以及如何利用自适应阈值和Otsu's二值化处理复杂图像。
25万+

被折叠的 条评论
为什么被折叠?



