【问题标题】:Understanding Freeman chain codes for OCR了解用于 OCR 的 Freeman 链码
【发布时间】:2011-10-06 19:21:25
【问题描述】:

请注意,我真的在寻找我的问题的答案。我不是在寻找一些源代码或一些学术论文的链接:我已经使用了源代码并且我已经阅读了论文,但仍然没有弄清楚这部分的最后一部分问题...

我正在开发一些快速屏幕字体 OCRing,并且我取得了很好的进展。

我已经找到基线,分离字符,将每个字符转换为黑白,然后对每个字符进行轮廓化,以便对其应用弗里曼链码。

基本上它是一个 8 连接的链码,如下所示:

  3  2  1
   \ | /
  4-- --0
   / | \
  5  6  7

所以,如果我有一个“a”,经过所有的转换(包括转换为黑白),我最终会得到这样的结果:

11110
00001
01111
10001
10001
01110

然后它的外部计数可能看起来像这样(我可能在这里犯了一个错误,那是 ASCII 艺术轮廓,我的“算法”可能会弄错轮廓,但这不是我问题的重点):

 XXXX
X1111X
 XXXX1X
X01111X
X10001X
X10001X
 X111X
  XXX

在 X 之后,我得到了链码,即:

0011222334445656677

请注意,这是规范化的链码,但您始终可以像这样规范化链码:您只需保留最小的整数。

(顺便说一句,有一个超级高效的实现可以找到链码,您只需在其中获取“X”的 8 个相邻像素,然后如果您有 0,1,则在 256 查找表中查找, 2,3,4,5,6 或 7)

然而,我现在的问题是:从那个 0011222334445656677 链码中,我如何发现我有一个“a”?

因为,例如,如果我的 'a' 看起来像这样:

11110
00001
01111
10001
10001
01111  <-- This pixel is now full

那我的链码现在是:0002222334445656677

然而这也是一个'a'。

我知道这些链码的全部意义在于对如此微小的变化具有弹性,但我不知道我应该如何找到哪个字符对应于一个链码。

我已经走了那么远,现在我被困住了......

(顺便说一句,我不需要 100% 的效率,区分 '0' 和 'O' 或 'o' 并不是真正的问题)

【问题讨论】:

  • 您可能已经阅读过它,但这里的描述:codeproject.com/KB/recipes/OCR-Chain-Code.aspx 似乎提供了一个很好的起点。我的看法是,您需要通过输入识别的样本来“训练”您的软件,然后在输入真实数据时,让它识别“最接近”的匹配。您不必能够说明输入绝对是“a”,您只需能够说它比您感兴趣的任何其他符号更接近“a”并且足够接近变成你愿意接受的“a”。
  • @forsvarir:感谢您提供的链接,我已经阅读了几本,但我还没有阅读。这就是说我同意你的观点,但实际上是选择“最接近的”给我带来了问题。你知道我应该运行类似 "Levenhstein Edit Distance" 来找到最近的吗?这基本上是我的问题:我不知道如何选择最接近的输入,也不知道需要输入多少输入。
  • 我认为 Levenhstein 编辑距离可能行不通:它不适用于不同尺寸的 a。
  • 一个人工神经网络可以提供很好的结果。 AFN 非常适用于输入端的微小变化不会改变输出的应用。但正如我在(已经提到的)代码项目网站A C# Project in Optical Character Recognition (OCR) Using Chain Code 上读到的,支持向量机K 最近邻欧几里得距离 也是可能的分类阶段的方法。
  • 你说的是“a的大小不同”的问题:为什么不把输入的字符在分类前缩放到统一的大小——也许是把链码压缩成固定的长度?

标签: algorithm ocr


【解决方案1】:

你需要的是一个函数d,它可以测量链码之间的距离。然后找到给定链码的字母很简单:

