【OCR项目】之用HALCON的深度学习工具进行文字识别,并导出到C++调用

前言

HALCON是一个强大的机器视觉工具,包含了2D,3D图像各种算子,以及各种任务的深度学习工具,包括目标检测,实例分割,文字识别等。

这次从实际生产的角度,来分享一下如何用HALCON进行文字识别。

衡量一个技术是否能在实际工业生产使用,要考虑的因素:

  • 最重要的一点,精度要高且稳定。在复杂的工业场景,需要能稳定的做到非常高的精度,而不是像简单的示例程序或者学生作品一样,只是学习和展示使用。这点HALCON的深度学习OCR可以满足大部分普通的工业场景。
    • 这里有一个细节,HALCON的版本越高,理论上提供的模型结构要越先进,预训练模型精度也越高。这里使用的是22.05的版本。
  • 速度要快。HALCON做深度学习OCR即使使用CPU进行识别,速度也非常快。
  • 需要能整合到实际开发的软件工程里。HALCON支持导出成C++,只需要少量的调整。

HALCON代码

HALCON的OCR和现在主流的字符识别任务一样,分成两阶段任务。

  • 文本检测Detection,识别出文本行的位置。
  • 文本识别Recognition,把Detection任务检测出来的文本行抠出来进行识别。

并且HALCON支持像上面图片这样倾斜的文字,下面是简单的实现代码和逐行解释。

* 读取图片
read_image (Image, 'D:/Project/OCR_demo.jpg')
* 获取显示窗口的句柄
dev_get_window (WindowHandle)
* 设置文字的字体和大小
set_font (WindowHandle, 'Courier New-Bold-' + round(26))
* 创建OCR识别句柄
create_deep_ocr ('mode', 'auto', DeepOcrHandle)
* 创建CPU/GPU设备句柄
query_available_dl_devices ('runtime', 'cpu', DLDeviceHandle)
* 设置OCR使用的设备
set_deep_ocr_param (DeepOcrHandle, 'device', DLDeviceHandle)* 记录开始时间
count_seconds(StartTime)
* 执行OCR
apply_deep_ocr (Image, DeepOcrHandle, 'auto', DeepOcrResult)
* 记录结束时间
count_seconds(EndTime)
* 计算耗时
Duration := EndTime - StartTime
* 绘制文字
write_string (WindowHandle, '耗时'+Duration+'s')* 获取结果
get_dict_tuple (DeepOcrResult, 'words', WordsRes)
* 获取文字区域的行坐标
get_dict_tuple (WordsRes, 'row', Rows)
* 获取文字区域的列坐标
get_dict_tuple (WordsRes, 'col', Cols)
* 获取文字区域的倾斜角度
get_dict_tuple (WordsRes, 'phi', Phis)
* 获取文字区域的矩形长边
get_dict_tuple (WordsRes, 'length1', Length1s)
* 获取文字区域的矩形短边
get_dict_tuple (WordsRes, 'length2', Length2s)
* 获取识别文字结果
get_dict_tuple (WordsRes, 'word', Words)
* 设置绘制模式为画轮廓
dev_set_draw('margin')
* 设置画线的宽度
dev_set_line_width (2)for Index := 0 to |Rows|-1 by 1* 绘制带方向的矩形disp_rectangle2(WindowHandle, Rows[Index], Cols[Index], Phis[Index], Length1s[Index], Length2s[Index])* 设置文字的坐标set_tposition(WindowHandle, Rows[Index],  Cols[Index])* 绘制文字write_string (WindowHandle, Words[Index])
endfor

上面的代码运行结果如下,可以看到HALCON在CPU上的速度也是非常快的。

导出C++

HALCON导出到C++也非常方便,只需要点击

【文件】-【导出程序】

需要注意的点是,上面的HALCON代码虽然在HALCON里运行没有问题,但是直接导出C++运行是会报错的。

因为上面使用的是HALCON自带的模型,导出C++之后,程序里是不带有这个模型的。所以需要将自带的模型导出,然后设置成使用这个模型来进行识别。

使用以下HALCON代码进行模型导出

* 创建自带的OCR模型
create_deep_ocr ('mode', 'auto', DeepOcrHandle)
* 设置导出模型的路径
Filename := 'D:/model.hdo'
* 导出模型
write_deep_ocr (DeepOcrHandle, Filename)

然后把上面的识别代码从创建默认OCR识别模型句柄,改成读取指定的模型。

* 创建OCR识别句柄
* create_deep_ocr ('mode', 'auto', DeepOcrHandle)
* 读取指定的模型
read_deep_ocr ('D:/model.hdo', DeepOcrHandle)

再进行C++代码导出,就可以使用了。

在C++工程里调用也非常简单,只需要包含halcon.dll,halconcppdll,halcondl.dll即可。

案例

在实际项目中,如果文字足够清晰,预处理足够干净,文本定位足够准确的话,即使使用默认的模型也能达到非常高的精度。

