目标
学习简单阈值处理(cv2.threshold)和自适应阈值处理(cv2.adaptiveThreshold),大津二值化处理(otus's thresholding)
简单阈值处理(cv2.threshold(img,thresholding,replace_value,threshold_method))
在这里,问题是很简单的。如果像素的值大于设定的阈值(因为处理的是灰度图,因而图像是只有一个通道,每个像素的像素值代表该像素的颜色深度,取值从0-255),那么该像素就会被用设定的替代值给替代,如果小于阈值就会被指定成另外一个颜色(不知道为什么只有一个replace_value,但是用了几次都发现这个不能自己设定的值是黑色)。函数的第一个参数是源图像,必须是灰度图。第二个参数就是要设定的阈值A,用于区分像素值。第三个参数是要替换的像素值B。函数会遍历所有的像素点,对每一个像素点,如果它的像素值大于A(文档里面说有时候是小于,我不知道这个怎么设置小于的时候生效),那么就把它重新设置为B,小于A的话就设定为黑色(我也不知道为啥)。对于阈值处理方法,opencv提供了五种类型:
cv2.THRESH_BINARY
cv2.THRESH_BINARY_INV
cv2.THRESH_TRUNC
cv2.THRESH_TOZERO
cv2.THRESH_TOZERO_INV
函数返回两个输出值,就是ret,img_threshold=cv2.threshold(img,thresholding,replace_value,threshold_method)
在没有启用大津二值化的时候,第一个返回值是没有用的,仅仅是你设置的thresholding的值(大津二值化在下文)。第二个返回值就是阈值处理后的图像(一个二维的numpy数组)。
下面是一个例子:
import cv2
import numpy
import matplotlib.pyplot as plt
#导入库
img=cv2.imread('E:/p.jpg',0)
#读入图像,以灰度图存储ret,img_threshold_BINARY=cv2.threshold(img,177,255,cv2.THRESH_BINARY)
ret_1,img_threshold_THRESH_BINARY_INV=cv2.threshold(img,177,255,cv2.THRESH_BINARY_INV)
ret_2,img_threshold_THRESH_TRUNC=cv2.threshold(img,177,255,cv2.THRESH_TRUNC)
ret_3,img_threshold_THRESH_THRESH_TOZERO=cv2.threshold(img,177,255,cv2.THRESH_TOZERO)
ret_4,img_threshold_THRESH_THRESH_THRESH_TOZERO_INV=cv2.threshold(img,177,255,cv2.THRESH_TOZERO_INV)
# 分别进行五种阈值处理
title=[
'img',
'BINARY',
'BINARY_INV',
'TRUNC', 'TOZERO',
'TOZERO_INV'
]
pic=[
img,
img_threshold_THRESH_BINARY,
img_threshold_THRESH_BINARY_INV,
img_threshold_THRESH_TRUNC,
img_threshold_THRESH_TOZERO,
img_threshold_THRESH_TOZERO_INV
]
for i in range(6):
plt.subplot(2,3,i+1),plt.imshow(pic[i],'gray')
#由于matplot的图像存储通道顺序是RGB,opencv存储图像的方式是BGR,用‘gray’可以以灰度图显示
plt.title(title[i])
plt.show()

关于五种阈值处理的方法,我去搜了一下,自己总结了一下。
cv2.THRESH_BINARY:当像素值小于设定的阈值的时候,设定像素值为0,否则设定为预先设定的值
cv2.THRESH_BINARY_INV:当像素值小于设定的阈值的时候,设定像素值为预先设定的值,否则设定为0,和第一种方法的像素设定类似
cv2.THRESH_TRUNC:像素值如果大于阈值,那么就以阈值赋值给像素值。小于阈值的部分保留原始像素值不变
cv2.THRESH_TOZERO:像素值如果小于阈值,那么就以0赋值给像素值,否则保持原来的像素值
cv2.THRESH_TOZERO_INV:像素值如果大于阈值,那么就以以0赋值给像素值,否则保持原来的像素值不变。
自适应阈值处理
cv2.adaptiveThreshold(img,replace_value,type_of_mean,threshold_type,C,size_of_matrix)
在简单阈值处理中,我们使用一个全局量作为阈值检测的标准。但是当图像的不同部分有不同亮度(比如随手拍摄的照片),这个阈值标准就不是那么好用了。在这种情况下,我们使用一个自动的阈值。算法会根据图像的性质计算一个最合适的阈值,因而对于图像的不同部位会有不同的阈值,这样处理的图像会有更好的结果。根据阈值的计算方法的不同,有两个取均值的方法,对应于参数:type_of_mean:
cv2.ADAPTIVE_THRESH_MEAN_C : 阈值是周围像素值的均值 cv2.ADAPTIVE_THRESH_GAUSSIAN_C : 根据像素周围的高斯矩阵得到的高斯均值 矩阵规模-决定了像素相邻矩阵的规模 (高斯矩阵就是根据像素周围的其他像素离它的远近进行加权平均,越近的像素点的权值越高)
img:源图像
the_other_value:要替换的阈值,也就是当像素值符合阈值标准的时候,像素值的取值
tyoe_of_mean:就是取阈值的方法
threshold_method:同上面的简单阈值处理的参数
C:在取阈值标准的时候在矩阵中要减去的像素值,也就是偏移量
size_of_matrix:矩阵的规模,会影响最终处理的结果的噪声值。
个人觉得自适应的阈值处理在拍摄照片的二值化处理中比简单阈值处理好用。
大津二值化
在简单阈值处理中,返回的第一个参数没有太大的意义。但是当我们加上大津二值化的额外参数之后,那个无用的返回值就有用了。
对于双峰图(就是像素条形图中出现两条峰值的图像),我们会自动使用双峰的均值作为阈值检测的标准。但是对于非双峰图,这个大津二值化不会生效。
要使用大津二值化,就是使用简单阈值处理,但是加上一个额外的参数:cv2.THRESH_OTSU,而原先的阈值标准只要简单地设置为0就行。