目录

简单阈值

自适应阈值

Otsu's二值化


简单阈值

当像素值高于阈值时,我们给这个像素赋予一个新值(可能是白色),否则我们给它赋予另外一种颜色(也许是黑色)。用到了cv2.threshhold()函数。

第一个参数表示原图。原图应该是灰度图像。

第二个参数表示阈值。

第三个参数表示当像素高于阈值时赋予的新的像素值。

第四个参数阈值类型有四种:

  • cv2.THRESH_BINARY:二值阈值化,只要第三个参数不是0,像素值大于阈值时为白色,系小于阈值时是黑色。
  • cv2.THRESH_BINARY_INV:反向二值阈值化,与上一个参数相反
  • cv2.THRESH_TRUNC:截断阈值化,当像素点超过阈值时,为白色,不论第三个参数是什么值
  • cv2.THRESH_TOZERO:超过阈值被置0,第三个参数可以为任意值
  • cv2.THRESH_TOZERO_INV:低于阈值被置0,第三个参数可以为任意值

返回值:阈值,阈值后的图片,在以下例子中,ret表示阈值,thresh表示处理后的图片。

import cv2
import numpy as np
import matplotlib.pyplot as plt
img=cv2.imread('../data/image/8.png',0)
#二值化阈值
ret,thresh1=cv2.threshold(img,127,1,cv2.THRESH_BINARY)
#反向二值化阈值
ret,thresh2=cv2.threshold(img,127,1,cv2.THRESH_BINARY_INV)
#截断阈值化
ret,thresh3=cv2.threshold(img,127,0,cv2.THRESH_TRUNC)
#超过阈值被置为0
ret,thresh4=cv2.threshold(img,127,0,cv2.THRESH_TOZERO)
#低于阈值被置为0
ret,thresh5=cv2.threshold(img,127,0,cv2.THRESH_TOZERO_INV)
titles = ['InImage','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.xticks([]),plt.yticks([])
plt.show()

自适应阈值


在简单阈值中我们使用是全局阈值,整幅图像采用同一个数作为阈值。这种方法并不适应与所有情况,尤其是当同一幅图像上的不同部分的具有不同亮度时。这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。用到了cv2.adaptiveThreshold()函数。



 第一个参数表示原图像(灰度图像,8bit单通道)

第二个参数官方的解释是最大值,但是根据我的实现来看,只要不为0,不影响最后结果。

第三个参数表示阈值的计算方式:

  • cv2.ADPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平均值
  • cv2.ADPTIVE_THRESH_GAUSSIAN_C:阈值取值相邻区域的加权和,权重为一个高斯窗口

第四个参数表示阈值类型,参照简单阈值中的解释。

第五个参数表示邻域大小,即计算阈值的区域大小,一般是3,5,7,....

第六个参数表示常数,计算出阈值之后,要减去这个参数,才是最后的阈值。

例如:比较简单阈值和自适应阈值的差别


import cv2
import numpy as np
import matplotlib.pyplot as plt
img=cv2.imread('../data/image/9.png',0)
#简单阈值
ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
#11 为 Block size, 2 为 C 值
th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,2)
th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
titles = ['Original Image', 'Global Thresholding (v = 127)',
'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [img, th1, th2, th3]
for i in range(4):
    plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()

python阈值标准 python阀值_opencv




Otsu's二值化

在简单阈值中,我们随便设置了一个数来做阈值,如果效果不好,我们需要人为去调试这个阈值,那么对于双峰图像(直方图中存在两个峰),我们在两个峰之间的峰谷选择一个值作为阈值,这就是Otsu二值化需要做的,简单来说,就是对一幅双峰图像自动根据其直方图计算出一个阈值,注意,对于非双峰图像,结果可能不会很理想。用到的函数是cv2.threshold()

第一个参数表示输入图片(灰度图片)

第二个参数表示阈值,这里需要设置为0

第三个参数表示阈值类型,参照简单阈值,这里需要多传入一个参数cv2.THRESH_OTSU,具体使用方法参照下面的例子。

返回值:计算出的阈值,处理后的图片

例:输入一幅双峰图像,使用Otsu二值化对图像进行阈值处理。

import cv2
import numpy as np
import matplotlib.pyplot as plt
img=cv2.imread('../data/image/10.png',0)
# Otsu's thresholding
ret1,th1 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
titles = ['Original Noisy Image','Histogram',"Otsu's Thresholding",] # 这里使用了 pyplot 中画直方图的方法,plt.hist, 要注意的是它的参数是一维数组
#显示原图
plt.subplot(1,3,1),plt.imshow(img,'gray')
plt.title(titles[0]), plt.xticks([]), plt.yticks([])
#显示原图的直方图
plt.subplot(1,3,2),plt.hist(img.ravel(),256)
plt.title(titles[1]), plt.xticks([]), plt.yticks([])
#显示二值化后的图
plt.subplot(1,3,3),plt.imshow(th1,'gray')
plt.title(titles[2]), plt.xticks([]), plt.yticks([])
plt.show()

python阈值标准 python阀值_自适应_02