什么是阈值?简单说就是一个临界值(分界线)。
例如:一个班有50个学生,期末考试及格(60分及以上)的人数为40人,不及格的人数是10人。这里就是以60分为临界值划分的。60分,可以叫做一个阈值。
图像是由一个个的像素点构成的,像素点的值的范围是 [0, 255] 。对图像做阈值操作,就是给个临界值,筛选像素点。超过临界值,像素值置为几,低于临界值,像素值又置为几,根据不同的处理,就形成了不同的分类。
OpenCV图像阈值操作分为:简单阈值,自适应阈值。在实际应用中,自适应阈值用得比较多。
简单阈值是整个图像采用同一个数作为阈值,是全局阈值。
命令:cv2.threshold(src, thresh, maxval, type, dst=None)
返回两个值,第一个值是阈值,第二个值是阈值化处理后的图像。本文讲解仅使用第二个返回值。
src
:输入图像,通常使用的是灰度图片thresh
:阈值maxval
:超过或低于阈值时,应该置为的值,也可以叫做最大值type
:通过阈值对图像处理的方法(超过或低于阈值的处理方式),有5种,分别是cv2.THRESH_BINARY
二值阈值化(超过阈值的像素值置为255,低于阈值的像素值置为0)cv2.THRESH_BINARY_INV
二值阈值化的反转(超过阈值的像素值置为0,低于阈值的像素值置为255)cv2.THRESH_TRUNC
截断阈值化(超过阈值的像素值置为阈值,低于阈值的像素值保持不变)cv2.THRESH_TOZERO
归零阈值化(超过阈值的像素值保持不变,低于阈值的像素值置为0)cv2.THRESH_TOZERO_INV
归零阈值化的反转(超过阈值的像素值置为0,低于阈值的像素值保持不变)如果还是不太理解,可以参考 Opencv之图像固定阈值二值化处理threshold ,讲解很形象。 最重要的是 cv2.THRESH_TOZERO
和 cv2.THRESH_TOZERO_INV
的操作没有讲反。我看了很多文章,都把这两种方法讲反了。
import cv2
import matplotlib.pyplot as plt
original_image = cv2.imread("pic.jpg", cv2.IMREAD_GRAYSCALE) # 以灰度模式打开图片
_, binary = cv2.threshold(original_image, 127, 255, cv2.THRESH_BINARY) # 二值阈值化
_, binary_inv = cv2.threshold(original_image, 127, 255, cv2.THRESH_BINARY_INV) # 二值阈值化的反转
_, trunc = cv2.threshold(original_image, 127, 255, cv2.THRESH_TRUNC) # 截断阈值化
_, tozero = cv2.threshold(original_image, 127, 255, cv2.THRESH_TOZERO) # 归零阈值化
_, tozero_inv = cv2.threshold(original_image, 127, 255, cv2.THRESH_TOZERO_INV) # 归零阈值化的反转
titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [original_image, binary, binary_inv, trunc, tozero, tozero_inv]
for i in range(6):
plt.subplot(2, 3, i+1), plt.imshow(images[i], "gray") # 以两行三列方式显示6张图片
plt.title(titles[i]) # 设置图片标题
plt.xticks([]), plt.yticks([]) # 取消坐标轴的刻度
# 显示图片
plt.show()
自适应阈值是局部阈值,同一个图像上的不同区域,使用不同的阈值。
命令:cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)
src
:输入图像maxValue
:超过或低于阈值时,应该置为的值,也可以叫做最大值adaptiveMethod
:计算阈值的方法,有两种,分别是cv2.ADAPTIVE_THRESH_MEAN_C
阈值取自相邻区域的平均值cv2.ADAPTIVE_THRESH_GAUSSIAN_C
阈值取自相邻区域的加权和,权重为一个高斯窗口thresholdType
:该参数与 cv2.threshold()
中的参数 type
用的方法是一样的,都是对图像阈值的处理方法blockSize
:邻域大小(用来计算阀值的区域大小),类似于CNN中的卷积核,值应该为奇数C
:一个常数(偏值),最终的阈值是adaptiveMethod
计算出的阈值再减去该常数,一般情况下置为0import cv2
import matplotlib.pyplot as plt
original_image = cv2.imread("chessboard.jpg", cv2.IMREAD_GRAYSCALE) # 以灰度模式打开图片
_, binary = cv2.threshold(original_image, 127, 255, cv2.THRESH_BINARY) # 二值阈值化
# 阈值取自相邻区域的平均值
thresh_mean = cv2.adaptiveThreshold(original_image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 17, 0)
# 阈值取自相邻区域的加权和,权重为一个高斯窗口
thresh_gaussian = cv2.adaptiveThreshold(original_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 17, 0)
images = [original_image, binary, thresh_mean, thresh_gaussian]
titles = ['Original Image', 'BINARY', 'MEAN', 'GAUSSIAN']
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()
cv2.THRESH_BINARY
cv2.THRESH_BINARY_INV
cv2.THRESH_TRUNC
cv2.THRESH_TOZERO
cv2.THRESH_TOZERO_INV
阈值适用范围
简单阈值处理,给定的阈值,用于整个图像,是全局阈值。
自适应阈值处理,计算出的阈值,只用于图像的局部区域,不同区域的阈值不同,所以是局部阈值。
阈值设定
简单阈值处理,是直接给定一个阈值(很直接)。
自适应阈值处理,所需的阈值,是通过 cv2.ADAPTIVE_THRESH_MEAN_C
或 cv2.ADAPTIVE_THRESH_GAUSSIAN_C
方法计算出来的。
偏值
简单阈值处理,由于是直接给定的阈值,所以没有在该阈值的基础上,再作调整。
自适应阈值处理,在通过电脑计算出局部阈值之后,可以给定一个常数(偏值)再进行调整。
[1] Aollo小北.OpenCV-Python中文教程
[2] 啧啧啧biubiu.Opencv之图像固定阈值二值化处理threshold
[3] bingma.OpenCV-图像阈值-简单阈值、自适应阈值、Otsu’s 二值化