自适应阈值处理可以使用变化的阈值完成对图像的处理,能够更好地处理明暗差异较大的图像。Otsu方法可以根据当前图像给出最佳的类间分割阈值。
自适应阈值处理
对于色彩不均衡的图像,只使用一个阈值,就无法得到清晰有效的阈值分割结果图像。自适应阈值处理的方式通过计算像素点周围临近区域的加权平均值获得阈值,并使用该阈值对当前像素点进行处理。
OpenCV中提供了函数cv2.adaptiveThreshold()
来实现自适应阈值处理。
dst = cv2.adaptiveThreshold(src, maxValue, apaptiveMethod, thresholdType, blockSize, C)
- dst代表自适应阈值处理结果
- src代表要处理的原始图像。该图像必须是8位单通道的图像
- maxValue代表最大值
- adaptiveMethod代表自适应方法
- thresholdType代表阈值处理方法,该值必须是
cv2.THRESH_BINARY
或者cv2.THRESH_BINARY_INV
中的一个 - blockSize代表块的大小,表示一个像素在计算其阈值时所使用的领域尺寸,通常为3、5、7
- C位常量
adaptiveMethod代表自适应方法,有两种方法:
- cv2.ADAPTIVE_THRESH_MEAN_C : 邻域所有像素点的权重值是一致的
- cv2.ADAPTIVE_THRESH_GAUSSIAN_C : 与临域各像素点到中心点的距离有关,通过高斯方程得到各个点的权重值
例:对一幅图像分别使用二值化阈值函数cv2.threshold()
和自适应阈值函数cv2.adaptiveThreshold()
进行处理,观察结果的差异。
import cv2
img = cv2.imread('jisuanqi.png', 0)
t, rst = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
ADAPTIVEMEAN = cv2.adaptiveThreshold(
img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 5, 3)
ADAPTIVEGAUS = cv2.adaptiveThreshold(
img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 5, 3)
cv2.imshow('IMG', img)
cv2.imshow('RST', rst)
cv2.imshow('ADAPTIVEMEAN', ADAPTIVEMEAN)
cv2.imshow('ADAPTIVEGAUS', ADAPTIVEGAUS)
cv2.waitKey()
Otsu处理
Otsu方法能够根据当前图像给出最佳的类间分割阈值。Otsu会遍历所有的阈值,从而找到最佳的阈值。
在OpenCV中,通过在cv2.threshold()
中对参数type的类型多传递一个参数 cv2.THRESH_OTSU
,即可实现Otsu方式的阈值分割。
需要说明的是,在使用Otsu方法时,要把阈值设为0,此时的函数cv2.threshold()
会自动寻找最优阈值,并将该阈值返回。
t, otsu = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+CV2.THRESH_OTSU)
例1:测试Otsu阈值处理。
import cv2
import numpy as np
img = np.zeros((5, 5), dtype=np.uint8)
img[0:6, 0:6] = 123
img[2:6, 2:6] = 126
print('img = ', img)
t1, thd = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
print('t1 = ', t1)
print('thd = ', thd)
t2, otsu = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
print('t2 = ', t2)
print('otsu = ', otsu)
结果:
img = [[123 123 123 123 123]
[123 123 123 123 123]
[123 123 126 126 126]
[123 123 126 126 126]
[123 123 126 126 126]]
t1 = 127.0
thd = [[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]]
t2 = 123.0
otsu = [[ 0 0 0 0 0]
[ 0 0 0 0 0]
[ 0 0 255 255 255]
[ 0 0 255 255 255]
[ 0 0 255 255 255]]
例:对一幅图像分别使用普通的二值化阈值处理和Otsu阈值处理,观察处理结果的差异。
import cv2
img = cv2.imread('hongmao.jpg', 0)
t1, thd = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
t2, otsu = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
print('t1 = ', t1)
print('t2 = ', t2)
cv2.imshow('IMG', img)
cv2.imshow('THD', thd)
cv2.imshow('OTSU', otsu)
cv2.waitKey()
t1 = 127.0
t2 = 141.0
换一副色彩不均衡图像实验效果:
t1 = 127.0
t2 = 169.0