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的几个定义:

image.png

通过实例来了解一下具体的操作:

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()

image.png

我们一次性将五种参数全部演示出来,方便对比,为了绘制多个图像,我们使用了plt.subplot()函数。

自适应阈值化

刚刚我们所讲述的,是一种最简单的阈值化的方法,也称为固定阈值,但是其局限性很大,现在我们做个实验,方便看出它的缺点,我们采用这张图片:

image.png

我们使用之前的方法:

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()

image.png

可以看到,处理之后的图像已经完全崩坏,没有办法再做下一步的处理。然而,这并不是个例,固定阈值化的缺点就是对暗亮程度不同的图片无法做到很好的处理。

现在我们将介绍自适应性二值化,相比于固定阈值的二值化处理,自适应阈值不需要确定一个固定的阈值,而是可以根据对应的自适应方法,通过图像的局部特征自适应的设定阈值,做出二值化处理。

先来了解一个函数:
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)

输出的第一幅图像为使用均值法得到的,第二个则为使用高斯法得到的:

image.png

image.png

可以看到,其效果要比固定阈值法好得多,而这种方法,我们会用与许多的例子,比如文档的OCR文字识别以及答题卡的判定等等,这些案例都会用到自适应性二值化对图像进行预处理,从而方便后期的操作。

当然,图像的阈值化不仅仅如此,下个教程我们将会讲述到图像阈值的其他方法,它们将更有实用性,且效果更好,但是相对应的,算法也相当的复杂。

posted @ 2021-12-07 13:44  wuyuan2011woaini  阅读(248)  评论(0编辑  收藏  举报