第三章-OpenCV基础-9-图像阈值

前置内容

发现40例这本书需要结合作者的才能将更好的学习OpenCV,这篇开始开始图像阈值的学习。

阈值是图像处理的重要概念,类似一个"像素值的标准线"。所有的像素点和这个标准线进行比对,最终是或大或小或相等。程序根据这些结果将所有的像素进行分组,然后对某一组的像素值进行"加深"或"变浅"操作,使得整个图像的轮廓更加鲜明,更容易被计算机或者肉眼识别。阈值处理可以有效得处理前景和背景的分离等功能。这里主要介绍简单阈值处理、自适应阈值处理,Otsu阈值处理。

简单阈值处理(固定阈值)

OpenCV提供了threshold()函数进行阈值化处理。

函数语法说明: retval,dst = cv2.threshold( src,thresh,maxval,type )

  • retval : 返回的阈值
  • dst : 返回处理后的图像,大小类型与原始图像等同
  • 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的不一样阈值处理也不一样。

  • THRESH_BINARY ---- 二值化阈值处理

dst( x,y ) = src( x,y ) > thresh ? maxval : 0

像素点大于阈值则像素点像素变为设定最大值,否则置为0,最终得到一个只有0和maxval的二值图。

  • THRESH_BINARY_INV ---- 反二值化阈值处理

dst( x,y ) = src( x,y ) >thresh ? 0 : maxval

像素点大于阈值则像素点像素变为0,否则设置为设定最大值,与上面恰好相反,最终也得到一个只有0和maxval二值图。

  • THRESH_TRUNC ---- 截断阈值化处理

dst( x,y ) = src( x,y ) >thresh ? thresh : 0

像素点大于阈值则像素值设为阈值,否则设置为0,最终得到一个只有0和阈值thresh的二值图

  • THRESH_TOZERO_INV ---- 超阈值零处理

dst( x,y ) = src( x,y )> thresh ? 0 : src( x,y )

像素点大于阈值则像素点设为0,否则不变,最终图像中没有大于阈值的像素点(这些像素点变为0了)

  • THRESH_TOZERO ---- 低阈值零处理

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 )

  • dst : 自适应阈值的处理结果
  • src : 原始图像,必须是8位单通道的图像
  • maxValue : 最大值
  • adaptiveMethon : 自适应方法,cv2.ADAPTVIVE_THRESH_MEAN_C或cv2.ADAPTIVE_THRESH_GAUSSIAN_C
  • thresholdType : 阈值处理方式,必须是cv2.THRESH_BINARY或者cv2.THRESH_BINARY_INV
  • blockSize : 块大小,标识一个像素在计算阈值时所使用的邻域尺寸,通常为3/5/7
  • C : 常量

自适应阈值等于各个像素由参数blockSize所指定的邻域的加权平均值减去常量C, 邻域的各个点的权重由adaptiveMethon来决定。

adaptiveMethon包括以下参数:

  • cv2.ADAPTVIVE_THRESH_MEAN_C : 邻域所有像素点的权重值一致
  • cv2.ADAPTIVE_THRESH_GAUSSIAN_C : 领域所有像素点的权重值与中心点的距离有关,通过高斯方程得到各个点的权重值

程序如下:

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阈值处理

针对简单阈值处理设定阈值的一刀切处理方式,大概率设置的阈值不是最优的阈值,得到的处理后图像往往也不是最优的待处理图像。

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好一些,但是,最好的感觉还是自适应阈值处理。

猜你喜欢

转载自blog.csdn.net/sunguanyong/article/details/129352721