图像二值化就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果。将所有灰度大于或等于阈值的像素被判定为属于特定物体,其灰度值为255表示,否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。下面详细介绍图像二值化过程。
阈值设定分为:
1.全局性质的阈值(又分为简单阈值和自适应阈值)
2.局部性质的阈值(Otsu's二值化)
首先,用设置阈值的图像都必须是灰度图像。其次,在设置简单阈值和Otsu's二值化时,使用cv2.threshold()函数。而在设置自适应阈值时,使用cv2.adaptiveThreshold()函数。
cv2.threshold()函数,它有四个输入,第一个是原图像(必须为灰度图),第二个是阈值,第三个是高于(低于)阈值赋予的新的像素,第四个是选择性参数:
cv2.THRESH_BINARY(黑白二值)
cv2.THRESH_BINARY_INV(黑白二值反转)
cv2.THRESH_TRUNC (得到的图像为多像素值)
cv2.THRESH_TOZERO(黑灰二值)
cv2.THRESH_TOZERO_INV(黑灰二值反转)
该函数有两个返回值,第一个ret值(得到的阈值值),第二个th值就是阈值化后的图像。
cv2.adaptiveThreshold() 函数,它有六个参数:
第一个原始图像
第二个像素值上限
第三个自适应方法Adaptive Method:
cv2.ADAPTIVE_THRESH_MEAN_C :领域内均值
cv2.ADAPTIVE_THRESH_GAUSSIAN_C :领域内像素点加权和,权重为一个高斯窗口
第四个值的赋值方法:只有cv2.THRESH_BINARY 和cv2.THRESH_BINARY_INV
第五个Block size:规定领域大小(一个正方形的领域)
第六个常数C,阈值等于均值或者加权值减去这个常数(为0相当于阈值,就是求得领域内均值或者加权值)
Otsu's二值化:
这是一个更加适合于图像灰度直方图具有双峰的情况,他会在双峰之间找到一个值作为阈值,对于非双峰图像,可能并不是很好用。那么经过Otsu’s得到的那个阈值就是函数cv2.threshold的第一个参数了。因为Otsu’s方法会产生一个阈值,那么函数cv2.threshold的的第二个参数(设置阈值)就是0了,并且在cv2.threshold的方法参数中还得加上语句cv2.THRESH_OTSU。
# 下面就是对以上三种设置阈值方式的一个例子
import cv2
import matplotlib.pyplot as plt
img = cv2.imread("DLS.jpg", 0)
img = cv2.medianBlur(img, 5)
ret1, th1 = cv2.threshold(img, 127, 225, cv2.THRESH_BINARY)
ret2, th_1 = cv2.threshold(img, 0, 225, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
print ret2
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", "Otsu Thresholding", "Histogram"]
images = [img, th1, th2, th3, th_1, ret2]
for i in xrange(6):
plt.subplot(3,2,i+1)
if i < 5:
plt.imshow(images[i], "gray")
plt.xticks([]), plt.yticks([])
if i == 5:
plt.hist(img.ravel(), 256)
plt.title(titles[i])
plt.savefig("Threshold_image")
从上图可以清楚的看出使用Otsu‘s是最好的区别了前景和背景,但是,这也不是绝对,个人觉得算法没有好坏,只有合适不合适还有参数设置是否最佳。针对不同的图像,可能得到的效果不一致。