【问题标题】:Identify text areas on a Talmud page识别塔木德页面上的文本区域
【发布时间】:2020-09-12 21:50:49
【问题描述】:

我有一个像这样的塔木德页面: 我想找到带有opencv 的文本区域以获得这样的结果,每个文本都将像这样独立:

在附图中,每个区域用不同的颜色标记,并且文本有一个数字,重要的是识别每个文本所属的区域,并将其与属于另一个文本的区域区分开来,数字顺序没关系。

根据文字之间的白色条纹,用眼睛做真的很容易,但我尝试用opencv做,但我做不到。

在下面的代码中,我尝试捕捉所有字母并将它们变成黑色矩形, 然后放大每个矩形以与相邻的矩形相遇, 所以文本的整个区域都是黑色的,文本之间会有一条清晰的白色条纹。

我不知道如何进行,不知道这是不是一个好方法。

public List<Rectangle> getRects(Mat grayImg)
{
    BlobCounter blobCounter = new BlobCounter();
    blobCounter.ObjectsOrder = ObjectsOrder.None;
    blobCounter.ProcessImage(grayImg);
    IEnumerable<Blob> blobs = blobCounter.GetObjectsInformation();

    var blackBlobs = grayImg.Clone;
    foreach (var b in blobs)
        blackBlobs.Rectangle(b.Rectangle.ToCvRect, Scalar.Black, -1);

    var widths = blobs.Select(X => X.Rectangle.Width).ToList;
    widths.Sort();
    var median = widths(widths.Count / (double)2);

    Mat erodet = new Mat();
    Cv2.Erode(grayImg, erodet, null, iterations: median);

    using (Window win = new Window())
    {
        win.ShowImage(erodet);
        win.WaitKey();
    }
}

在此先感谢,任何帮助将不胜感激。

补充说明:

如上图所示,文本区域不是矩形, 但这些区域可以描述为一堆大小不一的矩形的集合,一个在另一个之上。

注意,当两个矩形属于同一个文本时,不要将一个矩形排列在另一个矩形旁边,而只能将一个矩形排列在另一个矩形之上。

我想要实现的是这些矩形的集合,并知道每个矩形所属的文本。

答案可以是任何编程语言,尤其是C++ PythonC#

【问题讨论】:

  • 我不会在第一遍寻找矩形,我会寻找白线。查看如何进行光学过滤并找到一个将文本块识别为灰色但能够拾取空白区域的一维过滤器。沿每个方向扫描页面(例如,以每个字符高度 3 或 4 次扫描的频率)并构建由空白分隔的灰色斑点模型。这将需要一些试验和错误才能正确。如果页面没有很好地对齐(就像你展示的那样),那将会更加困难。如果是这样,您可能首先想做一些事情来弄清楚对齐方式,然后预先旋转一些东西
  • 你可以试试形态学操作erode。 kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(19,8)) out = cv2.morphologyEx(thresh, cv2.MORPH_ERODE, kernel)

标签: opencv image-processing computer-vision ocr image-segmentation


【解决方案1】:

我相信这个任务主要可以使用morphological operations来完成。
中更容易展示这个概念,但 有等效的操作。

我们首先粗略估计页面不同部分之间的差距大小。查看您的示例,间隙约为页面高度的 1%。

img = im2single(rgb2gray(imread('https://i.stack.imgur.com/LoV5x.jpg')));  % read the image into 1ch gray scale image in range [0, 1]
gap = ceil(size(img,1) * 0.01);  % gap estimation

首先,我们想使用图像dilation 创建一个掩码,使同一部分中的所有单词相互连接:

d1 = imdilate(img < 0.5, ones(gap));

结果为:

(如果不是因为打印机在每个部分底部添加的下一页中令人讨厌的单词,我们就会完成......)

有一些大的空缺没有被扩张,我们可以使用floodfill来补全:

f = imfill(d1, 'holes');

现在我们有了文本区域的完整掩码:

使用erosion 在不同部分之间切换:

e = imerode(f, ones(1, 5*gap));  % erosion only horizontally

导致分区正确,虽然太细了:

向后扩张

d2 = imdilate(e, ones(1, 5*gap));

给出这个二进制掩码:

您现在可以简单地查看此二进制掩码的connected components

我希望这对我来说算是“Daf Yomi”......


更新:
下一步 - 从线段到矩形多边形需要一些几何操作,我将在此处概述方法并将实现细节留给您。
最终,我们希望每个段都有一个边界polygon,基本多边形是段的矩形边界框。你必须实现这个“多边形”类。这个类的一个关键方法是“多边形减法”——即poly_result = poly_a - poly_b创建一个新的多边形poly_result,即poly_a减去poly_apoly_b之间的交集。

算法如下:

  1. 为每个段计算它的边界框、边界框的面积和段中的实际像素数。
    将每个线段的多边形初始化为其边界框。
  2. 根据像素数与边界框面积的比值,按降序对片段进行排序。
  3. 对于按降序排列的每个段:
    从此段中减去所有先前的多边形。

你应该得到这样的东西:


对于第二张图片:

【讨论】:

  • 谢谢,您如何将非矩形区域转换为几个矩形,这些矩形将像一堆一样覆盖该区域,正如我在问题中解释的那样?
  • 非常感谢,我不知道怎么弄matlab,请写一个可以在Python中运行并且可以运行的代码,这样我就可以检查一切是否也适合我。谢谢。
  • @googledev stackoverflow 不是为了“为我编写代码”,而是“帮助我编写自己的代码”。该答案逐步概述了算法,还包含对实现每个步骤输出的操作的 opencv 函数的引用。你应该可以从这里拿走它。我给了你塔木德 + Rashi,你需要自己做 Tosfot。
  • 注意,有些词在erotion之后是不会出现的。
  • @googledev 正如答案中所解释的,该算法基于使用形态学运算为每个文本区域形成一个“实心”掩码。为此,我们估计文本“块”内的行和单词之间的间隙大小。标题行显然不共享相同的“统计数据”——它的字数更少、间距大、字体大。因此,不“遵守”页面其余部分规则的标题行将需要单独处理。如果页面的其他部分有明显不同的行为 - 那么你是对的。
【解决方案2】:

据我所知,您首先尝试执行布局分析以提取感兴趣的区域。这是一个研究领域,不是很为人所知,但对这个问题有一些很好的结果。如果您不确定使用opencv 解决此问题,我建议您查看光学布局识别 (OLR)。 LAREX 开源工具是一个很好的起点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-12
    • 2010-11-16
    • 1970-01-01
    • 2015-03-01
    • 1970-01-01
    • 2013-06-27
    • 2015-10-23
    • 2011-05-14
    相关资源
    最近更新 更多