彩色图像:三个通道0-255,0-255,0-255,所以可以有2^24位空间 灰度图像:一个通道0-255,所以有256种颜色 二值图像:只有两种颜色,黑和白,1白色,0黑色
通常情况,我们一般不知道设定怎样的阈值thresh才能得到比较好的二值化效果,只能去试。如对于一幅双峰图像(理解为图像直方图中存在两个峰),我们指定的阈值应尽量在两个峰之间的峰谷。这时,就可以用第四个参数THRESH_OTSU,它对一幅双峰图像自动根据其直方图计算出合适的阈值(对于非双峰图,这种方法得到的结果可能不理想)。
对于双峰图,我们需要多传入一个参数cv2.THRESH_OTSU,并且把阈值thresh设为0,设置为其他数也默认为0,算法会找到最优阈值,并作为第一个返回值ret返回。
cv2.THRESH_BINARY:二进制阈值。把亮的处理成白色,暗的处理成黑色
cv2.THRESH_BINARY_INV:反二进制阈值。把亮的处理成黑色,暗的处理成白色
cv2.THRESH_TRUNC:截断阈值。亮的不能太亮,有上限,暗的不变
cv2.THRESH_TOZERO:threshold 阈值化为0,比较亮的部分不变,比较暗的部分处理成黑色为0
cv2.THRESH_TOZERO_INV:threshold 反阈值化为0,把比较亮的部分处理成0成黑色,小于等于阈值的像素点不变
cv2.THRESH_BINARY:二进制阈值。把亮的处理成白色,暗的处理成黑色
cv2.THRESH_BINARY_INV:反二进制阈值。把亮的处理成黑色,暗的处理成白色
cv2.THRESH_TRUNC:截断阈值。亮的不能太亮,有上限,暗的不变
cv2.THRESH_TOZERO:threshold 阈值化为0,比较亮的部分不变,比较暗的部分处理成黑色为0
cv2.THRESH_TOZERO_INV:threshold 反阈值化为0,把比较亮的部分处理成0成黑色,小于等于阈值的像素点不变
import cv2 as cv
import numpy as np
def threshold_demo(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
#ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)#cv.THRESH_OTSU计算阈值
#ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_TRIANGLE) # cv.THRESH_TRIANGLE计算阈值
#不同方法阈值不同,判断二值化的方法好坏 是看信息有没有丢失
#ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_BINARY) #手动指定阈值为127,大于127的是白色,小于127的是黑色
ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_BINARY_INV) #bin反 手动指定阈值为127,大于127的是黑色,小于127的是白色
ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_TRUNC) # 截断TRUNC, 大于的话直接变成127(截断)
ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_TOZERO) # 截断TRUNC, 大于的话直接变成保留,小于127的全变成0
print("threshold value %s" % ret)
cv.imshow("binary", binary)
src = cv.imread("C:/Users/lenovo/Desktop/opencv/daima/banknum/template-matching-ocr/images/lena.jpg") #读取图片位置
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
threshold_demo(src)
#local_demo(src)
#custom_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
print(“threshold value %s” % ret)
#打印阈值,前面先进行了灰度处理0-255,我们使用该阈值进行处理,低于该阈值的图像部分全为黑,高于该阈值则为白色
threshold value: 140.0 #获取的阈值是140
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_TRIANGLE)
threshold value: 67.0
ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_BINARY_INV)
反二进制阈值。把亮的处理成黑色,暗的处理成白色
threshold value: 127.0
ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_TRUNC)
截断阈值。亮的不能太亮,有上限,暗的不变
ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_TOZERO)
threshold 阈值化为0,比较亮的部分不变,比较暗的部分处理成黑色为0
OpenC的threshold函数进行全局阈值。其函数原型为:threshold(src, thresh, maxval, type[, dst]) -> retval, dst
src参数表示输入图像(多通道,8位或32位浮点)。
thresh参数表示阈值。
maxval参数表示与THRESH_BINARY和THRESH_BINARY_INV阈值类型一起使用设置的最大值。
type参数表示阈值类型。
retval参数表示返回的阈值。若是全局固定阈值算法,则返回thresh参数值。若是全局自适应阈值算法,则返回自适应计算得出的合适阈值。
dst参数表示输出与src相同大小和类型以及相同通道数的图像
cv2.threshold函数是有两个返回值的,第一个返回值,得到图像的阈值, 第二个返回值,也就是阈值处理后的图像,
cv.threshold(gray,0,255,cv.THRESH_BINARY | cv.THRESH_OTSU) #这是我们自己设置的
我们自己不一定能够找到一个最好的阈值,去二分化图像,所以我们需要算法自己去寻找一个阈值,而cv.THRESH_OTSU就可以满足这个需求去找到一个最好的阈值。 注意:他非常适用于图像灰度直方图具有双峰的情况, 他会在双峰之间找到一个值作为阈值,对于非双峰图像,可能并不是很好用。 因为cv.THRESH_OTSU方法会产生一个阈值,那么函数cv2.threshold的的第二个参数(设置阈值)就是0(None)了,并且在cv2.threshold的方法参数中还得加上语句cv2.THRESH_OTSU。
这里面第三个参数maxval参数表示与THRESH_BINARY和THRESH_BINARY_INV阈值类型一起使用设置的最大值。 而我们使用的灰度图像最大则为255,所以设置为255即可
ret, binary = cv.threshold(gray,0,255,cv.THRESH_BINARY | cv.THRESH_TRIANGLE)
THRESH_OTSU和THRESH_TRIANGLE和前面的说到的二值化方法组合使用,好处是不用自己指定thresh值,系统会进行计算并且作为返回值返回。区别是:THRESH_OTSU最适用于双波峰THRESH_TRIANGLE最适用于单个波峰,最开始用于医学分割细胞等
cv2.adaptiveThreshold()
ADAPTIVE_THRESH_MEAN_C :把图像分成一个个小的区域,每个区域做阈值处理,每个区域阈值为这个区域的均值减去常量c,大于阈值取白色,小于取黑色。整个图像有很多阈值。
ADAPTIVE_THRESH_GAUSSIAN_C:把图像分成一个个小的区域,阈值是每个区域均值的权重和(均值分布为高斯分布,越接近中心均值权重越高)再减去常量c,整个图像只有一个阈值
blocksize:区域大小,必须是奇数。
C: 二值化时,如何一个像素点减去均值大于C,才把这个点设为白色,能减弱噪声影响。等于说阈值=均值-C
import cv2 as cv
import numpy as np
def local_demo(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
#binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 25, 10)
binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 10)
#ADAPTIVE_THRESH_GAUSSIAN_C 换高斯
cv.imshow("binary", binary)
src = cv.imread("C:/Users/lenovo/Desktop/opencv/daima/banknum/template-matching-ocr/images/lena.jpg") #读取图片位置
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
#threshold_demo(src)
local_demo(src)
#custom_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()
def local_threshold(image): gray = cv.cvtColor(image,cv.COLOR_RGB2GRAY) #要二值化图像,要先进行灰度化处理 dst = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,25,10) cv.imshow(“local_threshold”, dst)
binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 10)
OpenCV的adaptiveThreshold函数进行局部阈值。函数原型为:adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst]) -> dst
src参数表示输入图像(8位单通道图像)。
maxValue参数表示使用 THRESH_BINARY 和 THRESH_BINARY_INV 的最大值. adaptiveMethod参数表示自适应阈值算法,平均 (ADAPTIVE_THRESH_MEAN_C)或高斯(ADAPTIVE_THRESH_GAUSSIAN_C)。
thresholdType参数表示阈值类型,必须为THRESH_BINARY或THRESH_BINARY_INV的阈值类型。
blockSize参数表示块大小(奇数且大于1,比如3,5,7… )。
C参数是常数,表示从平均值或加权平均值中减去的数。 通常情况下,这是正值,但也可能为零或负值。
在使用平均和高斯两种算法情况下,通过计算每个像素周围blockSize x blockSize大小像素块的加权均值并减去常量C即可得到自适应阈值。如果使用平均的方法,则所有像素周围的权值相同;如果使用高斯的方法,则每个像素周围像素的权值则根据其到中心点的距离通过高斯方程得到。
def custom_threshold(image):
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)#转换为灰度图
h, w = gray.shape[:2]#高宽
m = np.reshape(gray, [1, w*h])#将图像转换为1维数组,1行多列
mean = m.sum() / (w*h)#求均值,把均值作为阈值
print("mean : ", mean)
ret, binary = cv.threshold(gray, mean, 255, cv.THRESH_BINARY)
cv.imshow("binary", binary)
numpy的reshape函数是给数组一个新的形状而不改变其数据,函数原型:reshape(a, newshape, order=‘C’)
a参数表示需要重新形成的原始数组。
newshape参数表示int或int类型元组(tuple),若为(1, 3),表示生成的新数组是1行3列。
order参数表表示使用此索引顺序读取a的元素,并使用此索引顺序将元素放置到重新形成的数组中。 函数返回值:如果可能的话,这将是一个新的视图对象; 否则,它会成为副本。
注意:将图像转一维数组,转换维度要保证其size不变,newshape–>[行,列]一行n列,要保证其容量大小不变