Python-Opencv中阈值化操作和自适应阈值化,二值化操作
阈值化
阈值化图像其实就是对灰度图像进行二值化操作,根本原理是利用设定的阈值判断图像像素为0还是255,所以在图像二值化中阈值的设置很重要。图像的二值化分为全局二值化和局部二值化,其区别在于阈值是否在一张图像进行统一。
全局阈值化
全局阈值法方法就是将图像中低于某个阈值的像素设置为黑色(0),而其他的设置为白色(255)。全局固定阈值很容易理解,就是对整幅图像都是用一个统一的阈值来进行二值化
全局阈值化函数
cv2.threshold(src, thresh, maxval, type[, dst]) -> retval, dst
其中:
- src参数表示输入图像(多通道,8位或32位浮点)。
- thresh参数表示阈值。
- maxval参数表示与THRESH_BINARY和THRESH_BINARY_INV阈值类型一起使用设置的最大值。
- type参数表示阈值类型。
- retval参数表示返回的阈值。若是全局固定阈值算法,则返回thresh参数值。若是全局自适应阈值算法,则返回自适应计算得出的合适阈值。
- dst参数表示输出与src相同大小和类型以及相同通道数的图像。
阈值类型如下:
- type参数单独选择上述五种阈值类型时,是固定阈值算法,效果比较差。
- 此外还有自适应阈值算法:(自适应计算合适的阈值,而不是固定阈值)
- 比如结合cv.THRESH_OTSU,写成cv.THRESH_BINARY | cv.THRESH_OTSU。
例子:ret, binary = cv.threshold(gray, 0, 255,cv.THRESH_BINARY | cv.THRESH_OTSU)
OTSU为大律法,全局自适应阈值,第二个参数值0可改为任意数字但不起作用。
注:cv.THRESH_OTSU也可单独使用,不一定要写成和固定阈值算法结合的形式。单独写和结合起来写,都是自适应阈值算法优先。
例子:ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_OTSU) - 比如结合cv.THRESH_TRIANGLE写成cv.THRESH_BINARY | cv.THRESH_TRIANGLE。
例子:ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_TRIANGLE)
TRIANGLE法,全局自适应阈值,第二个参数值0可改为任意数字但不起作用,适用于单个波峰。
注:cv.THRESH_TRIANGLE也可单独使用,不一定要写成和固定阈值算法结合的形式。单独写和结合起来写,都是自适应阈值算法优先。
例子:ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_TRIANGLE)
代码实现全局阈值化
import cv2 as cv
def threshold_demo(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, binary = cv.threshold(gray, 230, 255, cv.THRESH_BINARY)
print("BINARY阈值:%s" % ret)
cv.imshow("BINARY", binary)
ret, binary = cv.threshold(gray, 230, 255, cv.THRESH_BINARY_INV)
print("BINARY_INV阈值:%s" % ret)
cv.imshow("BINARY_INV_230", binary)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_TRIANGLE)
# ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_TRIANGLE) 与上一行代码是同一个意思,| cv.THRESH_TRIANGLE 就是调用这种方法来算阈值
print("TRIANGLE自适应阈值:%s" % ret)
cv.imshow("TRIANGLE", binary)
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_OTSU)
print("OTSU自适应阈值:%s" % ret)
cv.imshow("OTSU", binary)
ret, binary = cv.threshold(gray, 200, 255, cv.THRESH_TRUNC)
print("TRUNC截断阈值:%s" % ret)
cv.imshow("TRUNC_200", binary)
ret, binary = cv.threshold(gray, 100, 255, cv.THRESH_TOZERO)
print("TOZERO归零阈值:%s" % ret)
cv.imshow("TOZERO_100", binary)
src1 = cv.imread("book.jpg")
cv.imshow("book", src1)
threshold_demo(src1)
cv.waitKey(0)
cv.destroyAllWindows()
BINARY阈值:230.0
BINARY_INV阈值:230.0
TRIANGLE自适应阈值:229.0
OTSU自适应阈值:164.0
TRUNC截断阈值:200.0
TOZERO归零阈值:100.0
用以上全局阈值化的效果来看显然全局阈值化的效果不好,其中OTSU阈值优于其他固定阈值。
局部阈值化
局部阈值(局部自适应)则是根据像素的邻域块的像素值分布来确定该像素位置上的二值化阈值,自适应阈值是图像的不同的区域使用不同的阀值,而阀值是对这个区域计算得来的。这样做的好处在于每个像素位置处的二值化阈值不是固定不变的,而是由其周围邻域像素的分布来决定的。亮度较高的图像区域的二值化阈值通常会较高,而亮度较低的图像区域的二值化阈值则会相适应地变小。不同亮度、对比度、纹理的局部图像区域将会拥有相对应的局部二值化阈值。常用的局部自适应阈值有:1)局部邻域块的均值;2)局部邻域块的高斯加权和。
自适应阈值化函数
cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst]) -> dst
其中:
- src参数表示输入图像(8位单通道图像)。
- maxValue参数表示使用 THRESH_BINARY 和 THRESH_BINARY_INV 的最大值。
- adaptiveMethod参数表示自适应阈值算法,有:
1)局部邻域块的均值 (ADAPTIVE_THRESH_MEAN_C)
2)局部邻域块的高斯加权和(ADAPTIVE_THRESH_GAUSSIAN_C)。 - thresholdType参数表示阈值类型,必须为THRESH_BINARY或THRESH_BINARY_INV的阈值类型。
- blockSize参数表示块大小(奇数且大于1,比如3,5,7… )。
- C参数是常数,表示从平均值或加权平均值中减去的数。 通常情况下,这是正值,但也可能为零或负值。阈值极为通过平均和高斯加权所计算的值在减去C。
代码实现局部(自适应)阈值化
import cv2 as cv
def local_adapt_threshold(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 5, 6)
cv.imshow("adapt_Mean", binary)
binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 5, 6)
cv.imshow("adapt_GAUSSIAN", binary)
src1 = cv.imread("book.jpg")
cv.imshow("bokk", src1)
local_adapt_threshold(src1)
cv.waitKey(0)
cv.destroyAllWindows()
自算阈值
可以通过计算灰度图的平均值作为阈值化的阈值等。
代码实现
def custom_threshold(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
mean = gray.mean()
print("mean:", mean)
ret, binary = cv.threshold(gray, mean, 255, cv.THRESH_BINARY)
print("阈值:%s" %ret)
cv.imshow("BINARY_Mean", binary)
src1 = cv.imread("book.jpg")
cv.imshow("bokk", src1)
custom_threshold(src1)
cv.waitKey(0)
cv.destroyAllWindows()
初学Opencv,如有错误地方和改进地方,真诚地邀请您提出来,谢谢!
本文结束…