1 基本概念
CV2中使用阈值的作用是将灰度图像二值化,即将灰度图像的像素值根据一个设定的阈值分成黑白两部分。阈值处理可以用于图像分割、去除噪声、增强图像对比度等多个领域。例如,在物体检测和跟踪中,可以通过对图像进行阈值处理来提取目标区域;在图像增强中,可以使用阈值处理来增强图像的轮廓和细节等。
阈值处理可以使用cv2.threshold()
函数来完成。
retval, dst = cv2.threshold(src, thresh, maxval, type)
其中,参数解释如下:
src
:输入图像,可以是灰度图像或彩色图像。thresh
:设定的阈值。maxval
:二值化后的最大值。当type
为cv2.THRESH_BINARY
或cv2.THRESH_BINARY_INV
时,像素值大于阈值的部分会设置为maxval
,否则会设置为0。type
:二值化操作的类型,包括:cv2.THRESH_BINARY
:二值化操作,大于阈值的像素值设置为maxval
,小于等于阈值的像素值设置为0。cv2.THRESH_BINARY_INV
:反向二值化操作,大于阈值的像素值设置为0,小于等于阈值的像素值设置为maxval
。cv2.THRESH_TRUNC
:截断操作,大于阈值的像素值设置为阈值,小于等于阈值的像素值保持不变。cv2.THRESH_TOZERO
:像素值小于等于阈值的设置为0,大于阈值的保持不变。cv2.THRESH_TOZERO_INV
:像素值大于等于阈值的设置为0,小于阈值的保持不变。
cv2.threshold()
函数的返回值为一个元组,包括:
retval
:实际使用的阈值。dst
:二值化后的输出图像。
2 二值化处理
灰度图像
通过对灰度图像进行二值处理,可以在图形中只保留两种颜色,通常我们设定为255(白色)和0(黑色),但也可根据需求设置为黑色和灰色的二值图像,如:
import cv2
img = cv2.imread("lenacolor.png", 0) # 将图像读成灰度图像
t1, dst1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 二值化阈值处理
t2, dst2 = cv2.threshold(img, 127, 200, cv2.THRESH_BINARY)
cv2.imshow('img', img)
cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey()
cv2.destroyAllWindows()
彩色图像
同样这一方法可用于彩色图像,通过对某一通道进行二值化,使图像的颜色变得更加夸张,如:
import cv2
img = cv2.imread('lenacolor.png')
b, g, r = cv2.split(img) # 将BGR通道分离
# 对红色通道进行阈值处理
t1, r = cv2.threshold(r, 127, 255, cv2.THRESH_BINARY)
img_after = cv2.merge([b, g, r])
cv2.imshow('original', img)
cv2.imshow('threshold', img_after)
cv2.waitKey(0)
cv2.destroyAllWindows()
反二值化处理
反二值化处理(Inverse Thresholding)是二值化处理的一种变体,其作用是将灰度图像的像素值根据一个设定的阈值分成两部分,但是与普通二值化处理不同的是,反二值化处理将像素值大于阈值的部分设置为0,小于等于阈值的部分设置为最大像素值,即产生一个反色的二值化图像。代码中type需要设置为cv2.THRESH_BINARY_INV
。
3 零处理
低于阈值零处理
低于阈值的部分会被处理为0,此时填入的maxval
无效
对灰度图来说,低于阈值的部分将会被处理为黑色;对于RGB彩图来说,低于阈值的部分图像会变暗。
import cv2
img1 = cv2.imread("test.png", 0) # 将图像读成灰度图像
img2 = cv2.imread("test.png")
b, g, r = cv2.split(img2) # 将BGR通道分离
t1, dst1 = cv2.threshold(img1, 127, 255, cv2.THRESH_TOZERO) # 低于阈值零处理
cv2.imshow('img1', img1)
cv2.imshow('dst1', dst1)
t2, b = cv2.threshold(b, 127, 255, cv2.THRESH_TOZERO) # 低于阈值零处理
img_after = cv2.merge([b, g, r])
cv2.imshow('img2', img2)
cv2.imshow('img_after', img_after)
cv2.waitKey()
cv2.destroyAllWindows()
超出阈值零处理
类似反二值化处理。将超出某一阈值的部分进行归零处理。超出阈值零处理可以在一些特定的场合下使用,例如在一些需要保留一定程度的图像细节的场合,超出阈值零处理可以避免将过多的像素值直接设置为0或最大像素值,从而使图像保留更多的细节信息。
4 截断处理
该方法传入的type是cv2.THRESH_TRUNC
,代码结构与前面高度重合,此处不再贴代码。
截断处理是二值化处理的一种变体,其作用是将灰度图像的像素值根据一个设定的阈值分成两部分,但是与普通的二值化处理不同的是,超出阈值的部分不会被设置为0或最大像素值,而是被截断为阈值本身。
图像截断处理通常适合用于需要保留图像主要信息的场合,而又不需要进行明显的二值化操作的场合。在这种情况下,截断处理可以使得图像保留更多的灰度级,从而能够更好地保留图像中的细节和信息,同时又能够去除一些噪声或者不需要的部分。
5 自适应处理
自适应阈值处理是图像处理中的一种常见操作,可以根据图像局部的灰度特征来自适应地确定阈值,以达到更好的二值化效果。在OpenCV中,可以使用cv2.adaptiveThreshold()
函数进行自适应阈值处理。
相比于阈值处理,自适应处理具有以下优点:
- 自适应处理可以根据局部像素的灰度值特征来确定二值化阈值,从而适应图像的不同区域和不同光照条件,能够更好地突出图像中的目标物体。
- 自适应处理可以在处理过程中保留更多的细节信息,减少因阈值过大或过小而造成的信息丢失,提高图像处理的准确性。
- 自适应处理适用于复杂背景下的目标物体分割,特别是在背景区域灰度分布不均的情况下,能够更好地处理背景区域和目标区域的差异。
自适应处理相比于阈值处理具有更好的适应性和灵活性,可以在不同的图像处理场景中应用。当图像的灰度分布不均、光照条件不同或需要保留更多的细节信息时,自适应处理通常是更好的选择。
cv2.adaptiveThreshold()
函数的基本语法如下:
dst = cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)
其中:
src
:输入图像,必须为灰度图像。maxValue
:二值化后的最大值。adaptiveMethod
:自适应阈值处理的方法,包括:cv2.ADAPTIVE_THRESH_MEAN_C
:基于均值的自适应阈值处理。cv2.ADAPTIVE_THRESH_GAUSSIAN_C
:基于高斯加权平均值的自适应阈值处理。
thresholdType
:阈值类型,与普通二值化处理相同,包括:cv2.THRESH_BINARY
:二值化操作,大于阈值的像素值设置为maxValue
,小于等于阈值的像素值设置为0。cv2.THRESH_BINARY_INV
:反向二值化操作,大于阈值的像素值设置为0,小于等于阈值的像素值设置为maxValue
。
blockSize
:每个像素点周围用来计算阈值的像素数。必须是奇数。C
:阈值校正值。该值会被加到均值或加权平均值上,用于调整阈值。
cv2.adaptiveThreshold()
函数的返回值为二值化后的输出图像。
仍以上一张图像为例:
import cv2
image_Gray = cv2.imread("test.png", 0)
# 自适应阈值的计算方法为cv2.ADAPTIVE_THRESH_MEAN_C
athdMEAM = cv2.adaptiveThreshold\
(image_Gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 5, 0)
# 自适应阈值的计算方法为cv2.ADAPTIVE_THRESH_GAUSSIAN_C
athdGAUS = cv2.adaptiveThreshold\
(image_Gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY, 5, 0)
# 显示自适应阈值处理的结果
cv2.imshow("MEAN_C", athdMEAM)
cv2.imshow("GAUSSIAN_C", athdGAUS)
cv2.waitKey()
cv2.destroyAllWindows()
可以看出自适应阈值似乎保留了更多细节,但此处效果并不好,也就说明自适应并不能完全代替人工选择。(对于人脸图像,该方法的效果会比上图更好一些)
6 Ostu方法
Otsu’s method 是一种经典的自适应阈值处理算法,可以自动确定图像的二值化阈值。该算法可以将图像中的像素值分为两部分,从而将图像转换为二值图像。在 OpenCV 中,可以使用cv2.threshold()
函数进行 Otsu’s method 处理。在type中,输入对应的方法名+cv2.THRESH_OTSU
即可调用该方法。该方法的存在也是threshold将阈值作为返回值的意义所在。
在 Otsu’s method 中,不需要预先指定阈值,而是通过计算图像灰度直方图和类间方差来确定阈值。具体来说,该方法会计算每一个像素灰度值作为阈值时,将图像分为前景和背景两部分的类间方差,然后选取类间方差最大的像素灰度值作为二值化阈值。
import cv2
img = cv2.imread('test.png', 0)
ret, thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imshow('original', img)
cv2.imshow('Otsu threshold', thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()