文章目录
-
-
- 1,介绍
-
- [1.1 核心定义与技术特点](#1.1 核心定义与技术特点)
- [1.2 完整应用流程](#1.2 完整应用流程)
- 1.3,关联文件介绍。
-
- [1.3.1 训练文件:`.trf`文件](#1.3.1 训练文件:
.trf文件) - [1.3.2 分类器文件:`.omc`文件、`.occ`文件](#1.3.2 分类器文件:
.omc文件、.occ文件) - [1.3.3 三种文件的区别](#1.3.3 三种文件的区别)
- [1.3.1 训练文件:`.trf`文件](#1.3.1 训练文件:
- 1.4,常用的识别方式
- 2,预处理
- 3,常见应用案例
- 4,OCR助手应用
-
- 4.1,OCR训练文件浏览器
-
- [4.1.1 打开浏览器。](#4.1.1 打开浏览器。)
- [4.1.2 创建或者加载训练文件。](#4.1.2 创建或者加载训练文件。)
- [4.1.3 浏览样本。](#4.1.3 浏览样本。)
- [4.1.4 生成样本变形,增加样本(可选)。](#4.1.4 生成样本变形,增加样本(可选)。)
- [4.1.5 系统字体添加为训练样本(可选)。](#4.1.5 系统字体添加为训练样本(可选)。)
- [4.2 OCR助手](#4.2 OCR助手)
-
- 4.2.1,OCR字符识别
- 4.2.2,OCR训练样本(可选)。
-
- [4.2.2.1 新建训练文件或者打开已有的训练文件。](#4.2.2.1 新建训练文件或者打开已有的训练文件。)
- [4.2.2.2 对样本进行标记。](#4.2.2.2 对样本进行标记。)
- [4.2.2.3 添加并保存样本至训练文件。](#4.2.2.3 添加并保存样本至训练文件。)
- [4.2.2.4 配置训练参数,训练样本。](#4.2.2.4 配置训练参数,训练样本。)
- [4.2.2.5 训练完成,生成分类器文件。](#4.2.2.5 训练完成,生成分类器文件。)
-
1,介绍
Halcon中的OCR是工业级光学字符识别模块,融合传统图像处理与深度学习技术,可将图像中的印刷体、手写体字符转换为可编辑文本,广泛适配各类工业复杂场景。
1.1 核心定义与技术特点
-
基础定位 :
OCR(Optical Character Recognition)是Halcon机器视觉体系中专门用于字符识别的功能模块,支持从单字符识别到整词端到端检测的全场景覆盖。 -
技术分支 :包含传统机器学习
OCR(MLP/SVM/GMM分类器)和深度学习Deep OCR两大路线,后者可直接检测识别连续的整词文本,而非仅单个孤立字符。 -
核心优势:抗干扰能力强,对光照不均、油污遮挡、倾斜变形的工业场景字符仍能保持高识别率,工业场景准确率普遍可达98%以上。
1.2 完整应用流程
Halcon OCR的应用分为离线训练 和在线检测两个核心阶段:
离线训练阶段(模型准备)
采集标注样本图像,覆盖目标场景下不同字体、光照、变形的字符样本
- 对样本图像执行灰度化、二值化、去噪等预处理,分割出单个字符区域
- 使用
append_ocr_trainf算子将字符区域与对应标签关联,存入.trf训练文件 - 创建指定类型的分类器(如MLP),完成训练后将模型保存为
.omc格式文件
在线检测阶段(实际识别)
- 读取待识别的目标图像,执行与训练阶段一致的预处理流程
- 分割提取图像中的字符独立区域,过滤无效噪点区域
- 通过
read_ocr_class_mlp加载训练好的.omc分类器模型 - 调用
do_ocr_single_class_mlp等算子完成字符分类识别,输出文本结果 - 对识别结果做后处理校正,结合行业词典修正语义不合理的识别错误
1.3,关联文件介绍。
1.3.1 训练文件:.trf文件
.trf:OCR(光学字符识别)训练文件(OCR Training File),训练文件需要完成训练后才能被用于
OCR识别使用。
trf 文件本质上是一个数据集,其中包含了以下关键信息:
字符图像区域(Region):分割出来的单个字符的形状区域。
灰度值信息(Image):对应区域的像素灰度值。
类别标签(Class):该字符对应的真实文本标识(例如 "A", "b", "3" 等)。
1.3.2 分类器文件:.omc文件、.occ文件
.omc、.occ:训练完成的 OCR 字符分类器模型文件(OCR Model Classifier),是 HALCON OCR 识别流程中
最终生成的可直接用于推理的核心产物。
它是 OCR 训练阶段的最终输出,完全区别于仅存储原始样本的 .trf 训练文件。文件内部封装了分类器通过大量样本学习到的字符特征、权重参数、网络结构等全部知识,相当于 OCR 识别的"大脑",可以直接加载到程序中完成实时字符识别任务。
Halcon提供了常用的OCR字符分类器文件,保存在安装路径\MVTec\HALCON-20.11-Steady\ocr。
提示:Halcon提供的字体文件例如 :Document_0-9_NoRej.omc与Document_0-9_Rej.omc区别是NoRej表示不严格字符识别兼容性强但容易误识别。Rej严格字符识别兼容性差。二者均是基于白底黑字,若使用Halcon提供的OCR分类器进行字符识别则需要图像中的字符满足白底黑字。
1.3.3 三种文件的区别
.trf |
.omc |
.occ |
|
|---|---|---|---|
| 本质 | 训练文件(样本集) | MLP 分类器文件(模型) | CNN 分类器文件(模型) |
| 存什么 | 字符区域 + 对应灰度值 + 类别名 | 训练好的 MLP 网络参数与字符集 | 训练好的 CNN 网络参数与字符集 |
| 谁产生 | 用户自己用 write_ocr_trainf / append_ocr_trainf 制作 |
用户训练后 write_ocr_class_mlp 写出;或 MVTec 预训练版 |
主要由 MVTec 预训练随软件发布 |
| 谁消费 | trainf_ocr_class_mlp / trainf_ocr_class_svm 训练时读取 |
read_ocr_class_mlp 加载后识别 |
read_ocr_class_cnn 加载后识别 |
| 能否追加 | 可以,反复追加样本 | 不能追加类别,只能重训 | 不能,常规流程无对应写出算子 |
1.4,常用的识别方式
1.4.1,文字模型识别
使用提供的分类器文件(例如:Document_0-9_NoRej.omc)自动识别字符与字符区域。
halcon
* 创建文字识别模型
create_text_model_reader ('auto', 'Document_0-9_NoRej.omc', TextModel)
* 进行查找
find_text (Image, TextModel, TextResultID)
* 获取表示字符的区域
get_text_object (Characters, TextResultID, 'all_lines')
* 获取识别的字符
get_text_result (TextResultID, 'class', Classes)
1.4.2,多字符识别
o_ocr_multi_class_mlp:一次识别多个字符
halcon
* 创建OCR分类器
read_ocr_class_mlp ('DotPrint_0-9A-Z_NoRej.omc', OCRHandle)
* 一次读取多个字符,class:为读取到的字符数组
do_ocr_multi_class_mlp (SortedRegions, ImageAffineTrans, OCRHandle, Class, Confidence)
1.4.3,单字符识别
do_ocr_single_class_mlp:一次识别1个字符
halcon
read_ocr_class_mlp ('Industrial_0-9A-Z_NoRej.omc', OCRHandle)
for Index := 1 to Number by 1
* 逐个字符识别
select_obj (SortedRegions, ObjectSelected, Index)
* 这里的Num=1表示:指定返回的最佳匹配结果数量。例如设为 1 则只返回最可能的一个字符
do_ocr_single_class_mlp (ObjectSelected, ImageInvert, OCRHandle, 1, Class, Confidence)
disp_message (WindowHandle, Class, 'image', Row[Index-1]+10, Col[Index-1], 'green', 'false')
endfor
2,预处理
- 使用Halcon提供的分类器文件进行识别时,目标字符区域必须预处理为白底黑字.
- 目标字符是环形分布时,需使用极坐标转换预处理为水平分布。
- 目标字符旋转时,需使用仿射变换预处理为水平分布。
- 目标字符倾斜时,需使用仿射变换预处理为非倾斜状态。
3,常见应用案例
3.1,环形字符识别
halcon
* Halcon 案例:ocr_cd_print_polar_trans.hdev
* This example demonstrates how to perform OCR
* of symbols printed along a non-linear pattern.
* In particular, this example reads the characters
* printed on a CD
*
dev_update_off ()
dev_close_window ()
WidthP := 900
HeightP := 20
read_image (Image, 'ocr/cd_print')
get_image_size (Image, Width, Height)
dev_open_window (HeightP + 60, 0, Width * 2 / 3, Height * 2 / 3, 'black', WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
*
* Show original image
dev_display (Image)
disp_message (WindowHandle, 'Read the number on the outer ring', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
*
* Segment disc in which the characters have been printed
mean_image (Image, ImageMean, 211, 211)
dyn_threshold (Image, ImageMean, RegionDynThresh, 15, 'dark')
connection (RegionDynThresh, ConnectedRegions)
select_shape_std (ConnectedRegions, SelectedRegions, 'max_area', 0)
gen_contour_region_xld (SelectedRegions, Contours, 'border')
fit_circle_contour_xld (Contours, 'ahuber', -1, 0, 0, 3, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder)
gen_circle (CircleO, Row, Column, Radius - 5)
gen_circle (CircleI, Row, Column, Radius - 30)
difference (CircleO, CircleI, Ring)
*
dev_set_draw ('margin')
dev_set_color ('green')
dev_set_line_width (3)
dev_display (Ring)
Message := '1. Segment ring'
disp_message (WindowHandle, Message, 'window', 36, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
*
* Rectify the region through a polar transformation
* so that the characters now are aligned along an
* horizontal line
polar_trans_image_ext (Image, ImagePolar, Row, Column, 0, rad(360), Radius - 30, Radius - 5, WidthP, HeightP, 'bilinear')
dev_open_window (0, 0, WidthP, HeightP, 'black', WindowHandle2)
rotate_image (ImagePolar, ImageRotate, 180, 'constant')
*
* Segment the characters
mean_image (ImageRotate, ImageMeanRotate, 51, 9)
dyn_threshold (ImageRotate, ImageMeanRotate, RegionDynThreshChar, 5, 'dark')
connection (RegionDynThreshChar, ConnectedRegions1)
select_shape (ConnectedRegions1, SelectedRegions, ['area','width'], 'and', [30,4], [150,10])
sort_region (SelectedRegions, SortedRegions, 'character', 'false', 'column')
* Remove distractors which happen to have similar dimensions to the characters.
* From all the candidate regions pickup those consisting of dark regions
* on light background
threshold (ImageMeanRotate, Region, 90, 255)
intersection (SelectedRegions, Region, RegionIntersection)
* Filter out resulting empty regions
area_center (RegionIntersection, Area, Row1, Column1)
select_mask_obj (RegionIntersection, Characters, Area [>] 0)
*
dev_display (ImageRotate)
Message := [Message,'2. Calculate polar transform']
disp_message (WindowHandle, Message, 'window', 36, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
*
* Read out
read_ocr_class_mlp ('Industrial_0-9A-Z_NoRej', OCRHandle)
sort_region (Characters, SortedRegions, 'character', 'true', 'row')
do_ocr_multi_class_mlp (SortedRegions, ImageRotate, OCRHandle, Class, Confidence)
* Correct zeros that are mistaken as capital O's.
* In a more general situation one may use a more
* complex regular expression or else the operator
* do_ocr_word_mlp()
tuple_regexp_replace (sum(Class), 'O', '0', Result)
*
dev_set_colored (6)
dev_set_draw ('fill')
dev_display (RegionIntersection)
Message := [Message,'3. Segment and read text']
disp_message (WindowHandle, Message, 'window', 36, 12, 'black', 'true')
disp_message (WindowHandle, Result, 'image', Height / 2 - 20, Width / 2 - 150, 'black', 'true')
clear_ocr_class_mlp (OCRHandle)
效果:

3.2,雕刻字符识别
halcon
* 案例:engraved.hdev
* 描述:浮雕字符识别(单字符识别)
dev_close_window ()
read_image (Image, 'engraved')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
dev_display (Image)
dev_set_line_width (3)
dev_set_draw ('margin')
set_display_font (WindowHandle, 20, 'mono', 'true', 'false')
* 区域增强,模板内最大灰度值与最小灰度值的差值
gray_range_rect (Image, ImageResult, 7, 7)
threshold (ImageResult, Region, 128, 255)
connection (Region, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, ['area','height'], 'and', [969.39,50], [5000,100])
* 提供的OCR分类器是基于白底黑字所以这里需要反转图像
invert_image (ImageResult, ImageInvert)
sort_region (SelectedRegions, SortedRegions, 'first_point', 'true', 'column')
* 读取halcon提供已训练好的OCR分类器
* halcon 的分类器是基于白底黑字
read_ocr_class_mlp ('Industrial_0-9A-Z_NoRej.omc', OCRHandle)
count_obj (SortedRegions, Number)
smallest_rectangle1 (SortedRegions, Row1, Column1, Row2, Column2)
Col:=(Column1+Column2)/2
Row:=gen_tuple_const(|Row2|,mean(Row2))
* 默认形状显示模式
dev_set_shape ('original')
dev_display (Image)
dev_display (SortedRegions)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
dev_display (Image)
dev_set_shape ('rectangle1')
for Index := 1 to Number by 1
* 逐个字符识别
select_obj (SortedRegions, ObjectSelected, Index)
* 这里的Num=1表示:指定返回的最佳匹配结果数量。例如设为 1 则只返回最可能的一个字符
do_ocr_single_class_mlp (ObjectSelected, ImageInvert, OCRHandle, 1, Class, Confidence)
disp_message (WindowHandle, Class, 'image', Row[Index-1]+10, Col[Index-1], 'green', 'false')
endfor
dev_display (SortedRegions)
* 清除分类器
clear_ocr_class_mlp (OCRHandle)
效果:

3.3,倾斜字符识别
halcon
* 案例:text_line_slant.hdev
* 描述:字符倾斜校正
dev_close_window ()
read_image (Image, 'dot_print_slanted')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
dev_display (Image)
* 计算字符倾斜角度
text_line_slant (Image, Image, 50, rad(-45), rad(45), SlantAngle)
* 进行校正
hom_mat2d_identity (HomMat2DIdentity)
hom_mat2d_slant (HomMat2DIdentity, -SlantAngle, 'x', 0, 0, HomMat2DSlant)
affine_trans_image (Image, ImageAffineTrans, HomMat2DSlant, 'constant', 'false')
threshold (ImageAffineTrans, Regions, 0, 80)
dilation_rectangle1 (Regions, RegionDilation, 1, 11)
connection (RegionDilation, ConnectedRegions)
intersection (ConnectedRegions, Regions, RegionIntersection)
partition_dynamic (RegionIntersection, Partitioned, 30, 20)
sort_region (Partitioned, SortedRegions, 'character', 'true', 'row')
read_ocr_class_mlp ('DotPrint_0-9A-Z_NoRej.omc', OCRHandle)
do_ocr_multi_class_mlp (SortedRegions, ImageAffineTrans, OCRHandle, Class, Confidence)
tuple_regexp_replace (sum(Class), ['o', 'replace_all', 'ignore_case'], '0', Result)
hom_mat2d_invert (HomMat2DSlant, HomMat2DInvert)
affine_trans_region (SortedRegions, RegionAffineTrans, HomMat2DInvert, 'nearest_neighbor')
dev_display (Image)
dev_set_draw ('margin')
dev_set_line_width (3)
dev_display (RegionAffineTrans)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
disp_message (WindowHandle, Result, 'window', 12, 12, 'forest green', 'white')
clear_ocr_class_mlp (OCRHandle)
dev_set_draw ('fill')
stop ()
* ---------------------------------------------------------------------------
* 第二种方法:使用点状图处理
dots_image (ImageAffineTrans, DotImage, 5, 'dark', 2)
gray_range_rect (DotImage, ImageResult,3, 3)
binary_threshold (ImageResult, Region, 'smooth_histo', 'dark', UsedThreshold)
erosion_circle (Region, RegionErosion, 0.5)
connection (RegionErosion, ConnectedRegions1)
select_shape (ConnectedRegions1, SelectedRegions, 'area', 'and', 27.83, 10000)
union1 (SelectedRegions, RegionUnion)
binary_threshold (ImageResult, Region1, 'max_separability', 'light', UsedThreshold1)
expand_gray_ref (Region1, ImageAffineTrans, RegionUnion, RegionExpand, 'maximal', 'image', 50, 100)
partition_dynamic (RegionExpand, Partitioned, 30, 50)
效果:

3.4,文本模型识别字符
halcon
* 案例:bottle.hdev
* 描述:通过文本模型识别字符
dev_close_window ()
FontName := 'Universal_0-9_NoRej.occ'
*FontName:='Document_0-9_NoRej.omc'
read_image (Image, 'bottle2')
dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
dev_display (Image)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_line_width (2)
dev_set_draw ('margin')
* 创建文字识别模型
create_text_model_reader ('auto', FontName, TextModel)
* 设置参数减少匹配误差
set_text_model_param (TextModel, 'min_stroke_width', 6)
set_text_model_param (TextModel, 'max_char_height', 45)
* 设置匹配的文字格式这里表示:两个字符一个空格两个字符一个空格两个字符一个空格
set_text_model_param (TextModel, 'text_line_structure', '2 2 2')
* 进行查找
find_text (Image, TextModel, TextResultID)
* 获取表示字符的区域
get_text_object (Characters, TextResultID, 'all_lines')
* 获取识别的字符
get_text_result (TextResultID, 'class', Classes)
* 打印识别的字符
area_center (Characters, Area, Row, Column)
dev_set_shape ('rectangle1')
dev_display (Image)
dev_display (Characters)
disp_message (WindowHandle, Classes, 'image',gen_tuple_const(|Row|,mean( Row)+25), Column, 'green', 'false')
clear_text_model (TextModel)
效果:

3.5,样本训练+字符识别
halcon
* halcon 案例:letters_mlp.hdev
* 描述:字符的训练文件的保存,训练,字符识别
dev_close_window ()
dev_update_off ()
dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
TrainFile:='letters.trf'
Classes:=[]
file_exists (TrainFile, FileExists)
if(FileExists)
delete_file (TrainFile)
endif
read_image (Image, 'letters')
get_image_size (Image, Width, Height)
dev_resize_window_fit_image (Image, 0, 0, -1, -1)
dev_display (Image)
gen_rectangle1 (Rectangle, 0, 0, Height, Width/2-5)
reduce_domain (Image, Rectangle, ImageReduced)
binary_threshold (ImageReduced, Region, 'max_separability', 'dark', UsedThreshold)
dilation_circle (Region, RegionDilation, 2.5)
connection (RegionDilation, ConnectedRegions)
intersection (ConnectedRegions, Region, RegionIntersection)
* 排序
sort_region (RegionIntersection, Character, 'first_point', 'true', 'row')
count_obj (Character, Number)
Length:=Number/27
* a-z共26个字母
* tuple_ord 将字符转换为整数
for i := 0 to 25 by 1
Classes:=[Classes,gen_tuple_const(Length,chr(ord('a')+i))]
endfor
Classes:=[Classes,gen_tuple_const(Length,'.')]
* 写入到训练文件,训练文件只是区域与标记文字的集合,
* 若要两者关联起来需要经过训练
write_ocr_trainf (Character, ImageReduced, Classes, TrainFile)
* 查询字符名称
read_ocr_trainf_names (TrainFile, CharacterNames, CharacterCount)
* 创建OCR分类器
create_ocr_class_mlp (8, 10, 'constant', 'default', CharacterNames, 80, 'none', 10, 42, OCRHandle)
* 训练
trainf_ocr_class_mlp (OCRHandle, TrainFile, 200, 1, 0.01, Error, ErrorLog)
* 识别
dev_display (Image)
binary_threshold (Image, Region, 'max_separability', 'dark', UsedThreshold1)
dilation_circle (Region, RegionDilation, 2.5)
connection (RegionDilation, ConnectedRegions)
intersection (ConnectedRegions, Region, RegionIntersection)
sort_region (RegionIntersection, Character, 'first_point', 'true', 'row')
do_ocr_multi_class_mlp (Character, Image, OCRHandle, Class, Confidence)
area_center (Character, Area, Row, Column)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
disp_message (WindowHandle, Class, 'image', Row-12, Column+12, 'blue', 'false')
clear_ocr_class_mlp (OCRHandle)
效果:

4,OCR助手应用
4.1,OCR训练文件浏览器
**作用:**用于浏览、编辑OCR训练文件中的样本。
4.1.1 打开浏览器。

4.1.2 创建或者加载训练文件。

4.1.3 浏览样本。

4.1.4 生成样本变形,增加样本(可选)。

4.1.5 系统字体添加为训练样本(可选)。

4.2 OCR助手
4.2.1,OCR字符识别
4.2.1.1,打开新的OCR

4.2.1.2,设置字符字体识别所需的分类器

4.2.1.3,框选目标区域

4.2.1.4,配置参数,并快速应用。

4.2.1.5,查看或编辑其他自动配置的参数

4.2.2,OCR训练样本(可选)。
若是Halcon未提供符合要求的分类器(例如:中文分类器),则需要进行中文样本训练。
字体选项中选择训练文件选项。
4.2.2.1 新建训练文件或者打开已有的训练文件。

4.2.2.2 对样本进行标记。


4.2.2.3 添加并保存样本至训练文件。

4.2.2.4 配置训练参数,训练样本。

4.2.2.5 训练完成,生成分类器文件。
示例生成分类器文件:DotPrint.omc
