OpenCV计算机视觉实战(9)——阈值化技术详解

OpenCV计算机视觉实战(9)------阈值化技术详解

    • [0. 前言](#0. 前言)
    • [1. 全局阈值与自适应阈值](#1. 全局阈值与自适应阈值)
    • [2. Otsu 算法](#2. Otsu 算法)
    • [3. 实战案例:文档扫描中的二值化处理](#3. 实战案例:文档扫描中的二值化处理)
    • [4. 算法对比](#4. 算法对比)
    • 小结
    • 系列链接

0. 前言

在图像处理领域,阈值化 (Binarization) 技术就像一把魔术剪刀,能够将复杂的灰度图像一分为二,提取出关键的前景信息。无论是光照均匀的实验室拍摄,还是手机拍摄的阴影斑驳文档,选择合适的阈值化方法都至关重要。本文将介绍 OpenCV 中的三大阈值化法------全局阈值、自适应阈值与 Otsu 算法,剖析它们的原理与优缺点,并通过一个真实的文档扫描案例演示如何在实际场景下灵活组合与应用。

1. 全局阈值与自适应阈值

阈值化 (Binarization) 是图像处理中的基础操作,旨在将灰度图像转换为黑白图像,以便于后续的轮廓提取、光学字符识别 (Optical Character Recognition, OCR) 或图像分割。OpenCV 提供的两种主要阈值化方法包括:

  • 全局阈值 (Global Thresholding):对整幅图像使用一个固定的阈值,适用于光照均匀的图像
  • 自适应阈值 (Adaptive Thresholding):根据图像的局部区域动态计算阈值,适用于光照不均或背景复杂的图像

接下来,读取图像并预处理,将图像转换为灰度图,使用中值滤波去除噪声,并对比两种不同的阈值化技术:

  • 全局阈值化:使用 cv2.threshold 函数,设置固定阈值 (如 127) 进行二值化
  • 自适应阈值化:使用 cv2.adaptiveThreshold 函数,分别采用均值法 (Mean) 和高斯加权法 (Gaussian) 进行局部阈值计算
python 复制代码
import cv2

# 读取图像并转换为灰度
img = cv2.imread('1.jpeg', cv2.IMREAD_GRAYSCALE)
blur = cv2.medianBlur(img, 5)

# 全局阈值
_, th_global = cv2.threshold(blur, 127, 255, cv2.THRESH_BINARY)

# 自适应阈值 - Mean
th_mean = cv2.adaptiveThreshold(
    blur, 255,
    cv2.ADAPTIVE_THRESH_MEAN_C,
    cv2.THRESH_BINARY,
    blockSize=11, C=2
)

# 自适应阈值 - Gaussian
th_gauss = cv2.adaptiveThreshold(
    blur, 255,
    cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
    cv2.THRESH_BINARY,
    blockSize=11, C=2
)

# 显示结果
cv2.imshow('Global Thresholding', th_global)
cv2.imshow('Adaptive Mean Thresholding', th_mean)
cv2.imshow('Adaptive Gaussian Thresholding', th_gauss)
cv2.waitKey(0)
cv2.destroyAllWindows()

关键函数解析:

  • cv2.threshold(src, thresh, maxval, type):对整个图像使用同一阈值进行二值化,其中 thresh 为阈值,maxval 为当像素值超过了阈值(或者小于阈值,根据 type 来决定)所赋予的值,type 可指定二值化操作的类型,包含以下 5 种类型:
    • cv2.THRESH_BINARY,超过阈值部分取 maxval (最大值),否则取 0
    • cv2.THRESH_BINARY_INVTHRESH_BINARY 的反转
    • cv2.THRESH_TRUNC,大于阈值部分设为阈值,否则不变
    • cv2.THRESH_TOZERO,大于阈值部分不改变,否则设为 0
    • cv2.THRESH_TOZERO_INVTHRESH_TOZERO 的反转
  • cv2.adaptiveThreshold(src, maxval, adaptiveMethod, thresholdType, blockSize, C):自适应阈值化,针对图像的每个局部区域 (blockSize × blockSize) 计算阈值,adaptiveMethod 可选 ADAPTIVE_THRESH_MEAN_C (局部平均值)或 ADAPTIVE_THRESH_GAUSSIAN_C (局部加权平均)

2. Otsu 算法

Otsu 算法是一种自动确定图像全局阈值的方法,特别适用于具有双峰 (bimodal) 直方图的图像。该算法通过最大化类间方差(或最小化类内方差)来找到最佳阈值,从而将图像分为前景和背景两部分。
Otsu 算法流程如下:

  1. 计算图像直方图:统计每个灰度级别的像素数量
  2. 遍历所有可能的阈值:对于每个可能的阈值 t,计算前景和背景的类内方差
  3. 选择最佳阈值:找到使类内方差最小(或类间方差最大)的阈值 t,作为最佳阈值

这种方法不需要手动设置阈值,适用于光照均匀且前景与背景对比明显的图像。

python 复制代码
import cv2

# 读取图像
img = cv2.imread('1.jpeg', cv2.IMREAD_GRAYSCALE)
blur = cv2.GaussianBlur(img, (5, 5), 0)

# Otsu 阈值化
otsu_thresh, th_otsu = cv2.threshold(
    blur, 0, 255,
    cv2.THRESH_BINARY + cv2.THRESH_OTSU
)

print(f"Otsu 选的阈值: {otsu_thresh}")

cv2.imshow('Otsu Thresholding', th_otsu)
cv2.waitKey(0)
cv2.destroyAllWindows()

关键函数解析:

  • cv2.threshold:当 type 参数中包含 cv2.THRESH_OTSU 时,函数会自动计算最佳阈值,并返回该值
  • cv2.GaussianBlur(src, ksize, sigmaX):在执行 Otsu 前对图像做高斯模糊,可有效降低噪声对阈值选取的影响

3. 实战案例:文档扫描中的二值化处理

在实际应用中,如手机扫描文档,常常会遇到光照不均、阴影干扰等问题。为了获得清晰的扫描效果,我们可以结合自适应阈值和 Otsu 算法,进行多阶段的图像处理。

python 复制代码
import cv2

# 1. 读取并灰度化
color = cv2.imread('doc_photo.jpg')
gray = cv2.cvtColor(color, cv2.COLOR_BGR2GRAY)

# 2. 降噪
blur = cv2.medianBlur(gray, 3)

# 3. 自适应阈值初筛
adaptive = cv2.adaptiveThreshold(
    blur, 255,
    cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
    cv2.THRESH_BINARY, 15, 8
)

# 4. Otsu 细化
otsu_val, final = cv2.threshold(
    adaptive, 0, 255,
    cv2.THRESH_BINARY + cv2.THRESH_OTSU
)

# 5. 保存并展示
cv2.imwrite('scanned_doc.png', final)
cv2.imshow('Scanned Document', final)
cv2.waitKey(0)
cv2.destroyAllWindows()

关键函数解析:

  • cv2.cvtColor(src, code):图像色彩空间转换,此处将 BGR 转为灰度,为阈值化做准备
  • cv2.imwrite(filename, img):将二值化结果写入文件,方便后续查看或集成至扫描应用

4. 算法对比

通过以上对比,我们可以得出以下结论:

  • 全局阈值:适用于光照均匀、对比明显的图像,处理速度快,但对光照变化敏感
  • 自适应阈值:适用于光照不均、背景复杂的图像,能更好地保留细节,但计算量较大
  • Otsu 算法:适用于双峰直方图的图像,能自动确定最佳阈值,但对噪声敏感

在实际应用中,需要根据图像的具体特点选择合适的阈值化方法,或将多种方法结合,以获得最佳的处理效果。

小结

在本文中,我们深入探讨 OpenCV 中三种常用阈值化 (Binarization) 技术:全局阈值 (Global Thresholding)、自适应阈值 (Adaptive Thresholding) 以及 Otsu 算法 (Otsu's Method),并通过一个"文档扫描"二值化应用案例展示如何在实际场景中选用合适的阈值化方法。我们首先对比全局阈值与自适应阈值的适用场景与优缺点,接着剖析 Otsu 算法自动阈值选择原理,最后实现一个简单的文档扫描脚本,用于在复杂光照下获得清晰的扫描效果。

系列链接

OpenCV计算机视觉实战(1)------计算机视觉简介
OpenCV计算机视觉实战(2)------环境搭建与OpenCV简介
OpenCV计算机视觉实战(3)------计算机图像处理基础
OpenCV计算机视觉实战(4)------计算机视觉核心技术全解析
OpenCV计算机视觉实战(5)------图像基础操作全解析
OpenCV计算机视觉实战(6)------经典计算机视觉算法
OpenCV计算机视觉实战(7)------色彩空间详解
OpenCV计算机视觉实战(8)------图像滤波详解

相关推荐
NAGNIP1 小时前
一文搞懂深度学习中的通用逼近定理!
人工智能·算法·面试
冬奇Lab2 小时前
一天一个开源项目(第36篇):EverMemOS - 跨 LLM 与平台的长时记忆 OS,让 Agent 会记忆更会推理
人工智能·开源·资讯
冬奇Lab2 小时前
OpenClaw 源码深度解析(一):Gateway——为什么需要一个"中枢"
人工智能·开源·源码阅读
AngelPP6 小时前
OpenClaw 架构深度解析:如何把 AI 助手搬到你的个人设备上
人工智能
宅小年6 小时前
Claude Code 换成了Kimi K2.5后,我再也回不去了
人工智能·ai编程·claude
九狼6 小时前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS6 小时前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区8 小时前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈8 小时前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
Ray Liang8 小时前
被低估的量化版模型,小身材也能干大事
人工智能·ai·ai助手·mindx