OpenCV-Python系列之图像阈值
自本教程开始,我们已经进入了图像处理的一些基本操作的学习,所谓的图像阈值,就是图像二值化,什么是二值化,就是只有0和1,没有其他的。在OpenCV的图像里面,二值化表示图像的像素为0和255,并没有其他的值,它跟灰度化并不同。然而要想实现二值化,就最好先对图像进行灰度化处理,因为我们需要的图像不能具备GBR三元通道。
简单阈值
我们先来看函数原型:
ret, dst = cv2.threshold(src, thresh, maxval, type)
src: 输入图,只能输入单通道图像,通常来说为灰度图
dst: 输出图
thresh: 阈值
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
type:二值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV
该函数返回两个值,但通常情况下我们只使用第二个值,第二个代表二值化之后的图像。
我们来看一下type的几个定义:
通过实例来了解一下具体的操作:
import cv2 as cv import numpy as np from matplotlib import pyplot as plt img = cv.imread("cat.jpg",0) ret,thresh1 = cv.threshold(img,127,255,cv.THRESH_BINARY) ret,thresh2 = cv.threshold(img,127,255,cv.THRESH_BINARY_INV) ret,thresh3 = cv.threshold(img,127,255,cv.THRESH_TRUNC) ret,thresh4 = cv.threshold(img,127,255,cv.THRESH_TOZERO) ret,thresh5 = cv.threshold(img,127,255,cv.THRESH_TOZERO_INV) titles = ['Original 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()
我们一次性将五种参数全部演示出来,方便对比,为了绘制多个图像,我们使用了plt.subplot()函数。
自适应阈值化
刚刚我们所讲述的,是一种最简单的阈值化的方法,也称为固定阈值,但是其局限性很大,现在我们做个实验,方便看出它的缺点,我们采用这张图片:
我们使用之前的方法:
import cv2 as cv img = cv.imread("text.png",0) ret,thresh1 = cv.threshold(img,127,255,cv.THRESH_BINARY) cv.imshow("res",thresh1) cv.waitKey(0) cv.destroyAllWindows()
可以看到,处理之后的图像已经完全崩坏,没有办法再做下一步的处理。然而,这并不是个例,固定阈值化的缺点就是对暗亮程度不同的图片无法做到很好的处理。
现在我们将介绍自适应性二值化,相比于固定阈值的二值化处理,自适应阈值不需要确定一个固定的阈值,而是可以根据对应的自适应方法,通过图像的局部特征自适应的设定阈值,做出二值化处理。
先来了解一个函数:
dst=cv.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst])
src:待二值化的图像,图像只能是CV_8UC1数据类型。
dst:二值化后的图像,与输入图像具有相同的尺寸、数据类型。
maxValue:二值化的最大值。
adaptiveMethod:自制应确定阈值的方法,分为均值法ADAPTIVE_THRESH_MEAN_C和高斯法ADAPTIVE_THRESH_GAUSSIAN_C这两种。
thresholdType:选择图像二值化方法的标志,只能是THRESH_BINARY和THRESH_BINARY_INV。
blockSize:自适应确定阈值的像素邻域大小,一般为3,5,7的奇数。
C:从平均值或者加权平均值中减去的常数,可以为正,也可以为负。
函数支持两种自适应方法,即ADAPTIVE_THRESH_MEAN_C(平均)和ADAPTIVE_THRESH_GAUSSIAN_C(高斯)。在两种情况下,自适应阈值T(x, y)。通过计算每个像素周围bxb大小像素块的加权均值并减去常量C得到。其中,b由blockSize给出,大小必须为奇数;如果使用平均的方法,则所有像素周围的权值相同;如果使用高斯的方法,则(x,y)周围的像素的权值则根据其到中心点的距离通过高斯方程得到。
我们来看一下代码实例:
import cv2 as cv import matplotlib.pyplot as plt img = cv.imread('text.png',0) # 自适应阈值 th2 = cv.adaptiveThreshold( img, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 15, 4) th3 = cv.adaptiveThreshold( img, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 15, 8) cv.imshow("th2",th2) cv.imshow("th3",th3) cv.waitKey(0)
输出的第一幅图像为使用均值法得到的,第二个则为使用高斯法得到的:
可以看到,其效果要比固定阈值法好得多,而这种方法,我们会用与许多的例子,比如文档的OCR文字识别以及答题卡的判定等等,这些案例都会用到自适应性二值化对图像进行预处理,从而方便后期的操作。
当然,图像的阈值化不仅仅如此,下个教程我们将会讲述到图像阈值的其他方法,它们将更有实用性,且效果更好,但是相对应的,算法也相当的复杂。