用于解析图像中的字符以进行 OCR 的算法



我正在研究 OCR,现在我正在努力将每个单独的字符与其他字符分开。例如,如果我有一个图像说以下内容:

12345678.90

我想检测每个数字在图像中的开始位置和结束位置的 x,y 坐标,以便我可以确定要处理多少个数字,然后解析出每个单独的数字/字符,并对其进行处理。

我已经设计了一个简单的算法来做到这一点,我想要一些关于如何改进它的意见/评论。

(在这个应用程序中,我只需要处理数字,但如果这个算法也可以解析出字母,那就更好了)。

  • 1)我会在图像底部以直线读取图像中的像素。例如,如果图像是 30x30,那么我将从 0,30 开始读取到 30,30。

  • 2)我将比较像素的颜色。已经确定了背景和前景色后,我将比较每个像素的颜色,看看它是在背景中还是在前景中。

  • 3)如果是背景,将被忽略。如果我在前景中遇到任何像素,这将表示数字的开始。在这种情况下,我会记下位置,然后开始向上读取像素。例如,如果在 5,30 处我检测到前景色,我将开始读取 5,29、5,28 等。

  • 4)我会向上读取像素(y轴),直到我在背景色中遇到像素。这应该给我角色的高度。(我知道对于像 5 这样的一些字符会更复杂,让我们暂时忽略它们)。因此,例如,我会确定该字符从 5,20 垂直变为 5,30。

  • 5
  • )然后我会回到x轴(5,30),在那里我水平检测角色的开始。我会继续水平阅读以确定字符的宽度,例如 6,30、7,30 等。

  • 6)这是棘手的步骤。我猜,在以下每个字符之间:

    12345678.90

背景颜色中有一个像素左右的间隙。而且它可能对我们不可见,但它就在那里,并且会被程序找到,因为逐个像素水平读取颜色。这会告诉它角色水平结束的位置。因此,例如,它可以检测到15,30的背景颜色像素。

  • 7)这就是算法,它应该给出每个字母开始和下一个字母开始的x,y坐标。在上面的示例中,字符将从 5,20 运行到 15,30,并且是 10x10。

这个算法可以改进吗,和/或我在步骤 6 上的假设是否正确?

我知道的一种常见的数字分割方法是滑动窗口。基本思想是您在数字图像上滑动一定大小的窗口。

滑动窗口的

每次移动都会生成一个图像(您只查看窗口覆盖的像素)。滑动窗口将很窄。现在可以训练分类器,它将滑动窗口映射到 1 或 0,其中 1 表示滑动窗口以 2 位数字的拆分为中心,0 表示相反。

您需要一些训练数据来训练分类器。或者你可以尝试使用无监督学习。

编辑:此视频可能很有用:https://www.youtube.com/watch?v=y6ga5DeVgSY

免责声明:我以前从未编写过任何类似 OCR 的软件。

对我来说,你的算法似乎有点不对劲,原因如下:

    1
  • 不是从底部找到第一个像素的地方开始的,因为您仍然有指向左侧的小笔划,位于 1 的顶部。
  • 2 只有几个像素高,因为您要直接向上移动,直到找到背景像素。
  • 由于与上述参数相同,3 将导致只有 1 x 1 像素。
  • 等。。。

我会尝试使用递归算法,该算法尽可能遵循前景色像素,而不会进入背景像素。当使用带有大字符的大图像时,这可能会导致堆栈溢出,因此最好在几个 for 循环中做到这一点,而不是使用递归函数。

如果你正在逐像素地发现一个角色,你可以使用这个过程来创建关于你的角色外观的矢量信息。我认为这将是识别角色的一个很酷的起点。

我没有

尝试编写OCR软件,但我们确实使用它,它(或可能)变得非常复杂。

目前还不完全清楚你的图像来自哪里;如果它是扫描的图像,那么有几个复杂的问题。 尤其是关于您的计划,即使数字之间存在间隙,它也可能无法垂直(扫描的页面不太可能完全笔直)。 其他因素包括"斑点" - 由图像或扫描仪上的污垢等引起的随机点。 如果您正在处理这种图像,您几乎肯定需要研究图像处理技术,该技术将许多不同的数学运算应用于整个像素数组,以执行纠偏(拉直图像)、去斑(去除随机点)等操作;边缘增强(加强从浅色到深色的变化以增强线条)。

您使用的"背景"和"前景色"颜色来看,您可能正在尝试从屏幕上"OCR"图像? 如果是这样(某种"屏幕抓取"过程),并且您知道(或可以使用)正在解释的特定字符形状进行训练,那么滑动窗口的变体可能会有所帮助:您将"5"的已知图像以不同的偏移量在图像周围滑动:如果"5"的所有像素都与图像中的"前景"像素匹配, 然后你知道你找到了"5"。 对其他数字重复此操作。 如上所述,这是我们正在谈论的"虚拟"窗口。

最新更新