阈值化
阈值化图像其实就是对灰度图像进行二值化操作,根本原理是利用设定的阈值判断图像像素为0还是255,所以在图像二值化中阈值的设置很重要。图像的二值化分为全局二值化和局部二值化,其区别在于阈值是否在一张图像进行统一。
全局阈值化
全局阈值法方法就是将图像中低于某个阈值的像素设置为黑色(0),而其他的设置为白色(255)。全局固定阈值很容易理解,就是对整幅图像都是用一个统一的阈值来进行二值化
全局阈值化函数
cv2.threshold(src, thresh, maxval, type[, dst]) -> retval, dst
其中:
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
其中:
代码实现局部(自适应)阈值化
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,如有错误地方和改进地方,真诚地邀请您提出来,谢谢!
本文结束…