OpenCV 对图像进行阈值处理 cv2.threshold
OpenCV 对图像进行阈值处理 cv2.threshold
flyfish
二值化的含义
基本概念
在图像处理领域,二值化是一种非常基础且重要的操作。它的核心目的是将图像中的像素值简化为两种状态,通常用 0 和 255 来表示,分别对应黑色和白色。简单来说,二值化就是把一幅灰度图像转换为只有黑和白两种颜色的图像。
实现原理
二值化处理主要依据设定的阈值来完成。对于图像中的每个像素,如果其灰度值大于设定的阈值,就将该像素的值设为一个特定的最大值(通常是 255,表示白色);如果灰度值小于或等于阈值,就将其设为 0(表示黑色)。其数学表达式如下:
f ( x , y ) = { 255 , if g ( x , y ) > T 0 , if g ( x , y ) ≤ T f(x,y) = \begin{cases} 255, & \text{if } g(x,y) > T \\ 0, & \text{if } g(x,y) \leq T \end{cases} f(x,y)={255,0,if g(x,y)>Tif g(x,y)≤T
这里的 (f(x,y)) 是二值化后图像在 ((x,y)) 位置的像素值,(g(x,y)) 是原始图像在 ((x,y)) 位置的像素值,(T) 则是设定的阈值。
应用场景
二值化在很多实际场景中都有广泛应用,例如:
- 文字识别:将文字图像二值化后,可以更清晰地分离出文字和背景,有助于后续的字符分割和识别。
- 目标检测:二值化能突出目标物体,方便检测和定位目标。
- 图像分析:简化图像信息,降低处理复杂度,使后续的分析更加高效。
cv2.threshold
函数
功能概述
cv2.threshold
函数用于对图像进行阈值处理。阈值处理是一种简单的图像分割方法,它将图像中的像素值根据设定的阈值进行分类,将像素值大于阈值的像素设置为一个值(通常是 255,表示白色),将像素值小于等于阈值的像素设置为另一个值(通常是 0,表示黑色)。
函数语法
ret, binary = cv2.threshold(src, thresh, maxval, type)
- 参数说明:
src
:输入的单通道图像,通常是灰度图像。thresh
:设定的阈值。在使用 Otsu 方法时,这个参数会被忽略,因为 Otsu 方法会自动计算出最优的阈值。maxval
:当像素值大于阈值时,将其设置为这个值,通常为 255。type
:阈值处理的类型,常见的类型有:cv2.THRESH_BINARY
:二值化阈值处理,像素值大于阈值的设为maxval
,小于等于阈值的设为 0。cv2.THRESH_BINARY_INV
:反向二值化阈值处理,像素值大于阈值的设为 0,小于等于阈值的设为maxval
。cv2.THRESH_OTSU
:Otsu 方法,它会自动计算出一个最优的阈值,该方法通常与其他阈值处理类型结合使用,如cv2.THRESH_BINARY + cv2.THRESH_OTSU
。
- 返回值:
ret
:返回的阈值,如果使用了 Otsu 方法,这个值就是 Otsu 计算出的最优阈值。binary
:阈值处理后的二值图像。
Otsu 方法,也被称为大津法,是由日本学者大津展之在 1979 年提出的一种自动确定图像二值化阈值的算法。在进行图像二值化时,关键在于选择合适的阈值,而 Otsu 方法能够自动找到一个最优的阈值,使得分割后的图像类间方差最大。以下为你详细介绍:
基本原理
Otsu 方法的核心思想是将图像中的像素分为两类(前景和背景),通过遍历所有可能的阈值,计算每一个阈值下这两类像素的类间方差,选择使类间方差达到最大值的阈值作为最优阈值。类间方差反映了这两类像素的差异程度,类间方差越大,说明这两类像素的区分度越高,分割效果也就越好。
算法步骤
假设图像的灰度级范围是 [ 0 , L − 1 ] [0, L - 1] [0,L−1],具体步骤如下:
- 计算灰度直方图:统计图像中每个灰度级的像素数量,得到灰度直方图。
- 遍历所有可能的阈值:从 t = 0 t = 0 t=0 到 t = L − 1 t = L - 1 t=L−1 遍历所有可能的阈值。
- 计算每一个阈值下的相关参数:
- 计算背景像素的概率 w 0 ( t ) w_0(t) w0(t) 和前景像素的概率 w 1 ( t ) w_1(t) w1(t):
w 0 ( t ) = ∑ i = 0 t p ( i ) w_0(t)=\sum_{i = 0}^{t}p(i) w0(t)=i=0∑tp(i)
w 1 ( t ) = ∑ i = t + 1 L − 1 p ( i ) = 1 − w 0 ( t ) w_1(t)=\sum_{i = t+1}^{L - 1}p(i)=1 - w_0(t) w1(t)=i=t+1∑L−1p(i)=1−w0(t)
其中, p ( i ) p(i) p(i) 是灰度级为 i i i 的像素出现的概率。 - 计算背景像素的平均灰度值 μ 0 ( t ) \mu_0(t) μ0(t) 和前景像素的平均灰度值 μ 1 ( t ) \mu_1(t) μ1(t):
μ 0 ( t ) = 1 w 0 ( t ) ∑ i = 0 t i × p ( i ) \mu_0(t)=\frac{1}{w_0(t)}\sum_{i = 0}^{t}i\times p(i) μ0(t)=w0(t)1i=0∑ti×p(i)
μ 1 ( t ) = 1 w 1 ( t ) ∑ i = t + 1 L − 1 i × p ( i ) \mu_1(t)=\frac{1}{w_1(t)}\sum_{i = t + 1}^{L - 1}i\times p(i) μ1(t)=w1(t)1i=t+1∑L−1i×p(i) - 计算类间方差 σ B 2 ( t ) \sigma_B^2(t) σB2(t):
σ B 2 ( t ) = w 0 ( t ) w 1 ( t ) ( μ 0 ( t ) − μ 1 ( t ) ) 2 \sigma_B^2(t)=w_0(t)w_1(t)(\mu_0(t)-\mu_1(t))^2 σB2(t)=w0(t)w1(t)(μ0(t)−μ1(t))2
- 计算背景像素的概率 w 0 ( t ) w_0(t) w0(t) 和前景像素的概率 w 1 ( t ) w_1(t) w1(t):
- 选择最优阈值:找到使类间方差 σ B 2 ( t ) \sigma_B^2(t) σB2(t) 最大的阈值 t ∗ t^* t∗,即:
t ∗ = arg max 0 ≤ t ≤ L − 1 σ B 2 ( t ) t^*=\arg\max_{0\leq t\leq L - 1}\sigma_B^2(t) t∗=arg0≤t≤L−1maxσB2(t)
代码示例
import cv2# 读取图像,以灰度模式读取
image = cv2.imread('example.jpg', 0)# 使用 Otsu 方法进行二值化处理
ret, binary = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)# 显示原始图像
cv2.imshow('Original Image', image)# 显示二值化后的图像
cv2.imshow('Otsu Binary Image', binary)# 等待按键事件,按任意键关闭窗口
cv2.waitKey(0)# 关闭所有打开的窗口
cv2.destroyAllWindows()
解释
cv2.imread('example.jpg', 0)
:以灰度模式读取图像。cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
:使用 Otsu 方法进行二值化处理,0
这个参数会被 Otsu 方法忽略,255
是像素值大于阈值时设置的值。ret
:返回的最优阈值。binary
:二值化后的图像。
优缺点
- 优点:
- 无需人为设定阈值,自动计算最优阈值,使用方便。
- 计算速度较快,适用于实时处理。
- 缺点:
- 假设图像的灰度分布是双峰的,对于灰度分布不符合双峰特征的图像,分割效果可能不理想。
- 对噪声比较敏感,噪声可能会影响阈值的选择。