比如下面的例子,通过内容区域提取,透视变换,文本检测,文本位置精细定位,背景分割过滤等手段,将文本区域精准提取出来之后,直接使用默认的模型也可以达到很好的效果。

当然,在针对性的场景,通过标注对应的数据集,并在预训练模型的基础上进行针对性训练,可以达到一个更好的效果,这个步骤也很简单,后面机会再展开讲一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/421470.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Modbus网关BL101 既实现Modbus转MQTT,还能当串口服务器使用

随着工业4.0的迅猛发展,人们深刻认识到在工业生产和生活中,实时、可靠、安全的数据传输至关重要。在此背景下,高性能的工业电力数据传输解决方案——协议转换网关应运而生,广泛应用于工业自动化系统、远程监控和物联网应用应用环境…

持续集成工具Jenkins的使用之安装篇(一)

Jenkins是一个基于Java开发的开源的一种持续集成工具,主要用于环境部署,监控重复性的工作,旨在提供一个开放易用的软件平台,使软件项目可以进行持续集成。要想使用它,你就必须的先安装,接下来我们就介绍下J…

ctfshow-反序列化(web267-web270)

目录 web267 web268 web269 web270 总结 web267 页面用的什么框架不知道 看源码看一下 框架就是一种软件工具,它提供了一些基础功能和规范,可以帮助开发者更快地构建应用程序。比如Yii框架和ThinkPHP框架就是两个流行的PHP框架,它们提供…

【Linux多线程】生产者消费者模型

目录 生产者消费者模型 1. 生产者消费者模式的概念 2. 生产者消费者模型优点 ​编辑3. 生产者消费者模型的特点 基于BlockingQueue(阻塞队列)的生产者消费者模型 1.BlockingQueue 2. 使用CSTL中的queue来模拟实现阻塞队列 3. 基于任务的生产者消费…

html 会跳舞的时间动画特效

下面是是代码&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml"> <head> <meta h…

Spring Boot3.2.2整合MyBatis Plus3.5.5

目录 1.前置条件 2.导坐标 3.配置数据源 4.配置mapper扫描路径 5.MyBatis Plus代码生成器整合 1.导坐标 2.编写代码生成逻辑 1.前置条件 已经初始化好一个spring boot项目且版本为3X&#xff0c;项目可正常启动 2.导坐标 <dependency><groupId>com.baomid…

Mysql-全局锁、表锁、行锁

本文已收录于专栏 《数据库》 目录 全局锁概述说明开启方式应用场景 表锁概念说明实现方式意向锁 开启方式 行锁概念说明实现方式记录锁&#xff1a;间隙锁临键锁 总结提升 全局锁 概述说明 全局锁是是对整个数据库实例加锁&#xff0c;加锁后整个实例就处于只读状态&#xff…

PySide6/PyQt6中Qt窗口标志/窗口属性汇总,如何正确的设置窗口标志/窗口属性

文章目录 📖 介绍 📖🏡 环境 🏡📒 使用方法 📒📚 窗口标志汇总📚 窗口属性汇总📝 使用方法📝 注意事项⚓️ 相关链接 ⚓️📖 介绍 📖 在Qt框架中,窗口标志(window flags)是用于控制窗口的各种属性和行为的强大工具。它们通过设置窗口的属性,如边框…

eNSP学习——配置通过STelnet登陆系统

可运行的topo不知道为什么无法上传&#xff0c;有需要的话&#xff0c;可以评论或私信文章标题获取相应的资源&#xff0c;也可评论“日常实验”获取常用的实验&#xff08;大概有一百个左右&#xff0c;里面有各种功能的单独配置&#xff0c;也有综合实验&#xff09;。 由于T…

JUC并发编程与源码分析学习笔记(二)

二十九、多线程锁之线程锁知识概述 说说Java“锁”事 从轻松的乐观锁和悲观锁开讲 通过8种情况演示锁运行案例&#xff0c;看看我们到底锁的是什么 公平锁和非公平锁 可重入锁&#xff08;又名递归锁&#xff09; 死锁及排查 写锁&#xff08;独占锁&#xff09;/读锁&a…

【每日一题】670. 最大交换-2024.1.22

题目&#xff1a; 670. 最大交换 给定一个非负整数&#xff0c;你至多可以交换一次数字中的任意两位。返回你能得到的最大值。 示例 1 : 输入: 2736 输出: 7236 解释: 交换数字2和数字7。示例 2 : 输入: 9973 输出: 9973 解释: 不需要交换。注意: 给定数字的范围是 [0, 1…

【K12】python用科学函数写方程解串联电路问题

物理例题&#xff1a; 代码分析 构造方程&#xff1a; from sympy中导包&#xff1a;Eq(),solve() 列方程函数 Eq()列方程函数 列出I2RP,这里设置P为1 解方程函数 solve((方程1&#xff0c;方程2&#xff0c;方程3&#xff09;&#xff0c;&#xff08;未知量1&#xff…