文章结构
- 阈值概述
- 阈值处理函数
- 二值化阈值处理
- 二值化阈值处理
- 反二值化处理
- 零处理
- 低于阈值零处理
- 超出阈值零处理
- 截断处理
- 自适应处理
- Otsu方法
阈值概述
在PhotoShop里头,有一个工具可以快速抠出一幅图像中的轮廓,这个工具就是阈值。OpenCV也提供了阈值,且与PS里头的阈值有相同的作用。在OpenCV中,阈值是一个临界值,类似一个”像素值的标准线“。所有像素值都会与这条“标准线”进行比较,最后得到三种结果:像素值比阈值大、像素值比阈值小和像素值等于阈值。程序会根据这些结果将所有像素进行分组,然后对某一组像素进行“加深”或者“变淡”的操作,使得一幅图像的轮廓更加鲜明,更容易被计算机和肉眼识别。
阈值处理函数
在图像处理的过程中,阈值使得图像的像素值更单一,进而使得图像的效果更简单。
- 首先,把一幅彩色图像转换为灰度图像,这样图像的像素值的取值范围即可简化为0 ~ 255。
- 然后,通过阈值使得转换后的灰度图像呈现出只有黑色和白色的视觉效果。
例如,当阈值为127时,把小于127的所有像素值都转换为0(即黑色),把大于127的所有像素值都转换为255(即白色)。虽然会丢失一些灰度细节,但是会更明显地保留灰度图像整体的轮廓。
OpenCV提供了threshold()方法用于对图像进行阈值处理。
retval,dst = cv2.threshold(src, thresh, maxval, type)
- src: 被处理的图像,可以是多通道图像
- thresh: 阈值,阈值在125~150范围内取值的效果最好
- maxval: 阈值处理采用的最大值
- type: 阈值处理类型
- retval: 处理时所采用的阈值
- dst: 经过阈值处理后的图像
二值化阈值处理
二值化处理会将灰度图像的像素值两极分化,使得灰度图像呈现出只有纯黑色和纯白色的视觉效果。经过阈值处理后的图像轮廓分明、对比明显,因此二值化处理常用于图像识别功能。
二值化阈值处理
该处理会让图像仅保留两种像素值,或者说所有的像素都只能从两种之中取值。进行二值化处理时,每一个像素都会与阈值进行比较,将大于阈值的像素值变为最大值,将小于或等于阈值的像素值变为0。通常二值化处理是使用255作为最大值,因为灰度图像中255表示白色,能够很清晰地与黑色进行区分。
实例1: 二值化阈值处理白黑渐变图
import cv2
img = cv2.imread("black.png", 0) # 将图像读成灰度图像
t1, dst1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 二值化阈值处理
cv2.imshow('img', img) # 显示原图
cv2.imshow('dst1', dst1) # 二值化阈值处理效果图
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
结果如下:
通过修改阈值大小可以调整黑白交接的位置。通过修改最大值,非黑的像素就从纯白色变为灰色(其灰度值由最大值决定)
反二值化处理
反二值化处理的结果为二值化处理的相反结果。将大于阈值的像素值变为0,将小于或等于阈值的像素值变为最大值。原图像中白色的部分会变成黑色,黑色的部分会变成白色。
实例2: 对图像进行反二值化处理
import cv2
img = cv2.imread("black.png", 0) # 将图像读成灰度图像
t1, dst1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 二值化阈值处理
t4, dst4 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY_INV) # 反二值化阈值处理
cv2.imshow('dst1', dst1) # 展示二值化效果
cv2.imshow('dst4', dst4) # 展示反二值化效果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
结果如下:
零处理
零处理会将某一个范围内的像素值变为0,并允许范围之外的像素保留原值。
低于阈值零处理
将低于或等于阈值的像素值变为0,大于阈值的像素值保持原值。
实例3:对图像进行低于阈值零处理
import cv2
img = cv2.imread("black.png", 0) # 将图像读成灰度图像
t5, dst5 = cv2.threshold(img, 127, 255, cv2.THRESH_TOZERO) # 低于阈值零处理
cv2.imshow('img', img) # 显示原图
cv2.imshow('dst5', dst5) # 低于阈值零处理效果图
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
结果如下:
图像经过低于阈值零处理后,颜色深的位置会彻底变黑,颜色浅的位置不受影响。彩色图像经过低于阈值零处理后,会让深颜色区域的颜色变得更深,甚至变黑。
超出阈值零处理
该处理会将大于阈值的像素值变为0,小于阈值的像素值保持原值。其过程与低于阈值零处理大致相同,类型为THRESH_TOZERO_INV。
图像经过超出阈值零处理后,浅颜色区域会彻底变黑,深颜色区域则不受影响。
截断处理
截断处理也叫阶段阈值处理,将图像中大于阈值的像素值变为和阈值一样的值,小于或等于阈值的像素保持原值。
实例4: 对图像进行截断处理
import cv2
img = cv2.imread("black.png", 0) # 将图像读成灰度图像
t1, dst1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) # 二值化阈值处理
t7, dst7 = cv2.threshold(img, 127, 255, cv2.THRESH_TRUNC) # 截断处理
cv2.imshow('dst1', dst1) # 展示二值化效果
cv2.imshow('dst7', dst7) # 展示截断效果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
结果如下:
自适应处理
如果直接使用一种阈值处理类型对图像进行阈值处理,是无法得到清晰有效的结果的。对此,OpenCV提供了一种改进的阈值处理技术:图像中的不同区域使用不同的阈值,称为自适应阈值处理。
自适应阈值是根据图像中某一正方形区域内的所有像素值按照指定的算法计算得到的,能更好地处理明暗分布不均的图像,获得更简单的图像效果。OpenCV提供了adaptiveThreshold()方法用于对图像进行自适应阈值处理。
dst = cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)
- src: 被处理的图像,必须是灰度图像
- maxValue: 阈值处理采用的最大值
- adaptiveMethod: 自适应阈值的计算方法。
- thresholdType: 阈值处理类型。只能是cv2.THRESH_BINARY或者cv2.THRESH_BINARY_INV中的一个
- blockSize: 一个正方形区域的大小。例如5指的是5×5的区域
- C: 常量。阈值等于均值或者加权值减去这个常量
- dst: 经过阈值处理后的图像
计算方法如下:
实例5: 显示自适应阈值处理的结果
import cv2
image = cv2.imread("4.27.png") # 读取4.27.png
image_Gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 将4.27.png转换为灰度图像
# 自适应阈值的计算方法为cv2.ADAPTIVE_THRESH_MEAN_C
athdMEAM = cv2.adaptiveThreshold\
(image_Gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 5, 3)
# 自适应阈值的计算方法为cv2.ADAPTIVE_THRESH_GAUSSIAN_C
athdGAUS = cv2.adaptiveThreshold\
(image_Gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY, 5, 3)
# 显示自适应阈值处理的结果
cv2.imshow("MEAN_C", athdMEAM)
cv2.imshow("GAUSSIAN_C", athdGAUS)
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 销毁所有窗口
结果如下:
注意: 使用自定义阈值处理图像时,如果是彩色图像,需要先将彩色图像转换为灰度图像,否则会报错。
Otsu方法
逐个寻找最合适的阈值不仅工作量大,而且效率低。对此,OpenCv提供了Otsu方法,能够遍历所有可能的阈值,从中找到最合适的阈值。
Otsu方法的语法与threshold()方法的语法基本一致,只不过在为type传递参数时,要多传递一个参数,即cv2.THRESH_OTSU,其作用就是实现Otsu方法的阈值处理。
retval, dst = cv2.threshold(src, thresh, maxval, type)
- src: 被处理的图像,必须是灰度图像
- thresh: 阈值,且要把阈值设置为0
- maxval: 阈值处理采用的最大值,即255
- type: 阈值处理类型。除了在表5.1中选择一种阈值处理类型外,还要多传递一个参数,即cv2.THRESH_OTSU。例如,cv2.THRESH_BINARY + cv2.THRESH_OTSU
- retval: 由Otsu方法计算得到并使用的最合适的阈值
- dst: 经过阈值处理后的图像
实例6: 实现Otsu方法的阈值处理
import cv2
image = cv2.imread("4.36.jpg") # 读取4.36.jpg
image_Gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 将4.36.jpg转换为灰度图像
t1, dst1 = cv2.threshold(image_Gray, 127, 255, cv2.THRESH_BINARY) # 二值化阈值处理
# 实现Otsu方法的阈值处理
t2, dst2 = cv2.threshold(image_Gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
cv2.putText(dst2, "best threshold: " + str(t2), (0, 30),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2) # 在图像上绘制最合适的阈值
cv2.imshow("BINARY", dst1) # 显示二值化阈值处理的图像
cv2.imshow("OTSU", dst2) # 显示实现Otsu方法的阈值处理
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 销毁所有窗口
结果如下: