Opencv中文网

自适应阈值(AdaptiveThreshold)

这是比普通 Threshold 强大 10 倍的核心函数,专门解决光照不均匀、局部明暗差异大的图像(比如阴影、反光、拍照偏光的文档)。

普通 Cv2.Threshold全局一个阈值,遇到阴影直接废;

AdaptiveThreshold每个像素自己算局部阈值,抗光照干扰极强!

一、它到底是什么?

自适应阈值 = 局部阈值化

  • 对图像每一个小区域单独计算阈值
  • 解决:阴影、反光、光照不均、局部亮度变化
  • 典型用途:扫描文档文字提取、银行卡 / 证件识别、暗背景文字、低光图像二值化

一句话区别:

  • Threshold:整张图用 同一个阈值(简单但怕光照)
  • AdaptiveThreshold:每个像素用 周围区域算出的阈值(复杂但鲁棒)

二、函数原型(C# / OpenCVSharp)

void AdaptiveThreshold(
    InputArray src,        // 输入图像(必须 8位 单通道灰度图)
    OutputArray dst,       // 输出二值图像
    double maxValue,       // 满足条件后的最大值(一般 255)
    AdaptiveThresholdTypes adaptiveType,  // 自适应算法
    ThresholdTypes thresholdType,         // 阈值类型(只能是 二值/反向二值)
    int blockSize,          // 局部区域大小(必须 奇数:3,5,7...)
    double C                // 微调常数(阈值减去 C)
);

重要:无返回值

它不像普通 Threshold 返回阈值,因为每个像素的阈值都不一样

三、所有参数逐行详解

1. src(输入)

  • 必须是 8 位 单通道灰度图
  • 彩色图必须先转灰度:Cv2.CvtColor(..., ColorConversionCodes.BGR2GRAY)

2. dst(输出)

  • 二值化图像(黑 0 / 白 maxValue)

3. maxValue(最大值)

  • 常用:255(白色)
  • 只有二值化时用到

4. adaptiveType(自适应算法)

2 种选择,决定 “局部阈值怎么算”

① AdaptiveThresholdTypes.MeanC(均值法)

  • 阈值 = 像素周围 blockSize×blockSize 区域的平均值 - C
  • 速度快,适合大部分文档、文字

② AdaptiveThresholdTypes.GaussianC(高斯加权均值)

  • 阈值 = 周围区域高斯加权平均值 - C
  • 更平滑,对噪声、斑点更鲁棒
  • 推荐优先使用!

5. thresholdType(阈值类型)

这里只能用 2 种! 不能用别的!

  • ThresholdTypes.Binary:正常二值化
  • ThresholdTypes.BinaryInv:反向二值化

99% 场景用 BinaryInv(白底黑字 → 黑底白字更清晰)

6. blockSize(局部窗口大小)

  • 必须是 奇数:3、5、7、9、11 ...
  • 越小:细节越多,噪声也多
  • 越大:越平滑,细节丢失
  • 常用:9、11、15

7. C(微调常数)

  • 最终阈值 = 局部均值 - C
  • C 越大,文字越粗、越黑
  • C 越小,文字越细、容易断
  • 经验值:2 ~ 15 之间

四、计算公式(一看就懂)

以 GaussianC + BinaryInv 为例:

阈值 = 高斯加权局部均值 - C 如果 原像素 > 阈值 → 黑色(0) 否则 → 白色(255)

五、最实用、最标准的代码示例

using OpenCVSharp;
using OpenCVSharp.Flag;

class Program
{
    static void Main()
    {
        // 1. 读图片
        Mat src = Cv2.ImRead("document.jpg", ImreadModes.Color);

        // 2. 转灰度(必须!)
        Mat gray = new Mat();
        Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);

        // 3. 自适应阈值(最常用组合)
        Mat dst = new Mat();
        Cv2.AdaptiveThreshold(
            gray,                // 原图
            dst,                 // 输出
            255,                 // 最大值
            AdaptiveThresholdTypes.GaussianC,  // 高斯(推荐)
            ThresholdTypes.BinaryInv,          // 反向二值化(文字清晰)
            blockSize: 15,       // 窗口大小(奇数)
            C: 9                 // 微调常数
        );

        // 保存结果
        Cv2.ImWrite("result.png", dst);
    }
}

六、2 种自适应算法对比

表格

类型原理速度噪声推荐场景
MeanC算术平均一般清晰文档、无噪点
GaussianC高斯加权平均稍慢很低绝大多数场景首选

七、参数怎么调?(超实用经验)

blockSize 怎么选?

  • 文字小 → 用 9
  • 文字大 → 用 11、15
  • 图像噪声大 → 用 15、21

C 怎么调?

  • 文字太淡、断断续续 → C 调大(如 9→12)
  • 文字太粗、连在一起 → C 调小(如 9→6)
  • 背景脏 → C 调大

八、自适应阈值 VS 普通阈值

表格

特性普通 Threshold自适应 AdaptiveThreshold
阈值全局一个每个像素局部计算
抗光照极强
阴影失效完美处理
速度极快较慢
适用光照均匀文档、低光、阴影、反光

九、最常见的坑(90% 的人踩过)

  1. 输入不是灰度图 → 直接报错
  2. blockSize 不是奇数 → 报错
  3. 用了 Otsu → 自适应阈值不支持 Otsu
  4. thresholdType 用了 ToZero/Trunc → 报错(只支持 Binary/BinaryInv)
  5. C 值太大 / 太小 → 文字全黑 或 全消失

copyright @重庆教主 WPF中文网 联系站长:(QQ)23611316 (微信)movieclip (QQ群).NET小白课堂:864486030 | 本文由WPF中文网原创发布,谢绝转载 渝ICP备2023009518号-1