ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

基于Halcon的瓶底字符识别

2022-07-01 01:03:25  阅读:181  来源: 互联网

标签:字符 字符识别 矩形 Halcon 区域 瓶底 图像 识别


背景

在食品,药品及日用化学品等领域,有很大一部分产品采用瓶装容器来盛放产品。企业通常使用喷码机将产品的批号、生产日期、保质期等喷印在瓶底部位。喷码机受自身性能、机械振动等因素的影响,可能会出现多种缺陷,如字符的缺印、漏印、错印等,以上的质量问题会对企业的品牌形象及信誉产生影响。
传统的喷码字符检测采用人工全检,人工检测的工作效率低、工作强度大且容易因人眼疲劳等因素产生人为误差出现漏检、误检的情况。因此人工检测的方式已经不适应当下制造业自动化、信息化的发展趋势,基于机器视觉的字符识别算法则可以解决人工检测效率低,成本高和误差大的缺点,具有广泛的市场需求和较高的研究价值。

要求

针对瓶装产品设计基于机器视觉技术的瓶底字符识别算法,瓶底字符识别的难点在于瓶底的旋转姿态不定,致使识别的准确率难以保证,因此在字符识别之前必须对瓶底字符进行姿态矫正,使字符水平排列。

  1. 收集瓶体喷码字符数据(拍摄罐装饮料、调料等图像),类似下图中
    样本,角度不定,多行,每行含有英文字符、数字和特殊符号(:等)。
    imageimage
  2. 设计算法,包括:图像预处理模块,字符定位模块,字符分割模块和字符识别模块。图像预处理模块用于对读取的图像进行便于操作的预先处理;字符定位模块用于将字符区域与背景区分开;字符分割模块用于将提取出的字符区域内的字符单独分割并排序;字符识别模块用于识别分割出的字符并显示。
  3. 设计针对瓶底图像字符分类器的训练程序,用于训练专属的分类器,进一步提高瓶底字符识别算法的准确率。

原理

Halcon已广泛应用于光学字符识别(OCR),利用Halcon中自带的工业字符识别模型可以实现多种字体的文本识别。罐装瓶底喷码字符多使用点式打印机,除使用自带的字符模型外可以根据样本进行训练,以此来提高识别准确率。
使用Halcon进行字符识别时,首先要获取水平排列的字符,分割出单个字符区域,然后再读取OCR分类器实现字符分类。
针对倾斜的文本,可以先进行仿射变换使其水平排列,不用考虑文本是否倒置。识别完成后对结果进行校验,如果识别结果符合逻辑,认为结果正确,否则认为文本倒置,调整后再进行识别,最后输出识别结果。
在实验时,待识别的图像应保证目标区域居中,即罐底应位于图片中央。图片大小一致,具有相同的长宽尺寸。在有条件的情况下,可以使用专业的检测平台获取罐底图像,拍摄时光照均匀且无明显阴影与遮盖,保证图片质量。

图片要求

  1. 目标居中,罐底圆形位于图片中央;
  2. 图片大小一致,长宽尺寸相同(正方形);
  3. 多角度可随意旋转(对字符而言);
  4. 拍摄时光照均匀无明显阴影与遮盖。

主要步骤

1. 设置圆形ROI,裁剪原图片

* 生成圆形区域:gen_circle
* 缩小图像的域:reduce_domain

这一步的目的是去掉原图像的背景,以免干扰识别结果,处理后的图像保留全部的字符区域和小部分的背景。

2. 图像处理

* 增强图像对比度:emphasize
* 转化为灰度图像:rgb1_to_gray
* 使用矩形结构元素进行膨胀:dilation_rectangle1
* 连接区域:connection
* 区域选择:select_shape
* 合并为一个区域:union1
* 拟合成矩形:shape_trans
* 得到矩形区域的偏转角度:orientation_region
* 计算矩形区域面积和中心点坐标:area_center
* 旋转图片至水平并得到仿射矩阵:vector_angle_to_rigid
* 仿射矩阵应用于图片:affine_trans_image
* 仿射矩阵应用于矩形区域:affine_trans_region
* 在原图中扣出字符区域图像:reduce_domain
* 选择第一个通道:access_channel

3. 字符分割

* 阈值分割:threshold
* 使用矩形结构元素进行膨胀:dilation_rectangle1
* 连接区域:connection
* 区域选择:select_shape
* 拟合成矩形:shape_trans
* 区域排序:sort_region
* 统计区域个数:count_obj

4. 字符识别

* 读取OCR分类器:read_ocr_class_mlp
* 选择识别的字符区域:select_obj
* 在灰度图中扣出字符区域图像:reduce_domain
* 使用OCR分类器进行字符识别:do_ocr_multi_class_mlp

5. 识别结果校验

