发现40例这本书需要结合作者的才能将更好的学习OpenCV,这篇开始开始图像阈值的学习。
阈值是图像处理的重要概念,类似一个"像素值的标准线"。所有的像素点和这个标准线进行比对,最终是或大或小或相等。程序根据这些结果将所有的像素进行分组,然后对某一组的像素值进行"加深"或"变浅"操作,使得整个图像的轮廓更加鲜明,更容易被计算机或者肉眼识别。阈值处理可以有效得处理前景和背景的分离等功能。这里主要介绍简单阈值处理、自适应阈值处理,Otsu阈值处理。
简单阈值处理(固定阈值)
OpenCV提供了threshold()函数进行阈值化处理。
函数语法说明: retval,dst = cv2.threshold( src,thresh,maxval,type )
类型 |
中文名 |
定义 |
cv2.THRESH_BINARY |
二值化阈值处理 |
dst( x,y ) = src( x,y ) > thresh ? maxval : 0 |
cv2.THRESH_BINARY_INV |
反二值化阈值处理 |
dst( x,y ) = src( x,y ) > thresh ? 0 : maxval |
cv2.THRESH_TRUNC |
截断阈值化处理 |
dst( x,y ) = src( x,y ) > thresh ? thresh : 0 |
cv2.THRESH_TOZERO_INV |
超阈值零处理 |
dst( x,y ) = src( x,y ) > thresh ? 0 : src( x,y ) |
cv2.THRESH_TOZERO |
低阈值零处理 |
dst( x,y ) = src( x,y ) > thresh ? src( x,y ) : 0 |
cv2.THRESH_MASK |
掩码处理 |
掩码 |
cv2.THRESH_OTSU |
最佳阈值处理 |
标记,使用Otsu算法时的可选阈值参数 |
cv2.THRESH_TRIANGLE |
三角形阈值处理 |
标记,使用Triangle算法时的可选阈值参数 |
threshold()提供的阈值处理方法是针对整个图像的像素点进行的统一处理方法,并且阈值是自己设定,根据type的不一样阈值处理也不一样。
dst( x,y ) = src( x,y ) > thresh ? maxval : 0
像素点大于阈值则像素点像素变为设定最大值,否则置为0,最终得到一个只有0和maxval的二值图。
dst( x,y ) = src( x,y ) >thresh ? 0 : maxval
像素点大于阈值则像素点像素变为0,否则设置为设定最大值,与上面恰好相反,最终也得到一个只有0和maxval二值图。
dst( x,y ) = src( x,y ) >thresh ? thresh : 0
像素点大于阈值则像素值设为阈值,否则设置为0,最终得到一个只有0和阈值thresh的二值图
dst( x,y ) = src( x,y )> thresh ? 0 : src( x,y )
像素点大于阈值则像素点设为0,否则不变,最终图像中没有大于阈值的像素点(这些像素点变为0了)
dst( x,y ) = src( x,y ) > thresh ? src( x,y ) : 0
像素点大于阈值则像素点不变,否则设为0,最终图像中小于阈值的像素点像素都变成0了
程序如下:
color_0_255 = cv.imread("0_255.png", 0) # 灰度图像素带
r, b1 = cv2.threshold(color_0_255, 127, 255, cv2.THRESH_BINARY) # 二进制阈值化:比阈值大设为最大值,否则为0
r, b2 = cv2.threshold(color_0_255, 127, 255, cv2.THRESH_BINARY_INV) # 反二进制阈值化:比阈值大设为0,否则为最大值
r, b3 = cv2.threshold(color_0_255, 127, 255, cv2.THRESH_TRUNC) # 截断阈值化:比阈值大的都设置成阈值
r, b4 = cv2.threshold(color_0_255, 127, 255, cv2.THRESH_TOZERO) # 反阈值化为0:大于阈值的为0
r, b5 = cv2.threshold(color_0_255, 127, 255, cv2.THRESH_TOZERO_INV) # 阈值化为0:小于阈值则设为0
cv.imshow("orginal 0~255", color_0_255)
cv.imshow("BINARY", b1)
cv.imshow("BINARY_INV", b2)
cv.imshow("TRUNC", b3)
cv.imshow("TOZERO", b4)
cv.imshow("TOZERO_INV", b5)
cv.waitKey()
cv.destroyAllWindows()
程序运行如下:
对于色彩均衡的图像一个阈值就能完成图像的阈值化处理,但对于色彩不均衡的图像,只用一个阈值就无法得到清晰有效的阈值分割图像,于是有了自适应阈值处理方法。
自适应阈值处理适合明暗差异较大的图像,通过计算每个像素点周围临近区域的加权平均值获得阈值,并使用该阈值对当前的像素点进行处理,这样整个过程就是使用变化的阈值进行图像的阈值处理。
函数语法说明: dst = cv2.adaptiveThreshold( src,maxValue,adaptiveMethod,thresholdType,blockSize,C )
自适应阈值等于各个像素由参数blockSize所指定的邻域的加权平均值减去常量C, 邻域的各个点的权重由adaptiveMethon来决定。
adaptiveMethon包括以下参数:
程序如下:
import cv2
image_Gray = cv2.imread("boy.png", 0)
t1, thresh_img = cv2.threshold(image_Gray, 127, 255, cv2.THRESH_BINARY)
# 自适应阈值的计算方法为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("image_gray", image_Gray)
cv2.imshow("shreshold_img", thresh_img)
cv2.imshow("MEAN_C", athdMEAM)
cv2.imshow("GAUSSIAN_C", athdGAUS)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果如下:
针对简单阈值处理设定阈值的一刀切处理方式,大概率设置的阈值不是最优的阈值,得到的处理后图像往往也不是最优的待处理图像。
Otsu阈值处理方式是在cv2.threshold()的type中选择cv2.THRESH_OTSU,同时,设置的阈值也需要改为0,这样此方法会遍历所有可能的阈值,从而找出最佳的阈值并进行阈值分割处理。
程序如下:
import cv2
image_Gray = cv2.imread("p1.png", 0)
t1, thresh_img_127 = cv2.threshold(image_Gray, 127, 255, cv2.THRESH_BINARY)
print(t1) # 127
t2, thresh_otsu = cv2.threshold(image_Gray, 0, 255, cv2.THRESH_OTSU)
print(t2) # 149
cv2.imshow("image_gray", image_Gray)
cv2.imshow("thresh_img_127", thresh_img_127)
cv2.imshow("thresh_otsu", thresh_otsu)
cv2.waitKey()
cv2.destroyAllWindows()
程序运行如下:
otsu的方法确实比默认设定的127好一些,但是,最好的感觉还是自适应阈值处理。