识别塔木德页面上的文本区域

Identify text areas on a Talmud page

我有一个像这样的犹太法典页面: 我想找到带有 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#

据我所知,您首先尝试执行布局分析以提取感兴趣的区域。这是一个研究领域,不是很出名,但对这个问题有一些很好的结果。如果您不确定使用 opencv 来解决此问题,我建议您查看 Optical Layout Recognition (OLR)。 LAREX open-source 工具是一个很好的起点。

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

我们首先粗略估计页面不同部分之间的差距大小。查看您的示例,间隙约为页面高度的 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));

结果为:

(如果不是因为打印机在每个部分的底部添加下一页的烦人文字,我们就已经完成了...)

有一些dilation没有填补的大空隙,我们可以用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,基本多边形是线段的矩形边界框。您必须实现这个“多边形”class。这个 class 的一个关键方法是“多边形减法”——即 poly_result = poly_a - poly_b 创建一个新的多边形 poly_result ,它是 poly_a 减去 poly_apoly_b.

算法如下:

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

你应该得到这样的东西:


对于第二张图片: