opencv⼆值化的cv2.threshold函数
(⼀)简单阈值
简单阈值当然是最简单,选取⼀个全局阈值,然后就把整幅图像分成了⾮⿊即⽩的⼆值图像了。函数为cv2.threshold()
这个函数有四个参数,第⼀个原图像,第⼆个进⾏分类的阈值,第三个是⾼于(低于)阈值时赋予的新值,第四个是⼀个⽅法选择参数,常⽤的有:
• cv2.THRESH_BINARY(⿊⽩⼆值)
• cv2.THRESH_BINARY_INV(⿊⽩⼆值反转)
• cv2.THRESH_TRUNC (得到的图像为多像素值)
• cv2.THRESH_TOZERO
• cv2.THRESH_TOZERO_INV
该函数有两个返回值,第⼀个retVal(得到的阈值值(在后⾯⼀个⽅法中会⽤到)),第⼆个就是阈值化
后的图像。
⼀个实例如下:
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('C:\\Users\\Administrator\\Desktop\\image\\ll.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh1 = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(gray,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3 = cv2.threshold(gray,127,255,cv2.THRESH_TRUNC)
ret,thresh4 = cv2.threshold(gray,127,255,cv2.THRESH_TOZERO)
ret,thresh5 = cv2.threshold(gray,127,255,cv2.THRESH_TOZERO_INV)
titles = ['img','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img,thresh1,thresh2,thresh3,thresh4,thresh5]
for i in range(6):
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.show()
可以看到这⾥把阈值设置成了127,对于BINARY⽅法,当图像中的灰度值⼤于127的重置像素值为255.
(⼆)⾃适应阈值:
前⾯看到简单阈值是⼀种全局性的阈值,只需要规定⼀个阈值值,整个图像都和这个阈值⽐较。⽽⾃适应阈值可以看成⼀种局部性的阈值,通过规定⼀个区域⼤⼩,⽐较这个点与区域⼤⼩⾥⾯像素点的平均值(或者其他特征)的⼤⼩关系确定这个像素点是属于⿊或者⽩(如果是⼆值情况)。使⽤的函数为:cv2.adaptiveThreshold()
该函数需要填6个参数:
第⼀个原始图像
第⼆个像素值上限
第三个⾃适应⽅法Adaptive Method:
c++trunc函数— cv2.ADAPTIVE_THRESH_MEAN_C :领域内均值
—cv2.ADAPTIVE_THRESH_GAUSSIAN_C :领域内像素点加权和,权重为⼀个⾼斯窗⼝
第四个值的赋值⽅法:只有cv2.THRESH_BINARY 和cv2.THRESH_BINARY_INV
第五个Block size:规定领域⼤⼩(⼀个正⽅形的领域)
第六个常数C,阈值等于均值或者加权值减去这个常数(为0相当于阈值就是求得领域内均值或者加权值)
这种⽅法理论上得到的效果更好,相当于在动态⾃适应的调整属于⾃⼰像素点的阈值,⽽不是整幅图像都⽤⼀个阈值。
⼀个实例如下:
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('C:\\Users\\Administrator\\Desktop\\image\\ll.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,th1 = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
th2 = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,\
cv2.THRESH_BINARY,11,2) #换⾏符号 \
th3 = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
cv2.THRESH_BINARY,11,2) #换⾏符号 \
images = [gray,th1,th2,th3]
plt.figure()
for i in range(4):
plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
plt.show()
可以看到上述窗⼝⼤⼩使⽤的为11,当窗⼝越⼩的时候,得到的图像越细。想想⼀下,如果把窗⼝设置⾜够⼤以后(不能超过图像⼤⼩),那么得到的结果可能就和第⼆幅图像的相同了。
(三)Otsu’s⼆值化
我们前⾯说到,cv2.threshold函数是有两个返回值的,前⾯⼀直⽤的第⼆个返回值,也就是阈值处理后的图像,那么第⼀个返回值(得到图像的阈值)将会在这⾥⽤到。
前⾯对于阈值的处理上,我们选择的阈值都是127,那么实际情况下,怎么去选择这个127呢?有的图像
可能阈值不是127得到的效果更好。那么这⾥我们需要算法⾃⼰去寻到⼀个阈值,⽽Otsu’s就可以⾃⼰到⼀个认为最好的阈值。并且Otsu’s⾮常适合于图像灰度直⽅图具有双峰的情况,他会在双峰之间到⼀个值作为阈值,对于⾮双峰图像,可能并不是很好⽤。那么经过Otsu’s得到的那个阈值就是函数
cv2.threshold的第⼀个参数了。因为Otsu’s⽅法会产⽣⼀个阈值,那么函数cv2.threshold的的第⼆个参数(设置阈值)就是0了,并且在
cv2.threshold的⽅法参数中还得加上语句cv2.THRESH_OTSU。那么什么是双峰图像(只能是灰度图像才有),就是图像的灰度统计图中可以明显看出只有两个波峰,⽐如下⾯⼀个图的灰度直⽅图就可以是双峰图:
好了现在对这个图进⾏Otsu’s阈值处理就⾮常的好,通过函数cv2.threshold会⾃动到⼀个介于两波峰之间的阈值。⼀个实例如下:import cv2
import matplotlib.pyplot as plt
img = cv2.imread('C:\\Users\\Administrator\\Desktop\\image\\ll.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#简单滤波
ret1,th1 = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
#Otsu 滤波
ret2,th2 = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
print(ret2)
plt.figure()
plt.subplot(221),plt.imshow(gray,'gray')
plt.subplot(222),plt.hist(gray.ravel(),256)#.ravel⽅法将矩阵转化为⼀维
plt.subplot(223),plt.imshow(th1,'gray')
plt.subplot(224),plt.imshow(th2,'gray')
print(ret2) 得到的结果为144。可以看出似乎两个结果并没有很明显差别,主要是两个阈值(127与144)太相近了,如果这两个隔得很远那么会很明显的。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。