本节将学习简单阈值,自适应阈值,Otsu's二值化等
学习的函数有cv2.threshold,cv2.adaptiveThreshold等
1、简单阈值
函数原型:cv2.treshold(src,x,y,method)
src:原函数 ,应为灰度值 x:指对像素值进行分类的阈值 y:当像素高于(或者小于)阈值时会被赋予的新值
method:
cv2.THRESH_BINARY cv2.THRESH_BINARY cv2.THRESH_TRUNC cv2.THRESH_TOZERO cv2.THRESH_TOZERO_INV
代码:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img=cv2.imread('C:\\Users\\WLX\\Desktop\\15.png',0)
ret,thresh1=cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret,thresh2=cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3=cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret,thresh4=cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
ret,thresh5=cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)
titles=['oringinal Image' ,'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()
结果:
2、自适应阈值
整幅图像用同一个阈值这种方法并不适用所有情况,尤其当同一副图像上的不同部分具有不同的亮度时。这种情况我们需要采用自适应阈值。因此在同一副图像上的不同区域采用不同的阈值。
函数原型:
dst = cv2.adaptiveThreshold(src, maxval, thresh_type, type, Block Size, C)
- src: 输入图,只能输入单通道图像,通常来说为灰度图
- dst: 输出图
- maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
- thresh_type: 阈值的计算方法,包含以下2种类型:cv2.ADAPTIVE_THRESH_MEAN_C; cv2.ADAPTIVE_THRESH_GAUSSIAN_C.
- type:二值化操作的类型,与固定阈值函数相同,但仅包含以下2种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV
- Block Size: 图片中分块的大小,用来计算阈值的像素邻域大小:3,5,7
- C :阈值计算方法中的常数项
自适应阈值: 对方法CV_ADAPTIVE_THRESH_MEAN_C,先求出块中的均值,再减掉C。
对方法 CV_ADAPTIVE_THRESH_GAUSSIAN_C ,先求出块中的加权和(gaussian), 再减掉C。
参见 点击打开链接
代码:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img=cv2.imread('C:\\Users\\WLX\\Desktop\\7.jpg',0)
ret,th1=cv2.threshold(img,127,255,cv2.THRESH_BINARY)
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()
结果:
3、Otsu's二值化
当处理双峰图像时,我们使用Otsu二值化。它对一副双峰图像自动根据直方图计算一个阈值。(对于非双峰图像这种方法并不适用)
这里会用到cv2.threshold(),但需要传入一个参数(flag),cv2.THRESH_OTSU。这里把阈值设为0.然后算法会找到最优阈值,这个最优阈值返回值retVal。如果不适用Otsu二值化,返回的retVal值与设定的阈值相等。
下面的例子中,输入图像是一副带有噪声的图像,第一种方法,我们设127为全局阈值。第二种方法,我们直接使用Otsu二值化。第三种方法,我们首先用一个5x5的高斯核除去噪声,然后再使用Otsu二值化。
代码:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img=cv2.imread('C:\\Users\\WLX\\Desktop\\16.png',0)
ret1,th1=cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret1,th2=cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
blur=cv2.GaussianBlur(img,(5,5),0)
ret3,th3=cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
images=[img,0,th1,img,0,th2,blur,0,th3]
titles=['Original Noisy Image','Histogram','Global Thresholding(v=127)','Original Noisy Image','Histogram','Otus s Thresholding','Gaussian giltered Image','Histogram','Otsu s Thresholding']
for i in range(3):
plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')
plt.title(titles[i*3]),plt.xticks([]),plt.yticks([])
plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256)
plt.title(titles[i*3+1]),plt.xticks([]),plt.yticks([])
plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray')
plt.title(titles[i*3+2]),plt.xticks([]),plt.yticks([])
plt.show()
结果: