2013-04-30 50 views
0

我开发了一个应用程序,用于在不同光照条件下在C#中提取文本。图像中文本的局部阈值或二值化

我的问题是,有时在图像中不同的亮度级别,像这样:

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

,所以我不能利用预先计算的门槛,整个图像,否则我将失去一些字母。

我正在寻找一个算法/片段/函数或其他,可以适用于正确的阈值/二值化图像。

我在AForge创建了thhis BradleyLocalThresholding,比其他非自适应方法要好,但是它放宽了一些细节。 (例如图像中的G变为O)

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

+0

您是否尝试过用“T”个玩弄?也许你可以尝试几种价值观,并就它是什么字母使用共识。 * Disclamer:我从来没有做过任何reall图像处理,只读了你发布的链接上的评论。* – Cemafor 2013-04-30 20:48:48

+0

我试过的最好的t值,大部分字母都很好,但'G'变成'O '(所以加太多),'L'变成'I'(所以减得太多)。 我玩过窗口大小,但没有结果。 – Univers3 2013-04-30 21:00:25

回答

2

是的,使用niblack(opencv有它作为一个函数) - 基本上它使用本地平均来构造一个变量theshold。它最适合OCR。根据图像分辨率的不同,您可能也希望双倍上采样2倍或3倍的倍数。

+0

嗨,你可以在OpenCV中显示niblack或bicubical upsamle函数的位置? 我在网上搜索了它的文档,但没有结果。 – Univers3 2013-04-30 21:14:47

+1

使用类型ADAPTIVE_THRESH_MEAN的cv :: adaptiveThreshold()和使用cv :: resize调整大小的类型INTER_CUBIC – 2013-04-30 22:35:09

0

除了局部阈值之外的其他选项是调整变化的照度。有些方法试图纠正照明并使其在整个图像上均匀。然后,您可以使用恒定的阈值,或继续使用本地阈值,也许可以取得更好的成效。如果图像与您展示的图像相似,则可以使用字母周围较亮的方块作为调整照明的关键。

+1

光照校正也使用本地平均值,因此与niblack没什么区别,除了它需要额外的步骤。如果你正在寻找的唯一东西是OCR的文本,那么真的没有意义。 – 2013-05-02 12:54:01

+0

照明可应用于宏视图,因为图像上的失真是渐变和连续的。它可以在应用自适应阈值之前以非均匀的方式减小局部区域的方差。 – denver 2013-05-02 16:58:42

2

其相当困难的,因为你的图像质量是如此之低,但可以按如下方式尝试迭代全局阈值的方法:

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

诀窍是不是将它应用到整个图像,但打破了图像分割为(例如)5×5块,并将其应用到块单独这将使您:

enter image description here

下面是R中的实现,我相信你能重现

 
getT = function(y){ 
    t = mean(y) 

    mu1 = mean(y[y>=t]) 
    mu2 = mean(y[y 1){ 
     cmu1 = mean(y[y>=t]) 
     cmu2 = mean(y[y 1 & cmu1 == mu1 & cmu2 == mu2){ 
     print(paste('done t=', t)) 
     return(t) 
     break; 
    }else{ 
     mu1 = cmu1 
     mu2 = cmu2 
     t = (mu1 + mu2)/2 
     print(paste('new t=', t)) 
    } 
    i = i+1 
    } 
} 


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

display(y) 
+0

非常好的例子,但我不认为是足够的强大的字符识别。 BradleyLocalThreshold的结果现在好得多。 – Univers3 2013-05-03 21:43:55

+0

足够公平:-)是否有一个原因,图像质量如此之低? – by0 2013-05-03 23:05:14

+0

我同意,图像质量太低,通过改变捕获方法可能会更容易。 – 2013-05-04 01:29:07