【问题标题】:Separate image of text into component character images将文本图像分离成组件字符图像
【发布时间】:2018-10-27 19:50:19
【问题描述】:

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

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

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

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


示例图片:

【问题讨论】:

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


    【解决方案1】:

    这不是一件容易的事,尤其是在背景不统一的情况下。如果你所拥有的是一个已经像示例这样的二进制图像,它会稍微简单一些。

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

    之后,您可以使用标记算法来识别形成您的形状的每个像素“岛”(在本例中为每个字符)。

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

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

    如果我能提供帮助,请询问;)

    【讨论】:

    • 感谢您的回复!在这一点上,我只对处理简单的图像感兴趣,比如我提供的示例,纯白色上的黑色文本。我稍后可能会考虑其他注意事项,因此感谢您的提示。那么标签算法呢?一个快速的谷歌让我从 OpenCV 库中获取了 cvBlobsLib,这似乎可以完成查找形状的工作。我不知道如何去保存它们,但我会试一试。
    【解决方案2】:

    我知道我迟到了几年 :-) 但是你现在可以很容易地用 ImageMagick 做这种事情,直接在命令行中,无需编译任何东西,因为它内置了 Connected Component Analysis:

    这是一种方法:

    #!/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
    

    结果如下:

    首先,我将您的图像阈值设置为 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
    

    【讨论】:

    • @Setchell,我在运行您的脚本时遇到此错误。转换:没有定义图像'word.png'@error/convert.c/ConvertImageCommand/3275。你能帮忙吗?
    • @ShreeshaN 你是如何运行它的?你用的是什么图片?您使用哪个版本的 ImageMagick?你在什么操作系统上?尝试在第一行末尾添加 `-xv`。
    • ImageMagick 版本 - 7.0.7-38,图像 - jpg/png,操作系统 - MacOS。添加 -xv 没有帮助。没有图像定义错误仍然存​​在
    • 你是如何运行它的?
    • 将其保存在 .sh 文件中并运行 sh filename.sh
    【解决方案3】:

    您可以从一个简单的连通分量分析 (CCA) 算法开始,该算法可以通过扫描线算法非常有效地实现(您只需跟踪合并的区域并在最后重新标记)。这将为每个连续区域提供单独编号的“斑点”,这适用于大多数(但不是全部)字母。然后,您可以简单地获取每个连接的 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 库应该为您完成大部分工作。

    【讨论】:

      【解决方案4】:

      嗯,对于您提供的示例,这实际上非常简单:

      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”,您必须查看每一列的 all

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

      【讨论】:

      • 这种方法有问题。步骤“再次向右直到没有黑色,字符结束”是不正确的。如果您正在处理“U”甚至“h”字符,黑色的结尾并不意味着字符的结尾,因为它们形成了两列像素,中间有空白。
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

        Djvu 套件中的许多工具已在标题 djvulibre 下开源;不幸的是,我无法弄清楚如何使用现有的命令行工具提取前景(或单个字符)。我很想看到这个完成。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-05-09
          • 2018-03-18
          • 2020-02-11
          • 1970-01-01
          • 1970-01-01
          • 2015-02-28
          • 2020-07-26
          • 2011-10-27
          相关资源
          最近更新 更多