OpenCV的阈值处理

如果你用过手机的 “文档扫描” 功能,或是处理过老照片的 “去灰”,可能没意识到 —— 这些操作的核心,其实是阈值处理。作为 OpenCV 中最基础也最实用的图像预处理技术,阈值处理能快速将灰度图像转化为 “黑白二值图”,帮我们从复杂背景中提取关键信息(比如文字、物体轮廓)。

一、先搞懂:什么是阈值处理?

简单说,阈值处理是给图像的像素值设定一个 “门槛”(阈值),然后根据像素值与门槛的大小关系,把像素归为两类(比如黑色和白色)

举个生活化的例子:我们把一张灰度图的像素值看作 “学生的考试分数”(0-255 分,0 是纯黑,255 是纯白),阈值就是 “及格线”(比如 127 分)。那么:

分数≥127 分(像素值≥阈值):归为 “及格”,像素设为纯白(255);

分数 <127 分(像素值 < 阈值):归为 “不及格”,像素设为纯黑(0);

经过这样的处理,原本 “灰蒙蒙” 的灰度图,就变成了 “非黑即白” 的二值图 —— 这就是最基础的阈值处理(二值化)。

为什么要做阈值处理?因为它能消除背景干扰,突出目标区域:比如处理文档照片时,把 “纸的浅色背景” 设为白,“文字的深色” 设为黑,后续就能轻松提取文字内容;处理工业质检图像时,用阈值分离 “零件的正常区域” 和 “缺陷区域”。

二、OpenCV 阈值处理核心:cv2.threshold () 函数

OpenCV 中实现固定阈值处理的核心函数是 cv2.threshold(),它能根据我们设定的 “阈值” 和 “处理类型”,快速输出处理后的图像。先记住它的基本用法:

1. 函数语法与参数

ret, dst = cv2.threshold(src, thresh, maxval, type)

参数解释(新手必看,少一个都不行):

src:输入图像,必须是单通道灰度图(不能直接用彩色图!);

thresh:我们设定的阈值(比如 127,0-255 之间的整数);

maxval:当像素值满足 “超过阈值” 的条件时,赋予的新像素值(通常设为 255,即纯白);

type:阈值处理的类型(关键!决定了 “像素值与阈值比较后怎么处理”);

返回值

ret:实际使用的阈值(如果用了自动阈值算法如 Otsu,会返回计算出的最佳阈值);

dst:处理后的输出图像。

2. 5 种常用阈值类型(重点!)

type 参数决定了阈值处理的效果,OpenCV 提供了 5 种最常用的类型,我们用 “灰度图(像素值 0-255)”+“阈值 127”+“maxval=255” 来举例,直观理解每种类型的差异:

类型常量中文名称处理逻辑(像素值 p 与阈值 thresh=127 比较)适用场景
cv2.THRESH_BINARY二值化p ≥ 127 → 255(白);p < 127 → 0(黑)文档文字提取、物体轮廓分割
cv2.THRESH_BINARY_INV反二值化p ≥ 127 → 0(黑);p < 127 → 255(白)提取浅色背景中的深色目标
cv2.THRESH_TRUNC截断p ≥ 127 → 127(固定为阈值);p < 127 → 不变降低图像亮度,保留暗部细节
cv2.THRESH_TOZERO低于阈值置零p ≥ 127 → 不变;p < 127 → 0(黑)突出亮部目标,消除暗部干扰
cv2.THRESH_TOZERO_INV高于阈值置零p ≥ 127 → 0(黑);p < 127 → 不变突出暗部目标,消除亮部干扰

一句话总结:想 “非黑即白” 用BINARYBINARY_INV;想 “保留部分亮度” 用TRUNC;想 “只留亮部 / 暗部” 用TOZEROTOZERO_INV

3. 实战:5 种阈值类型效果对比

光看表格不够直观,我们用一张 “带文字的灰度图” 做实验,代码可直接复制运行(需要先安装 OpenCV:pip install opencv-python):

