石鑫华视觉论坛

 找回密码
 注册会员
查看: 3180|回复: 2

[转载] Halcon的OCR字符识别算法技巧总结

[复制链接]
  • TA的每日心情

    4 小时前
  • 签到天数: 3384 天

    连续签到: 6 天

    [LV.Master]2000FPS

    发表于 2021-12-28 17:49:46 | 显示全部楼层 |阅读模式 来自:广东省东莞市 电信

    注册登陆后可查看附件和大图,以及购买相关内容

    您需要 登录 才可以下载或查看,没有账号?注册会员

    x
    本文转自:https://www.cnblogs.com/xh6300/p/13392610.html
    Halcon的OCR字符识别算法技巧总结


    一、重要算子
    OCR分类器其实有很多,如下图所示。但是通常mlp分类器效果较好,使用较多。
    1002191-20200728172901027-43222378.png

    主要算子如下:
    ① append_ocr_trainf(Character, Image : : Class, TrainingFile : )
    四个参数分别是:字符Region、字符Image、字符文本、OCR训练的.trf文件路径

    如果该路径下不存在.trf文件,那么它会自动生成该文件。
    该算子作用是将单个字符区域、单个字符图像和对应的字符文本写入TrainingFile 文件。

    ② read_ocr_trainf_names( : : TrainingFile : CharacterNames, CharacterCount)
    查询.trf训练文件中存储有哪些字符,以及每个字符在训练器中的数量。

    ③ create_ocr_class_mlp(42, 67, 'constant', 'default', CharacterNames, NumHidden, 'none', 10, 42, OCRHandle)
    最前面的两个参数分别指字符的宽度高度。NumHidden指隐藏层的层数,一般不宜过低。

    ④ trainf_ocr_class_mlp( : : OCRHandle, TrainingFile, MaxIterations, WeightTolerance, ErrorTolerance : Error, ErrorLog)
    训练神经网络,通常参数用默认值即可。

    ⑤ write_ocr_class_mlp( : : OCRHandle, FileName : )
    保存OCR的的.omc分类器到文件。

    ⑥ read_ocr_class_mlp( : : FileName : OCRHandle)
    从文件中读取OCR的.omc分类器。

    一个典型的创建OCR分类器的过程通常是:
    append_ocr_trainf → create_ocr_class_mlp → trainf_ocr_class_mlp → write_ocr_class_mlp

    具体创建OCR分类器的方法,可以看这个例子:Halcon自动化训练OCR分类器举例


    二、关键问题
    1、create_ocr_class_mlp算子中,如何确定字符的宽度和高度?

    同一种字体不同字符的宽度、高度是不一样的(例如字母A和I),如何确定这两个值?
    有两种方式:一是直接测量字符中较宽字符的宽度和高度,把它们作为 WidthCharacterHeightCharacter ;二是使用OCR助手(助手——打开新的OCR)来分析得出这两个值(推荐这种方式)。
    1002191-20200728172924779-2144825247.png

    转到“分割”页面即可看到自动分析得出的“字符宽度”和“字符高度”等信息。
    1002191-20200728172944053-534123238.png

    2、使用自己训练的OCR分类器,还是使用Halcon自带的分类器?

    如果字体恰好合适的话,使用Halcon自带的分类器,通常效果是极好的。但是缺点也很明显:一是选择有限,如果需要OCR的字体比较特殊,可能选不好合适的分类器;二是你很难对Halcon自带的分类器进行优化,因为它只提供.omc文件,而不提供训练用的.trf文件

    自己训练的分类器也有优缺点。训练和使用分类器主要使用下面几个算子:
    append_ocr_trainf、create_ocr_class_mlp、trainf_ocr_class_mlp、do_ocr_multi_class_mlp

    缺点一是需要自己切割字符收集字库,如下所示:
    1002191-20200728172956272-828200144.png
    缺点二是可能自己训练的分类器不如Halcon自带的分类器效果好。(原因一方面因为字库不够丰富,另一方面可能对OCR的理解不够深刻,导致训练分类器时有些细节考虑不周全)
    不过自己训练分类器也有优点,最大的的优点是训练过程可控,而且自己可以添加字符图片,丰富字库,即分类器可以不断得到优化。这一点是Halcon自带的分类器所不具备的。

    3、如果使用Halcon自带的分类器,如何选择合适的?

    点击OCR助手中的下图中的红框中的图标即可。
    1002191-20200728173010170-1934216558.png

    先加载“训练文件”(.trf),再加载“分类器”(.omc),即可看到识别结果及其把握度。当所有字符均识别正确,且把握度很高的时候,就说明这个分类器很合适。
    1002191-20200728173021264-483484818.png

    4、如何准确分割出图像中的字符区域?

    OCR的过程实际是调用do_ocr_multi_class_mlp算子。
    do_ocr_multi_class_mlp(Character, Image : : OCRHandle : Class, Confidence)

    其中Character即是字符区域(Region),如下所示:
    1002191-20200728173036757-1706453358.png

    分割字符区域的思路有两种:① 用形态学阈值分割;② 用find_text系列算子。
    形态学分割算子大家比较熟悉,不需要多说,但是算子之间的组合比较灵活,思路比较重要。

    find_text分割字符区域代码举例如下:(Characters即是字符区域Region)
    1002191-20200728173047158-1080585764.png
    注:如果自己训练OCR分类器,create_text_model_reader就不需要传入.omc文件路径,例如:
    create_text_model_reader ('manual', [], TextModel)

    5、对于字符区域分割,形态学阈值分割和find_text方法,哪种更好?

    通常来说,直接用find_text系列算子,很容易得到比较不错的字符区域分割结果。因为它可以通过set_text_model_param算子设置很多字体的信息参数,例如:
    1002191-20200728173119364-721198310.png

    这种方法的优点很明显:就是很容易做到标准化。只需要设置几个参数,就可以得到很好的分割效果。
    但是这种方法的缺点也很明显,它的自由度有点差,效果不理想时,继续优化的办法有限。如果该设的参数都设置了,分割字符区域效果还是不理想,该怎么办呢?

    因此,对于经验丰富的视觉算法工程师,对于棘手的OCR项目,我仍然推荐使用形态学阈值分割来分割字符区域(Region),不过这个需要相当的技巧。

    6、提高字符区域分割效果的技巧。

    提高OCR准确率有两条路子:① 训练分类器时,尽量用丰富的字符图片库,训练出良好的分类器;② 识别前,尽量分割出准确的字符区域,好利于识别。

    训练分类器的过程中,其实能玩出的花样并不多。因此重点还是在分割字符区域这一步,建议如下:

    (1)尽量把需要OCR的文字图像转正。
    (2)可以用reduce_domain算子把需要OCR的图像区域挖出来,排除图像其他区域的干扰。
    (3)分割之前可以增强图像的对比度,例如使用scale_image_max和emphasize算子。
    (4)改变图像中字符笔画宽度的算子gray_erosion_rect可尝试使用,但是如果字符本身比较小,这个算子就不建议使用了,因为此时它对字符笔画的宽度改变会很大。
    (5)如果图像光照情况基本一致,尽量使用threshold而不是binary_threshold这类自动阈值算子。因为threshold的结果是可预测的,而自动阈值的分割结果通常较难预测。
    (6)阈值分割以后,可以使用select_shape算子限定一些筛选条件,筛选出真正的字符部分。

    特别注意:训练分类器的程序和正式识别字符的程序中,图像预处理和阈值分割方式必须一致,这样才能得到最好的OCR效果。

    7、对于识别错的“相似”字符的补救措施。

    有些字符是很相似的,例如字母“Q”和“O”,字母“I”和数字“1”。
    1002191-20200728173137289-1168915320.png
    对于上图的Q和O,如果容易识别混淆,那么如何判断到底是Q还是O呢?

    提供一种思路:可以求字母内部的空白区域,调用算子:convexity (CharRegion, Convexity)
    这个算子可以获得Q或者O内部区域的“凸度”,凸度极高的,说明这个字符是O,反之就是Q。

    其他字符也可以用其他方法分别个性化判断。

    另外,对于OCR,可以观察图中字符的分布,例如某一块区域只可能出现数字,但是识别出了形如“058I”这样的结果,那么很可能就是把数字“1”错判为了字母“I”。这时可以人为把字母“I”改成数字“1”作为后续补救措施。

    至于其他未提到的OCR技巧,欢迎留言补充。



    回复

    使用道具 举报

    该用户从未签到

    发表于 2021-12-31 09:43:15 | 显示全部楼层 来自:广东省深圳市 移动
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    昨天 22:11
  • 签到天数: 1202 天

    连续签到: 13 天

    [LV.10]1000FPS

    发表于 2022-2-21 18:06:14 | 显示全部楼层 来自:台湾省 中华电信(HiNet)数据中心
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册会员

    本版积分规则

    LabVIEW HALCON图像处理入门教程(24.09)
    石鑫华机器视觉与LabVIEW Vision图像处理PDF+视频教程11种全套
    《LabVIEW Vision函数实例详解2020-2024》教程-NI Vision所有函数使用方法介绍,基于NI VISION2020,兼容VDM21/22/23/24

    QQ|石鑫华视觉论坛 |网站地图

    GMT+8, 2024-11-22 12:50

    Powered by Discuz! X3.4

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表