* 识别正确:显示识别结果。
* 识别错误:重新旋转图像并进行字符分割与识别;
           显示识别结果。

过程步骤

  1. 设置圆形ROI,裁剪原图片:
    生成圆形区域:gen_circle
    缩小图像的域:reduce_domain
  2. 图像处理:
    增强图像对比度:emphasize
    转化为灰度图像:rgb1_to_gray
    使用矩形结构元素进行膨胀:dilation_rectangle1
    连接区域:connection
    区域选择:select_shape
    合并为一个区域:union1
    拟合成矩形:shape_trans
    得到矩形区域的偏转角度:orientation_region
    计算矩形区域面积和中心点坐标:area_center
    旋转图片至水平并得到仿射矩阵:vector_angle_to_rigid
    仿射矩阵应用于图片:affine_trans_image
    仿射矩阵应用于矩形区域:affine_trans_region
    在原图中扣出字符区域图像:reduce_domain
    选择第一个通道:access_channel
  3. 字符分割:
    阈值分割:threshold
    使用矩形结构元素进行膨胀:dilation_rectangle1
    连接区域:connection
    区域选择:select_shape
    拟合成矩形:shape_trans
    区域排序:sort_region
    统计区域个数:count_obj
  4. 字符识别:
    读取OCR分类器:read_ocr_class_mlp
    选择识别的字符区域:select_obj
    在灰度图中扣出字符区域图像:reduce_domain
    使用OCR分类器进行字符识别:do_ocr_multi_class_mlp
  5. 识别结果校验:
    识别正确:显示识别结果。
    识别错误:重新旋转图像并进行字符分割与识别;
    显示识别结果。
    image

运行结果

1、 输入图像文本水平排列时的样本图像与识别结果:
imageimage
2、 输入图像文本倾斜排列时的样本图像与识别结果:
imageimage
3、 裁剪ROI区域后图像:
image
4、 仿射变换后得到的字符区域:
image
5、 分割字符区域:
image
6、 字符识别:
image

思考分析

  1. 采用先识别再对结果进行校验的方法消耗太多资源,尤其是在工业中流水线识别时会浪费大量时间,一般工控机运算能力有限,实际应用时效果不佳。针对这个问题,可以先进行第一个字符的识别,随后立即进行校验,可以有效减少无效步骤。
  2. 除了识别后进行校验的方法,还可以根据字符排列的特点,如空格的空间位置,文本的排列特点等方式进行水平仿射变换,省去校验过程。
  3. 如果待识别图像文本中含有不变字符,可以使用模板匹配的方法,通过不变字符创建模板,寻找字符区域进行文字识别。
  4. 自己训练OCR文件可以显著提高识别准确率。
  5. 识别时最重要的是字符区域的确定,要找到包含字符的最小的矩形框,才能最好的与训练样本保持一致,识别准确率提高。

程序源码

* 瓶底字符识别
*
*设置系统参数
dev_update_off ()
get_system ('clip_region', Information)
set_system ('clip_region', 'true')
*读取图片
read_image (Image, 'E:/学习/大三下/机器视觉专题实践/图像/样本/1')
*获取图片尺寸
get_image_size (Image, Width, Height)
*配置窗体
dev_close_window ()
dev_open_window (0, 0, Width/4, Height/4, 'black', WindowHandle)
dev_set_colored (12)
dev_display (Image)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
*
*图像处理
*预处理,裁剪出字符区域
gen_circle (CircleROI, Width/2, Height/2, 745)
reduce_domain (Image, CircleROI, ImageReduced)
*增强对比度
emphasize (ImageReduced, ImageEmphasize, 3, 3, 1)
*转化为灰度图像
rgb1_to_gray (ImageEmphasize, GrayImage)
*阈值分割
threshold (GrayImage, Image_threshold, 0, 100)
*使用矩形结构元素进行膨胀
dilation_rectangle1 (Image_threshold, RegionDilation, 12, 24)
*连接区域
connection (RegionDilation, RegionConnection)
*区域选择
select_shape (RegionConnection, RegionSelect, 'area', 'and', 1000, 50000)
*合并为一个区域
union1 (RegionSelect, RegionUnion)
*拟合成矩形
shape_trans (RegionUnion, TransShape, 'rectangle2')
*得到矩形区域的偏转角度
orientation_region (TransShape, TransShapePhi)
*计算矩形区域面积和中心点坐标
area_center (TransShape, TransShapeArea, TransShapeRow, TransShapeColumn)
*旋转图片至水平并得到仿射矩阵
vector_angle_to_rigid (TransShapeRow, TransShapeColumn, TransShapePhi, TransShapeRow, TransShapeColumn, 3.141593, HomMat2D)
*仿射矩阵应用于图片
affine_trans_image (GrayImage, ImageAffineTrans, HomMat2D, 'constant', 'false')
*仿射矩阵应用于矩形区域
affine_trans_region (TransShape, RegionAffineTrans, HomMat2D, 'nearest_neighbor')
*在原图中扣出字符区域图像
reduce_domain (ImageAffineTrans, RegionAffineTrans, ImageOCR)
*选择第一个通道
access_channel (ImageOCR, ImageOCR, 1)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
*
*分割字符并识别
*阈值分割
threshold (ImageOCR, ImageOCRThreshold, 0, 100)
*膨胀
dilation_rectangle1 (ImageOCRThreshold, ImageOCRDilation, 12, 25)
*连接区域
connection (ImageOCRDilation, ImageOCRConnection)
*区域选择
select_shape (ImageOCRConnection, ImageOCRSelect, 'area', 'and', 750, 10000)
*拟合成矩形
shape_trans (ImageOCRSelect, ImageOCRRectangle, 'rectangle1')
*区域排序
sort_region (ImageOCRRectangle, ImageOCRSorted, 'upper_left', 'true', 'column')
*统计区域个数
count_obj (ImageOCRSorted, Number)
*读取OCR分类器
read_ocr_class_mlp ('E:/学习/大三下/机器视觉专题实践/test.omc', OCRHandle)
*识别
for i := 1 to Number by 1
    *选择识别的字符区域
    select_obj (ImageOCRSorted, ObjectSelected, i)
    *在灰度图中扣出字符区域图像
    reduce_domain (ImageOCR, ObjectSelected, Character)
    *使用OCR分类器进行字符识别
    do_ocr_multi_class_mlp (Character, Character, OCRHandle, Class, Confidence)
    *存放识别结果
    char[i-1] := Class
    *返回字符中心坐标
    area_center (Character, Area, charcenterRow, charcenterColum)
    charRow[i-1] := charcenterRow 
    charColum[i-1] := charcenterColum
