1

我正在开发一个应用程序来在不同的光照条件下提取 C# 中的文本。

我的问题是有时图像中有不同的亮度级别,如下所示:

http://i.imgur.com/NJ2XTrn.png?1

所以我不能为整个图像使用预先计算的阈值,否则我会丢失一些字母。

我正在搜索可以将正确的阈值/二值化应用于图像的算法/片段/函数。

我在 AForge 中创建了这个BradleyLocalThresholding,它比其他非自适应方法更好,但它丢失了一些细节。(例如图像中的 G 变成 O )

任何人都可以向我建议更好的方法吗?

4

3 回答 3

2

这非常困难,因为您的图像质量非常低,但您可以尝试迭代全局阈值方法,如下所示:

  1. 随机选择一个初始估计阈值 T(通常作为平均值)。
  2. 使用 T 分割信号,这将产生两组,G1 由值<=T 的所有点组成,G2 由值>T 的点组成。
  3. 计算 G1 和 T 点以及 G2 和 T 点之间的平均距离。
  4. 计算一个新的阈值 T=(M1+M2)/2
  5. 重复步骤 2 到 4,直到 T 的变化足够小。

诀窍不是将其应用于整个图像,而是将图像分解为(例如)5x5 的块并将其单独应用于块,这将为您提供:

在此处输入图像描述

下面是 R 中的一个实现,我相信你可以重现

getT = 函数(y){
  t = 平均值(y)

  mu1 = 平均值(y[y>=t])
  mu2 = 平均值(y[y 1){
      cmu1 = 平均值(y[y>=t])
      cmu2 = mean(y[y 1 & cmu1 == mu1 & cmu2 == mu2){
      打印(粘贴('完成 t=',t))
      回报(t)
      休息;
    }别的{
      mu1 = cmu1
      mu2 = cmu2
      t = (mu1 + mu2)/2
      打印(粘贴('新 t=',t))
    }
    我=我+1
  }
}


r = seq(1, nrow(图像), by=5)
c = seq(1, ncol(图像), by=5)
r[长度(r)] = nrow(图像)
c[长度(c)] = ncol(图像)
y = 图像
for(i in 2:length(r) ){
  for(j in 2:length(c) ){
    块 = 图像[r[i-1]:r[i], c[j-1]:c[j]]
    t = getT(块)
    y[r[i-1]:r[i], c[j-1]:c[j]] = (block>t)+0
  }
}

显示(y)
于 2013-05-02T23:47:27.490 回答
2

是的,使用 niblack(opencv 将它作为一个函数) - 基本上它使用局部平均值来构造一个变量阈值。它最适合 OCR。根据图像分辨率,您可能还希望在阈值处理之前将双三次上采样率提高 2 倍或 3 倍。

于 2013-04-30T20:44:12.290 回答
0

除了局部阈值之外的另一个选项是针对变化的照明进行调整。有一些方法试图校正照明并使其在整个图像中均匀。然后,您可以使用恒定阈值,或继续使用局部阈值,可能会取得更好的成功。如果图像与您显示的图像一样,那么您可以使用字母周围较亮的方块作为调整照明的关键。

于 2013-05-01T01:57:24.353 回答