输入:

  • 标准化链码S 用于可能的字母集(通常是 A-Z、a-z、0-9、...的链码)
  • 需要检测的字母的链码x,可能会轻微变形(链码与集合S中的任何链码都不匹配)

该算法将遍历一组可能的链码并计算每个元素的距离d(x,si)。距离最小的字母将是算法的输出(识别出的字母)。

我建议遵循距离函数: 对于两个链码,将每个方向的长度差相加:d(x,si) = |x0-si0| + |x1-si1| + .. + |x7-si7|x0是链码x中0的个数,si0是链码si中0的个数等

一个例子可以更好地解释我的想法。下图中有字母8、B、D,第四个字母是稍微变形的8,需要识别。字母用 Arial 书写,字体大小为 8。图像中的第二行放大了 10 倍,以便更好地看到像素。

我手动计算(希望是正确的)标准化链码,它们是:

8:  0011223123344556756677
B:  0000011222223344444666666666
D:  00001112223334444666666666
8': 000011222223344556756666 (deformed 8)

长度差异(绝对值)为:


direction | length         | difference to 8'
          | 8 | B | D |  8'|   8 |  B |  D |
----------+---+---+---+----+-----+----+-----
        0 | 2 | 5 | 4 |  4 |   2 |  1 |  0 |
        1 | 3 | 2 | 3 |  2 |   1 |  0 |  1 |
        2 | 3 | 5 | 3 |  5 |   2 |  0 |  2 |
        3 | 3 | 2 | 3 |  2 |   1 |  0 |  1 |
        4 | 2 | 5 | 4 |  2 |   0 |  3 |  2 |
        5 | 3 | 0 | 0 |  3 |   0 |  3 |  3 |
        6 | 3 | 9 | 9 |  5 |   2 |  4 |  4 |
        7 | 3 | 0 | 0 |  1 |   2 |  1 |  1 |
----------+---+---+---+----+-----+----+-----
                        sum   10 | 12 | 14 |

8'8的链码距离最小,因此算法会识别出字母8。到字母B的距离并没有大多少,但这是因为变形后的8看起来和B差不多。

此方法不是缩放不变的。我认为有两种选择可以克服这个问题:

  • 对于不同的字体大小,具有不同的规范化链码集
  • 一组大尺寸(例如 35x46 像素)的标准化链码,并将输入字母(需要识别)缩放到这个更大的尺寸。

我不太确定距离函数对于所有字母数字字母的集合是否足够好,但我希望如此。为了尽量减少识别字母的错误,您可以在分类步骤中加入其他特征(不仅是链码)。再一次,你需要一个距离测量——这次是特征向量。

【讨论】:

  • +1 惊人的答案。是的,我确实已经在使用其他功能来丢弃明显的不匹配项或保留明显的可能匹配项(同时非常小心误报/漏报)。它工作得很好,但我很乐意使用链码的帮助:)
  • 那个距离函数,你是自己想出来的还是你知道它被链码算法使用了?你以前知道这些链码吗?
  • 我之前对链码一无所知。距离函数是我的第二个想法。我的第一个想法是(在查看变形 8 的链码时)旋转一个链码,直到找到最佳匹配(两个链码之间的链码位置最多对应)。但是后来我想到了一个非常简单的解决方案(每个方向的长度),它也应该会产生良好的效果,所以我将其作为答案。
  • 我还对距离函数进行了网络搜索。我没有找到这样的功能,但有两篇有趣的论文:Application of Freeman Chain Codes: An Alternative Recognition Technique for Malaysian Car PlatesA Complete Bangla OCR System for Printed Chracters
  • 为什么你有 B 0000011 的情况?当它只是对角向右移动一次时..与D相同...?
【解决方案2】:

由于您的问题不够具体(您是想要基于链码的完整算法还是只是一些概率分类),我会告诉您我对这个问题的了解。

