☰
置信度增强的 Sauvola 二值化:文档图像前景信息保留算法解析与实战(computervision-recipes)
2026/10/8 1:38:34 网站建设 项目流程
  • 计算机视觉
  • 深度学习

【免费下载链接】computervision-recipes

Best Practices, code samples, and documentation for Computer Vision.

项目地址:https://gitcode.com/gh_mirrors/co/computervision-recipes
点击查看免费下载

本文围绕 computervision-recipes 仓库中confidence_based_Sauvola_binarization模块,系统讲解一种对经典 Sauvola 二值化进行改进的文档图像处理技术:通过为背景像素引入置信度评分,在二值化过程中保留更多前景信息,从而改善扫描文档图像的可读性与清晰度。读完本文,你将掌握该算法的数学原理、核心实现函数SauvolaModBinarization的参数含义与默认取值,以及基于默认参数和自定义参数的实际调用方法。

该算法属于仓库 document_cleanup(文档图像清理) 方向的子模块。在文档清理任务中,输入往往是带有噪声、阴影或扫描痕迹的文档图像,目标是去除噪声元素、提升可读性与可见性;而二值化正是这一流程中最基础也最关键的一步——它负责把前景(文字、笔迹、图形)与背景(纸张)像素可靠地区分开来。

什么是文档图像二值化

二值化(Binarization)是一种将前景像素与背景像素分割开来的技术。正如模块 README 所述,最朴素的二值化手段是对灰度或彩色扫描文档图像直接做阈值化(thresholding):设定一个全局阈值,像素值大于阈值则判为前景(通常置 255),否则判为背景(置 0)。

然而,真实扫描文档常存在光照不均、纸张发黄、阴影遮挡等问题,单一全局阈值难以同时处理好整幅图像。Sauvola 算法通过在每个像素的局部邻域窗口内自适应计算阈值,正是应对上述场景的经典方案,本文介绍的置信度增强技术则是在此基础上的进一步改进。

Sauvola 算法回顾:局部自适应阈值公式

在改进版算法的示例 Notebook Modified-Sauvola_Binarization.ipynb 中,给出了 Sauvola 算法的阈值计算公式(原文公式 1):

$$ T_W(p) = m_{W}^{p} \times \left[ 1 + k \times \left( \frac{s_{W}^{p}}{R} - 1 \right) \right] $$

其中:

  • 对于输入图像 $I$,$R = \frac{\max(I) - \min(I)}{2}$;
  • $m_{W}^{p}$、$s_{W}^{p}$ 分别是以像素 $p$ 为中心的 $n \times n$ 窗口 $W$ 内的灰度均值与标准差;
  • $k$ 为调节因子,取值位于 $0 \le k \le 1$ 之间,默认取 $0.5$。

可以看出,Sauvola 阈值并非全局常数,而是随局部窗口内均值和标准差的统计特性自适应变化:在对比度较高(标准差大)的区域自动调整阈值,从而能更好地处理光照不均匀的文档。在仓库的源码与 Notebook 中,第一遍 Sauvola 阈值由skimage.filters.threshold_sauvola计算得到,窗口大小通常取图像较小边长的一定比例,并强制取奇数。

置信度改进的核心思想

经典 Sauvola 虽然自适应,但在二值化过程中仍可能丢失部分前景信息——尤其是与背景灰度接近的浅色笔迹、印章或弱对比边缘。本模块的改进思路(参见 README 与 Notebook)是:为背景像素引入一个置信度评分(confidence score),从而在最终二值图像中保留更多前景信息。

具体地,对每个像素 $p$ 定义置信度 $C$(原文公式 2):

$$ C_W(p) = \begin{cases} \dfrac{I(p) - T_W(p)}{\max(I) - T_W(p)} & \text{if } I(p) > T_W(p) \ 0 & \text{otherwise} \end{cases} $$

其中 $I(p)$ 为像素 $p$ 的灰度值,$T_W(p)$ 为其局部 Sauvola 阈值,$\max(I)$ 为整幅输入图像的最大像素值。

该置信度的直观含义是:当某像素灰度高于其局部 Sauvola 阈值时,它高出阈值的程度被归一化到 $(0, 1]$ 区间,作为该像素属于前景的"可信程度";反之,若像素灰度低于阈值,则置信度直接置 0。算法随后利用这一置信度值生成一幅新的置信度图像 $I_c$,再对 $I_c$ 再次应用 Sauvola 公式计算阈值,并用这些新阈值生成最终二值图像——这正是源码中的"两遍(two-pass)Sauvola"结构:

  1. 第一遍:对原始灰度图 $I$ 应用 Sauvola,得到局部阈值 $T_1$;
  2. 置信度映射:由公式 2 计算每个像素的置信度 $C$,并缩放到 $[0, 255]$ 形成中间图像 $I_c$;
  3. 第二遍:对置信度图像 $I_c$ 再次应用 Sauvola,得到阈值 $T_2$;
  4. 二值化:根据 $I_c$ 与 $T_2$ 的大小关系输出最终二值图像。

由于置信度图像放大了前景像素与局部阈值的相对差异,第二次 Sauvola 分割时能更细致地保留弱前景信息,这是该改进算法能"保留更多前景信息"的根本原因。更详细的推导与实验依据可参阅随模块附带的论文 ModifiedSauvola.pdf。

核心实现剖析:SauvolaModBinarization 函数

整个算法的核心实现位于 ModifiedSauvola_Binarization.py,由一个独立的函数SauvolaModBinarization完成,依赖numpy、cv2(OpenCV)与skimage.filters.threshold_sauvola。函数签名与完整实现如下:

import numpy as np import cv2 from skimage.filters import threshold_sauvola def SauvolaModBinarization(image, n1=51, n2=51, k1=0.3, k2=0.3, default=True): if default: n1 = int(0.05 * min(image.shape[0], image.shape[1])) if (n1 % 2 == 0): n1 = n1 + 1 n2 = int(0.1 * min(image.shape[0], image.shape[1])) if (n2 % 2 == 0): n2 = n2 + 1 k1 = 0.5 k2 = 0.5 if image.ndim == 3: gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) else: gray = np.copy(image) T1 = threshold_sauvola(gray, window_size=n1, k=k1) max_val = np.amax(gray) min_val = np.amin(gray) C = np.copy(T1) C = C.astype(np.float32) C[gray > T1] = (gray[gray > T1] - T1[gray > T1]) / (max_val - T1[gray > T1]) C[gray <= T1] = 0 C = C * 255.0 new_in = np.copy(C.astype(np.uint8)) T2 = threshold_sauvola(new_in, window_size=n2, k=k2) binary = np.copy(gray) binary[new_in <= T2] = 0 binary[new_in > T2] = 255 return binary

对照上文的算法流程,可以逐段对应源码中的实现步骤:

  1. 参数解析与默认值计算:当default=True时,依据图像较小边长按比例推导n1、n2,并将偶数窗口强制加 1 调整为奇数(skimage的threshold_sauvola要求窗口尺寸为奇数);k1、k2均设为 0.5。
  2. 灰度转换:输入为 3 通道图像时,用 OpenCV 的COLOR_BGR2GRAY转为灰度;输入本身为单通道灰度图时直接拷贝使用。注意这里默认假设彩色输入是 BGR 通道顺序(即cv2.imread的默认读取结果)。
  3. 第一遍 Sauvola:调用threshold_sauvola(gray, window_size=n1, k=k1)得到逐像素阈值矩阵T1。
  4. 置信度计算与缩放:对gray > T1的像素按公式 2 计算归一化置信度,其余像素置信度置 0,整体乘以 255 后转换为uint8中间图像new_in,即置信度图像 $I_c$。
  5. 第二遍 Sauvola 与二值化:对new_in以窗口n2、系数k2再次计算阈值T2,然后按"低于阈值置 0、高于阈值置 255"生成并返回与输入等尺寸的二值图像。

核心参数详解与取值建议

函数提供了 4 个核心算法参数与 1 个开关参数,完整参数含义如下表(依据源码 docstring 与实现):

参数类型含义default=True时的取值
n1int第一遍 Sauvola 的窗口大小图像较小边长的 5%,且强制取奇数
n2int第二遍 Sauvola 的窗口大小图像较小边长的 10%,且强制取奇数
k1float第一遍 Sauvola 的 $k$ 值0.5
k2float第二遍 Sauvola 的 $k$ 值0.5
defaultbool是否使用上述默认参数True

从源码实现可以推断出以下调参规律:

  • 窗口大小n1、n2直接决定局部统计的邻域范围:窗口过小会使局部均值和标准差对噪声敏感,窗口过大会使阈值趋于全局化、丢失自适应优势。第一遍窗口默认取较小边长的 5%(更细粒度地捕捉局部前景),第二遍取 10%(在置信度图上做较稳健的二次分割),两者均需为奇数,偶数会自动 +1 校正。
  • 系数k1、k2控制阈值对局部标准差偏离的敏感程度,取值介于 0 到 1 之间,默认 0.5 是 Sauvola 算法文档与实现的常用经验值。
  • default=False模式用于需要针对特定文档类型微调的场景,此时n1、n2、k1、k2完全由调用方传入,但需要调用方自行保证窗口为奇数。

实战用法:默认参数与自定义参数

示例 Notebook Modified-Sauvola_Binarization.ipynb 提供了完整的、可直接复现的调用示例。首先导入依赖与模块:

import numpy as np import cv2 from matplotlib import pyplot as plt from skimage.filters import threshold_sauvola import ModifiedSauvola_Binarization as MSB

基线对比:经典 Sauvola 二值化

Notebook 先用与默认改进参数一致的设置(窗口为较小边长的 5%、取奇数,$k=0.5$)跑一遍经典 Sauvola,作为效果对比基线:

filename = "test_images/2.jpeg" in_color = cv2.imread(filename, 1) # BGR 彩色读取 win_size = int(0.05 * min(in_color.shape[0], in_color.shape[1])) if win_size % 2 == 0: win_size = win_size + 1 k = 0.5 gray = cv2.cvtColor(in_color, cv2.COLOR_BGR2GRAY) T = threshold_sauvola(gray, window_size=win_size, k=k) binary = np.copy(gray) binary[gray <= T] = 0 binary[gray > T] = 255

默认参数调用改进算法

使用改进算法时,只需一行调用,内部会自动按默认规则推导n1 = 5%、n2 = 10%、k1 = k2 = 0.5:

binary_default = MSB.SauvolaModBinarization(in_color)

自定义参数调用

针对对比度较弱的文档,可以显式传入自定义窗口与系数,此时需将default置为False:

k1 = 0.5 k2 = 0.5 n1 = int(0.04 * min(in_color.shape[0], in_color.shape[1])) if n1 % 2 == 0: n1 = n1 + 1 n2 = int(0.09 * min(in_color.shape[0], in_color.shape[1])) if n2 % 2 == 0: n2 = n2 + 1 binary_nondefault = MSB.SauvolaModBinarization( in_color, n1, n2, k1, k2, default=False )

上述代码展示了完整的实战流程:读取彩色文档图像 → (可选)用经典 Sauvola 做基线 → 用默认参数调用改进算法 → 用自定义参数(本例窗口比例取 4% 与 9%)调用并对比。函数返回值与输入图像尺寸一致,可直接用plt.imshow(binary, cmap='gray')或cv2.imwrite输出查看/保存。

效果对比:置信度增强如何保留更多前景

模块的 README 通过三组测试图像(test_images/目录下的2.jpeg、10.jpeg、new1.jpg)展示了改进前后的直观差异:每组均对比经典 Sauvola 的输出(results 目录 中以_old结尾的2_bin_old.png、10_bin_old.png、new1_bin_old.png)与置信度增强 Sauvola 的输出(以_new结尾的2_bin_new.png、10_bin_new.png、new1_bin_new.png)。

从这些对比结果可以看出,改进后的二值图像在前景区域保留了更完整的信息:原本被经典 Sauvola 误判为背景而"吞掉"的浅色笔迹与细节,在置信度增强版本中被保留下来。这一改进方向与本模块所属的 文档图像清理 任务目标一致——去除噪声的同时最大化保留文字等前景内容的可读性。关于定量指标、更多实验细节与算法论证,请查阅附带的论文 ModifiedSauvola.pdf。

环境依赖与运行准备

模块 README 明确列出的依赖版本如下:

  • Python 3.7
  • numpy 1.16
  • OpenCV(cv2)4.2
  • scikit-image(skimage)0.17

threshold_sauvola来自skimage.filters,因此 scikit-image 是算法的关键依赖;OpenCV 用于读取图像与 BGR→灰度转换;numpy 承担全部矩阵运算。在满足上述版本的 Python 环境中,可通过以下方式使用该模块:

  • 作为脚本/模块运行:将ModifiedSauvola_Binarization.py放入工作目录后,import ModifiedSauvola_Binarization as MSB即可调用;
  • 按 Notebook 方式复现:依次执行 Modified-Sauvola_Binarization.ipynb 中的单元格,可完整走通"经典 Sauvola → 改进算法(默认参数)→ 改进算法(自定义参数)"的对比流程,并使用 matplotlib 可视化中间结果;
  • 测试图像:仓库的 test_images 目录 提供了2.jpeg、10.jpeg、new1.jpg等多张样例文档图像,results 目录 中存放了对应的新旧二值化结果,便于直接核验算法输出。

进一步阅读与延伸

  • 算法出处:模块附带的论文 ModifiedSauvola.pdf,其中包含置信度公式的完整推导与实验验证。
  • 可运行示例:Modified-Sauvola_Binarization.ipynb 覆盖了本文全部代码示例与可视化输出。
  • 核心源码:ModifiedSauvola_Binarization.py 是该算法的唯一实现文件,约 50 行,便于直接阅读与二次改造。
  • 所属方向:document_cleanup(文档图像清理) 下还包含基于深度学习的轻量级文档清理方案(ICDAR 2021),与本二值化算法互为补充,可结合具体场景选用。

综上所述,本模块以"两遍 Sauvola + 置信度映射"为核心设计,通过一次极简的代码实现,在经典自适应二值化框架内显著提升了对弱前景信息的保留能力。无论你是想快速获得更优的文档二值化结果,还是希望理解自适应阈值算法的改进思路,SauvolaModBinarization都是一个易于复现、便于二次开发的优秀起点。

  • 计算机视觉
  • 深度学习

【免费下载链接】computervision-recipes

Best Practices, code samples, and documentation for Computer Vision.

项目地址:https://gitcode.com/gh_mirrors/co/computervision-recipes
点击查看免费下载
上一篇:如何用5分钟打造专业邮件签名:开源神器全解析
下一篇:语义相似度阈值优化实战指南:突破检索性能瓶颈的关键技术

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询