import cv2
import matplotlib.pyplot as plt

# 1. 读取图像(必须转灰度图!)
img = cv2.imread("document.jpg")  # 替换成你的图像路径
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 彩色图转灰度图

# 2. 定义5种阈值类型
threshold_types = [
    cv2.THRESH_BINARY,
    cv2.THRESH_BINARY_INV,
    cv2.THRESH_TRUNC,
    cv2.THRESH_TOZERO,
    cv2.THRESH_TOZERO_INV
]
type_names = ["BINARY", "BINARY_INV", "TRUNC", "TOZERO", "TOZERO_INV"]

# 3. 循环处理并显示结果
plt.figure(figsize=(15, 5))  # 设置画布大小
for i, (type_val, type_name) in enumerate(zip(threshold_types, type_names)):
    ret, dst = cv2.threshold(gray, thresh=127, maxval=255, type=type_val)
    # 显示图像(matplotlib默认RGB,OpenCV默认BGR,灰度图无需转换)
    plt.subplot(1, 5, i+1)
    plt.imshow(dst, cmap="gray")
    plt.title(f"THRESH_{type_name}")
    plt.axis("off")  # 隐藏坐标轴

plt.show()

运行后你会发现:

BINARY 能把 “黑色文字” 变成 “黑色,背景变白”,最适合文档扫描;

BINARY_INV 会把 “文字变白色,背景变黑”,适合提取深色背景中的文字;

TRUNC 会把 “亮于 127 的区域压暗到 127”,图像整体偏灰;

三、进阶:自适应阈值处理(解决光照不均匀问题)

固定阈值(比如 127)有个大问题:如果图像光照不均匀(比如一边亮、一边暗),用固定阈值处理会导致 “亮的地方目标丢失,暗的地方背景残留”。

比如一张 “左边光照强、右边光照弱的文档图”:用固定阈值 127 处理,左边的文字会因为 “像素值超过 127” 被变成白色(消失),右边的背景会因为 “像素值低于 127” 被变成黑色(残留)。

这时候,自适应阈值处理就派上用场了 —— 它不使用 “全局固定阈值”,而是根据每个像素周围的局部区域亮度,动态计算该像素的阈值。

1. 核心函数:cv2.adaptiveThreshold ()

dst = cv2.adaptiveThreshold(src, maxval, adaptiveMethod, thresholdType, blockSize, C)

关键参数解释(比固定阈值多了 3 个参数):

adaptiveMethod:计算局部阈值的方法(两种选择):

cv2.ADAPTIVE_THRESH_MEAN_C:局部阈值 = 局部区域的均值 - C;cv2.ADAPTIVE_THRESH_GAUSSIAN_C:局部阈值 = 局部区域的高斯加权均值 - C;(效果更好,推荐用)

blockSize:局部区域的大小(必须是奇数,比如 3、5、7... 表示 “以当前像素为中心,取 3×3 或 5×5 的区域计算阈值”);

C:从局部均值 / 高斯均值中减去的常数(用来调整阈值的偏移量,通常设为 2-10 之间的整数,值越大,阈值越低,目标越容易被保留);

其他参数(srcmaxvalthresholdType)和固定阈值一致。

2. 实战:自适应阈值 vs 固定阈值

我们用 “光照不均匀的文档图” 做对比实验,看自适应阈值的优势:

import cv2
import matplotlib.pyplot as plt

# 1. 读取图像并转灰度图
img = cv2.imread("uneven_light_document.jpg")  # 光照不均匀的文档图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 2. 固定阈值处理(对比组)
ret_fixed, fixed_dst = cv2.threshold(gray, thresh=127, maxval=255, type=cv2.THRESH_BINARY)

# 3. 自适应阈值处理(实验组)
# 用高斯加权均值计算局部阈值,局部区域5×5,C=5
adaptive_dst = cv2.adaptiveThreshold(
    gray, 
    maxval=255, 
    adaptiveMethod=cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
    thresholdType=cv2.THRESH_BINARY, 
    blockSize=5, 
    C=5
)