使用链码,您可以计算符号的一些属性,例如344445、244445、2555556、344446(4 的任意数量)形式的 旋转次数,即字母上的“尖峰”。假设链码中有 3 个部分看起来像这样。所以,这几乎可以肯定是“W”!但这是一个很好的案例。您可以计算不同类型的旋转次数,并将其与之前保存的每个字母的值进行比较(您手动完成)。 这是一个很好的分类器,但当然,仅靠它是不够的。它不可能区分“D”和“O”、“V”和“U”。很大程度上取决于您的想象力。

您应该首先创建一个带有参考的字母图像的测试用例,并在更改和发明新标准之间检查您的算法。

希望这至少部分回答了您的问题。

更新: 一个好主意突然出现在我的脑海中:) 您可以计算链中单调序列的数量,例如,对于链 000111222233334443333222444455544443333(一个简单的愚蠢示例,并不真正对应任何字母)我们有
00011122223333444 333322244445554443333,
00011122223333444 3333222 444455544443333,
000111222233334443333222 4444555 44443333,
0001112222333344433332224444555 44443333,

即四个单调子序列。

这应该是一个很好的概括,只计算真实字母的这种变化的数量,并与从检测到的链中获得的变化进行比较,这是一个很好的尝试。

一些问题和想法:

  1. 链在某种程度上是循环的,因此您应该处理检测链末端的单调性(以避免一个错误),
  2. 应该考虑一些伪影,例如,如果您知道字母足够大(例如,高度为 20 像素),您可能希望忽略短于 3 项的单调中断,例如 :)

【讨论】:

  • +1,你敢打赌!但是仍然:您能否详细说明我将如何进行计数/查找?是否有任何特定的数据结构会有所帮助?我完全了解“D”/“O”/“0”问题,这不是问题:我不需要 100% 的准确度。
  • @unkulunkuly:另外,我需要做些特别的事情才能让你在 6 天内获得赏金吗?
  • @SyntaxT3rr0r,对不起,我从来没有实现过这样的算法,我只记得我听过的一些课程中的这个想法,讲师提到了这个,但没有给出具体的例子。我认为我们应该等待更长的时间才能得到答案,我也会感兴趣:)
  • @SyntaxT3rr0r,我认为没有办法推迟赏金。如果你不及时提出,它就会丢失,除非有人写了一个至少得到 +2 的答案,在这种情况下她会得到一半的赏金。
  • 最好不要失去赏金。如果您是唯一一个回答的人,我如何确保您获得赏金?
【解决方案3】:

您可以将链码转换为更简单的模型来传达拓扑,然后运行机器学习代码(可能会在 Prolog 中编写)。

但我不会赞同它。人们已经这样做/尝试了很多年,但我们仍然没有好的结果。

与其在这种基于非线性/阈值的方法上浪费时间,不如直接使用基于相关性的稳健技术?最简单的方法是与模板进行卷积。

但我会在字母上开发 Gabor 小波,并将系数排序到向量空间中。通过一些示例训练支持向量机,然后将其用作分类器。

这几乎就是我们大脑的工作方式,我相信它在计算机中是可能的。

一些随意的闲聊(忽略):

我不会使用神经网络,因为我不了解它们,因此不喜欢它们。 然而,Geoff Hintons 小组http://www.youtube.com/watch?v=VdIURAu1-aU 的工作给我留下了深刻的印象。

不知何故,他在可以向后传播信息的网络(深度学习)上工作。 有一个关于他的谈话,他让一个训练有素的数字识别网络梦想成真。这意味着他将其中一个输出神经元设置为“2”,网络将在输入神经元上生成它认为是两个的事物的图片。

我觉得这很酷。

【讨论】:

    【解决方案4】:

    上个月,我也在处理同样的问题。现在,我通过vetex链码解决了这个问题。

    vetex链码是二进制链码。然后,我把它切成5份。显然,数字0-9在不同的部分都有自己的特点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-10
      • 2019-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-05
      • 1970-01-01
      • 2016-11-04
      相关资源
      最近更新 更多