OCR 图像预处理

Posted

技术标签:

【中文标题】OCR 图像预处理【英文标题】:OCR Image preprocessing 【发布时间】:2016-03-10 13:53:07 【问题描述】:

我一直在使用 OCR 的 Office 文档成像来从图像中获取文本。对于这张图片,

我想知道在将图像输入 OCR 之前提高图像质量所涉及的预处理步骤。到目前为止,我已经尝试过二值化(阈值)、模糊(高斯)、锐化、平均去除和增加图像的亮度和对比度,但 OCR 引擎仍然无法获得准确的文本(可能成功率为 50%)。

我想知道预处理步骤(按正确顺序)以提高 C# 中的质量。屏幕图像是通过网络摄像头捕获的。谢谢。

【问题讨论】:

【参考方案1】:

我在 C++ 中使用我的 DIP 库对您的图像进行了一些操作,结果如下:

picture pic0,pic1;
pic0.load("ocr_green.png");
pic0.pixel_format(_pf_u);       // RGB -> Grayscale <0-765>
pic0.enhance_range();           // remove DC offset and use full dynamic range <0-765>
pic0.normalize(8,false);        // try to normalize ilumination conditions of image (equalize light) based on 8x8 sqares analysis, do not recolor saturated square with avg color
pic0.enhance_range();           // remove DC offset and use full dynamic range <0-765>
pic1=pic0;                      // copy result to pic1
pic0.pixel_format(_pf_rgba);    // Grayscale -> RGBA
int x,y,c,c0,c1;
for (y=0;y<pic1.ys;y++)         // process all H lines
    
    c0=pic1.p[y][0].dd; c1=c0;  // find min and max intensity in H line
    for (x=0;x<pic1.xs;x++)
        
        c=pic1.p[y][x].dd;
        if (c0>c) c0=c;
        if (c1<c) c1=c;
        
    if (c1-c0<700)              // if difference not big enough blacken H line...
     for (x=0;x<pic1.xs;x++) pic1.p[y][x].dd=0;
    else                        // else binarize H line
     for (x=0;x<pic1.xs;x++)
      if (pic1.p[y][x].dd>=155) pic1.p[y][x].dd=765; else pic1.p[y][x].dd=0;
    
pic1.pixel_format(_pf_rgba);    // Grayscale -> RGBA

左图 (pic0) 是您的图像,已转换为灰度、增强的动态范围至最大和均衡照明。

见:Enhancing dynamic range and normalizing illumination 你还会发现我的picture 类的描述...

正确的图像 (pic1) 已二值化,但仅适用于像素强度变化足够高的水平线(如我的评论中所述)...其余设置为黑色...

【讨论】:

我尝试实现你的代码,因为我使用字节指针来访问每个颜色组件,我不确定如何使用值 0-765。你能解释一下吗?我假设它是所有 3 个颜色分量的总和。对吗? @Questions 你有什么像素格式?如果你有 RGB 24/32 bit 那么每个 BYTER,G,B=&lt;0,255&gt; ...当我使用灰度时,我只是将 R,G,B 加在一起得到 I=R+G+B=&lt;0,3*255=765&gt; 来简化事情......如果你想回到 RGB 然后只是 R=G=B=I/3; 那就是 pixel_format 无论如何我的每个像素都是 DWORD dd; DWORD dw[2]; BYTE db[4]; 的联合所以我可以很容易地访问像素作为 32bit, 2x16bit or 4x8bit 值对应全彩色,部分推导在派生和 r,g,b,a 分量后 我使用的是 RGB32。我将您的代码转换为 c#,它看起来像这样,但它会使整个图像变黑。 pastebin.com/EZvepnFD @Questions 您的来源看起来不错,但是由于您没有应用增强动态范围和标准化照明步骤,因此您的阈值会有所不同,您需要使用值 700 和 @987654338 @ 直到你得到想要的输出。由于光照条件不同,图像右侧可能会出现噪点 @Questions 尝试使用520 而不是700 并保留155 原样【参考方案2】:

此图像的 OCR 质量非常好。它将无缝二值化。根据引擎,您将自己执行二值化或让引擎执行。

可能您必须将底部区域变黑以便字符分开。由于屏幕布局是固定的,因此可以轻松实现自动化。

您还需要检查此 OCR 是否知道此字体。

您可以通过轮廓分析(水平累积)来划定白色区域。

【讨论】:

使用您的图像,OCR 几乎可以完美地获取文本,只是它无法识别字体的某些字符。我能够对其进行二值化,但由于文本可能会动态出现在多行中,我不确定如何使底部区域变黑。在这种情况下有什么方法可以自动化它? @Questions 我会首先检测水平线是否有任何黑色像素,如果是,则只有然后将其二值化,否则将其设置为黑色......所以你记得最暗和最亮的颜色,如果它们的强度差异是够高... @Questions:通过沿水平方向累积像素值,白色区域并不难定位。然后进行轮廓分析。 (见新图片。)

以上是关于OCR 图像预处理的主要内容,如果未能解决你的问题,请参考以下文章

首先有啥好的算法可以捕捉到像样的图像?之后是预处理/图像清洁,最后是 OCR 程序?

对低质量数字图像进行 OCR 的预处理方法?

实时图像处理(OCR)[关闭]

OCR中的图像预处理

改进 OCR/图像识别的预处理

Python图像处理之图片文字识别(OCR)