endfor
*识别结果校验
if (char[0] == '2')
    *结果正确
else
    *旋转图片至水平并得到仿射矩阵
    vector_angle_to_rigid (TransShapeRow, TransShapeColumn, TransShapePhi, TransShapeRow, TransShapeColumn, 0, HomMat2D)
    *仿射矩阵应用于图片
    affine_trans_image (GrayImage, ImageAffineTrans, HomMat2D, 'constant', 'false')
    *仿射矩阵应用于矩形区域
    affine_trans_region (TransShape, RegionAffineTrans, HomMat2D, 'nearest_neighbor')
    *在原图中扣出字符区域图像
    reduce_domain (ImageAffineTrans, RegionAffineTrans, ImageOCR)
    *选择第一个通道
    access_channel (ImageOCR, ImageOCR, 1)
    set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
    disp_continue_message (WindowHandle, 'black', 'true')
    stop ()
    *
    *分割字符并识别
    *阈值分割
    threshold (ImageOCR, ImageOCRThreshold, 0, 100)
    *膨胀
    dilation_rectangle1 (ImageOCRThreshold, ImageOCRDilation, 12, 25)
    *连接区域
    connection (ImageOCRDilation, ImageOCRConnection)
    *区域选择
    select_shape (ImageOCRConnection, ImageOCRSelect, 'area', 'and', 1000, 20000)
    *拟合成矩形
    shape_trans (ImageOCRSelect, ImageOCRRectangle, 'rectangle1')
    *区域排序
    sort_region (ImageOCRRectangle, ImageOCRSorted, 'upper_left', 'true', 'column')
    *统计区域个数
    count_obj (ImageOCRSorted, Number)
    *读取OCR分类器
    read_ocr_class_mlp ('E:/学习/大三下/机器视觉专题实践/test.omc', OCRHandle)
    *识别
    for i := 1 to Number by 1
        *选择区域
        select_obj (ImageOCRSorted, ObjectSelected, i)
        *在灰度图中扣出字符区域图像
        reduce_domain (ImageOCR, ObjectSelected, Character)
        *使用OCR分类器进行字符识别
        do_ocr_multi_class_mlp (Character, Character, OCRHandle, Class, Confidence)
        *存放识别结果
        char[i-1] := Class
        *返回字符中心坐标
        area_center (Character, Area, charcenterRow, charcenterColum)
        charRow[i-1] := charcenterRow 
        charColum[i-1] := charcenterColum
    endfor
endif
*清除句柄
clear_ocr_class_mlp (OCRHandle)
*显示识别结果
dev_display (Image)
for i := 1 to Number by 1
    disp_message (WindowHandle, char[i-1], 'Image', charRow[i-1] + 100, charColum[i-1], 'red', 'true')
endfor
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()

标签:字符,字符识别,矩形,Halcon,区域,瓶底,图像,识别
来源: https://www.cnblogs.com/kooop/p/16433142.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有