将文本图像分离为组件字符图像

时间:2009-12-29 00:22:38

标签: python image-processing python-imaging-library

我想将文本图像分成它的组成字符,也作为图像。例如,使用下面的示例,我最终会得到14张图像。

我只会在一行上使用文字,所以y高度并不重要 - 我需要找到的是每个字母的开头和结尾以及裁剪到那些坐标。这样我也可以避免'i','j'等问题。

我是图像处理的新手,我不知道如何去做。某种形式的边缘检测?有没有办法确定纯色的连续区域?任何帮助都很棒。

尝试提高我的Python技能并熟悉一些可用的库,所以我使用Python Imaging Library (PIL),但我也看过OpenCV。


示例图片:

This is some text

6 个答案:

答案 0 :(得分:5)

这不是一件容易的事,特别是如果背景不均匀的话。如果您拥有的是已经是二进制的图像,就像示例一样,它稍微简单一些。

如果您的图像不是二进制(Otsu自适应阈值效果很好),您可以开始应用阈值算法

您可以使用标记算法来识别形成您的形状的每个“孤岛”(在这种情况下为每个字符)。

当你有噪音时会出现问题。标记但不符合您兴趣的形状。在这种情况下,您可以使用一些启发式方法来确定形状是否为字符(如果文本位于定义良好的位置,则可以使用标准化区域,对象的位置等)。如果这还不够,你将需要处理更复杂的工作人员,如形状特征提取算法和某种模式识别算法,如多层感知器。

要完成,这似乎是一项简单的任务,但根据图像的质量,它可能会变得更难。这里引用的算法很容易在互联网上找到,也可以在OpenCv等一些库中实现。

如果我当然可以提供帮助,请再问一下;)

答案 1 :(得分:5)

我知道我迟到了几年:-)但你可以很容易地使用ImageMagick做这种事情,直接在命令行上编译而不编译任何东西,因为它内置了连接组件分析:

这是一种方法:

#!/bin/bash
image="$1"
draw=$(convert $image                              \
   -threshold 50%                                  \
   -define connected-components:verbose=true       \
   -define connected-components:area-threshold=10  \
   -connected-components 8                         \
   -auto-level objects.png | \
   awk 'BEGIN{command=""}
        /\+0\+0/||/id:/{next}
        {
          geom=$2
          gsub(/x/," ",geom)
          gsub(/+/," ",geom)
          split(geom,a," ")
          d=sprintf("-draw \x27rectangle %d,%d %d,%d\x27 ",a[3],a[4],a[3]+a[1],a[4]+a[2])
          command = command d
          #printf "%d,%d %d,%d\n",a[3],a[4],a[3]+a[1],a[4]+a[2]
        }
        END{print command}')

eval convert "$image" -fill none -strokewidth 2 -stroke red $draw result.png

结果如下:

enter image description here

首先,我将您的图像阈值设置为50%,以便其中只有纯黑色和白色,没有色调渐变。然后我告诉ImageMagick输出它找到的边界框的细节,并且我对小于10像素的总面积的对象不感兴趣。然后我允许像素8连接,即它们的对角线邻居(NE,SE,NW,SW)以及它们的左右和上下邻居。最后,我用awk解析边界框输出,在边界框周围绘制红线。

我用awk解析的初始命令的输出如下所示:

Objects (id: bounding-box centroid area mean-color):
  0: 539x53+0+0 263.7,24.3 20030 srgba(255,255,255,1)
  11: 51x38+308+14 333.1,30.2 869 srgba(0,0,0,1)
  13: 35x39+445+14 461.7,32.8 670 srgba(0,0,0,1)
  12: 35x39+365+14 381.7,32.8 670 srgba(0,0,0,1)
  2: 30x52+48+0 60.4,27.0 634 srgba(0,0,0,1)
  1: 41x52+1+0 20.9,16.6 600 srgba(0,0,0,1)
  8: 30x39+174+14 188.3,33.1 595 srgba(0,0,0,1)
  7: 30x39+102+14 116.3,33.1 595 srgba(0,0,0,1)
  9: 30x39+230+14 244.3,33.1 595 srgba(0,0,0,1)
  10: 35x39+265+14 282.2,33.0 594 srgba(0,0,0,1)
  16: 33x37+484+15 500.2,33.0 520 srgba(0,0,0,1)
  17: 22x28+272+19 282.3,32.8 503 srgba(255,255,255,1)
  5: 18x51+424+2 432.5,27.9 389 srgba(0,0,0,1)
  6: 18x51+520+2 528.5,27.9 389 srgba(0,0,0,1)
  15: 6x37+160+15 162.5,33.0 222 srgba(0,0,0,1)
  14: 6x37+88+15 90.5,33.0 222 srgba(0,0,0,1)
  18: 22x11+372+19 382.6,24.9 187 srgba(255,255,255,1)
  19: 22x11+452+19 462.6,24.9 187 srgba(255,255,255,1)
  3: 6x8+88+0 90.5,3.5 48 srgba(0,0,0,1)
  4: 6x8+160+0 162.5,3.5 48 srgba(0,0,0,1)

并且awk将其转换为此

convert http://imgur.com/AVW7A.png -fill none -strokewidth 2 -stroke red \
-draw 'rectangle 308,14 359,52'        \
-draw 'rectangle 445,14 480,53'        \
-draw 'rectangle 365,14 400,53'        \
-draw 'rectangle 48,0 78,52'           \
-draw 'rectangle 1,0 42,52'            \
-draw 'rectangle 174,14 204,53'        \
-draw 'rectangle 102,14 132,53'        \
-draw 'rectangle 230,14 260,53'        \
-draw 'rectangle 265,14 300,53'        \
-draw 'rectangle 484,15 517,52'        \
-draw 'rectangle 272,19 294,47'        \
-draw 'rectangle 424,2 442,53'         \
-draw 'rectangle 520,2 538,53'         \
-draw 'rectangle 160,15 166,52'        \
-draw 'rectangle 88,15 94,52'          \
-draw 'rectangle 372,19 394,30'        \
-draw 'rectangle 452,19 474,30'        \
-draw 'rectangle 88,0 94,8'            \
-draw 'rectangle 160,0 166,8' result.png

答案 2 :(得分:2)

您可以从简单的连通分量分析(CCA)算法开始,该算法可以通过扫描线算法非常有效地实现(您只需跟踪合并区域和最后的重新标记)。这将为每个连续区域提供单独编号的“blob”,这适用于大多数(但不是全部)字母。然后,您可以简单地获取每个连接的blob的边界框,这将为您提供每个blob的轮廓。在应用CCA提高效率时,您甚至可以维护边界框。

所以在你的例子中,CCA之后的左边第一个单词会产生类似的结果:

1111111  2         3
   1     2
   1     2 4444    5  666
   1     22    4   5 6
   1     2     4   5  666
   1     2     4   5     6
   1     2     4   5  666

等价类为4 = 2.

然后每个blob的边界框为您提供字母周围的区域。你会遇到像i和j这样的字母的问题,但它们可以是特殊的。您可以查找小于特定大小的区域,该区域位于特定宽度的另一个区域之上(作为粗略启发式)。

OpenCV中的cvBlobsLib库应该为您完成大部分工作。

答案 3 :(得分:2)

嗯,这对你提供的样本来说非常容易:

start at left edge
  go right 1 column at a time until the current column contains black (a letter)
  this is the start of the character
  go right again till no black at all in current column
  end of character
repeat till end of image

(顺便说一下,这也适用于将一个段落分成几行。)
如果字母重叠或共享列,则会有更多难度有趣。

编辑:

@Andres,不,它适用于'U',你必须查看每列的全部

 U   U
 U   U
 U   U
 U   U
  UUU
 01234

0,4:everything but bottom row
1-3:only bottom row

答案 4 :(得分:1)

我最近一直在玩ocropus,这是一个开源文本分析和ocr预处理工具。作为其工作流程的一部分,它还可以创建您想要的图像。也许这会对你有所帮助,虽然不涉及蟒蛇魔法。

答案 5 :(得分:1)

你提出的问题非常困难 - 它需要一些世界上最好的图像处理研究人员来解决。该解决方案是Djvu图像压缩和显示工具集的主要部分:压缩文档的第一步是识别前景并将其拆分为字符。然后他们使用这些信息来帮助压缩,因为一个小写的'e'的图像非常像另一个 - 压缩文档只需要包含差异。您可以在http://djvu.org/resources/找到一系列技术论文的链接;一个好的起点是High Quality Document Image Compression with Djvu

Djvu套件中的许多工具都是以djvulibre标题开源的;遗憾的是,我无法弄清楚如何使用现有的命令行工具拉出前景(或单个字符)。我很想看到这件事。