# 4. 显示对比结果
plt.figure(figsize=(12, 6))
# 原图
plt.subplot(1, 3, 1)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))  # 转RGB显示彩色图
plt.title("Original Image")
plt.axis("off")
# 固定阈值
plt.subplot(1, 3, 2)
plt.imshow(fixed_dst, cmap="gray")
plt.title("Fixed Threshold (127)")
plt.axis("off")
# 自适应阈值
plt.subplot(1, 3, 3)
plt.imshow(adaptive_dst, cmap="gray")
plt.title("Adaptive Threshold (Gaussian)")
plt.axis("off")

plt.show()

运行后你会明显看到:

固定阈值处理的图像,光照强的区域文字丢失,光照弱的区域有背景噪点;

自适应阈值处理的图像,无论光照强弱,文字都清晰保留,背景干净 —— 这就是它的核心优势!

四、实用技巧:让阈值处理效果更好的 3 个关键

  1. 先转灰度图,再去噪
    阈值处理只对单通道灰度图有效,所以第一步必须用 cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 转灰度。另外,图像中的噪声会干扰阈值判断(比如小噪点会被误判为目标),建议处理前用高斯模糊去噪:

    gray_blur = cv2.GaussianBlur(gray, ksize=(5, 5), sigmaX=0)  # 5×5高斯核去噪
    
  2. 用 Otsu 自动选阈值(固定阈值的优化)
    如果不知道该设多少阈值(比如 127 还是 150),可以在 cv2.threshold() 的 type 参数中加 cv2.THRESH_OTSU,让算法自动计算最佳阈值:

    # 自动计算最佳阈值,ret就是Otsu算出的阈值
    ret_otsu, otsu_dst = cv2.threshold(gray_blur, thresh=0, maxval=255, type=cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    print(f"Otsu自动计算的阈值:{ret_otsu}")  # 比如输出135,比手动设127更合适
    
     

    注意:Otsu 只适用于 “目标和背景灰度差异明显” 的图像(比如清晰的文档)。

  3. 调整 blockSize 和 C(自适应阈值的关键)

    • blockSize:局部区域越小(如 3×3),阈值对局部光照越敏感,但可能引入噪点;区域越大(如 11×11),抗噪能力越强,但细节可能模糊。建议从 5×5 或 7×7 开始试。
    • C:值越大,阈值越低,目标区域越容易被保留(但可能保留背景);值越小,阈值越高,背景越干净(但可能丢失目标细节)。建议从 2-5 开始试。
好的,我来为您讲解一下 OpenCV 中的阈值处理阈值处理是一种图像处理方法,通过将图像中的像素值与一个特定的阈值进行比较,并根据比较结果对像素值进行修改。在 OpenCV 中,有两种常用的阈值处理方法:全局阈值和自适应阈值。 1. 全局阈值 全局阈值是指对整个图像应用一个固定的阈值。在 OpenCV 中,可以使用 cv2.threshold() 函数来实现全局阈值处理。该函数的参数包括输入图像、阈值、最大像素值和阈值处理类型等。 例如,以下代码将图像中所有像素值大于 127 的像素设为白色(255),其余像素设为黑色(0): ``` import cv2 img = cv2.imread('image.jpg', 0) ret, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) cv2.imshow('Thresholded Image', thresh) cv2.waitKey(0) ``` 2. 自适应阈值 自适应阈值是指对不同区域使用不同的阈值,可以更好地处理光线不均匀的图像。在 OpenCV 中,可以使用 cv2.adaptiveThreshold() 函数来实现自适应阈值处理。该函数的参数包括输入图像、最大像素值、自适应方法、阈值类型、块大小和常数等。 例如,以下代码将图像进行自适应阈值处理: ``` import cv2 img = cv2.imread('image.jpg', 0) thresh = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2) cv2.imshow('Adaptive Thresholded Image', thresh) cv2.waitKey(0) ``` 以上就是 OpenCV阈值处理的简单介绍,希望能够帮到您。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值