QQ登录

只需一步,快速开始

3.4 halcon 上位机实现洗发水瓶标签偏移检测

[ 复制链接 ]
当前帖子实现洗发水瓶上标签位置的检测。
首先在参考图片上创建瓶子和标签的形状模型,然后在随后的图片上查找 模型。
如果找到的两模型相对位置(中心X,Y,角度)与参考图片上计算的数值对比,
在要求范围内就表示合格。

实例中使用了形状模板匹配方法来定位瓶子与标签。
模板匹配定位方法其速度 相对blob分析会低些,但是在对比 度较好的环境 下匹配精度 比较高。
工业 视觉中采用形状类型的模板 匹配居多。
其具体实现过程 是 先建立 一个形状模板,在图片上搜索这个模板,
找到模板后就确定 的目标区域的坐标位置及区域,
然后在这个区域 内进行下一步的检测 识别等操作。

下面是实现实现的代码和注释:

上位机实现洗发水瓶标签偏移检测

上位机实现洗发水瓶标签偏移检测

  1. dev_update_off ()
  2. dev_set_draw ('margin')
  3. dev_set_line_width (2)
  4. * 加载一幅参考图像,用于创建模型
  5. set_system ('clip_region', 'false')
  6. read_image (Image, 'packaging/shampoo_01')
  7. dev_close_window ()
  8. dev_open_window_fit_image (Image, 0, 0, -1, -1, WindowHandle)
  9. set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
  10. dev_display (Image)
  11. *
  12. * 准备形状匹配模型,生成第一个模型区域和搜索ROI
  13. BottleModelRow := 131
  14. BottleModelColumn := 370
  15. BottleModelLength1 := 350
  16. BottleModelLength2 := 35
  17. BottleModelPhi := -0.1093
  18. gen_rectangle2 (Rectangle1, BottleModelRow, BottleModelColumn, BottleModelPhi, BottleModelLength1, BottleModelLength2)
  19. gen_rectangle2 (Rectangle2, BottleModelRow + 220, BottleModelColumn, -BottleModelPhi, BottleModelLength1, BottleModelLength2)
  20. union2 (Rectangle1, Rectangle2, TemplateBottleRegion)

  21. *获取图片的区域,在halcon中区域不等于图像,区域要在图像中用reduce_domain等算子截取对应图像后才有数据。
  22. get_domain (Image, Domain)
  23. *获取TemplateBottleRegion, Domain的交集区域,保存到TemplateBottleRegion
  24. intersection (TemplateBottleRegion, Domain, TemplateBottleRegion)
  25. area_center (TemplateBottleRegion, Area, RowBottleRef, ColumnBottleRef)
  26. gen_circle (SearchROIBottle, RowBottleRef, ColumnBottleRef, 40)
  27. reduce_domain (Image, TemplateBottleRegion, ImageReduced)
  28. *
  29. *创建形状模型,ImageReduced为要创建的模板函数, 5为金字塔层数, -rad(3)为模板 起始 角度 ,
  30. *rad(6)为模板角度范围, 0为旋转角度 步长, 'auto'为优化选项,表示 是否减少模板的像素点数,
  31. *这里表示自动,'use_polarity'匹配度量极性选择方式,就是匹配标准,这里使用了极性,
  32. *25为对应阈值, 3最小对比度, ModelIDBottle为输出 的模板句柄,后续用于模板查找。
  33. create_shape_model (ImageReduced, 5, -rad(3), rad(6), 0, 'auto', 'use_polarity', 25, 3, ModelIDBottle)
  34. *
  35. dev_display (Image)
  36. dev_set_color ('forest green')
  37. dev_display (TemplateBottleRegion)
  38. dev_set_color ('slate blue')
  39. disp_message (WindowHandle, 'bottle shape model', 'window', 12, 12, 'black', 'true')
  40. disp_continue_message (WindowHandle, 'black', 'true')
  41. stop ()
  42. * 生成第二模板区域及搜索ROI
  43. * generate second model region and search ROI
  44. LabelRow1 := 180
  45. LabelRow2 := 310
  46. LabelColumn1 := 50
  47. LabelColumn2 := 470
  48. gen_rectangle1 (TemplateLabelRegion, LabelRow1, LabelColumn1, LabelRow2, LabelColumn2)
  49. area_center (TemplateLabelRegion, Area1, RowLabelRef, ColumnLabelRef)
  50. gen_circle (SearchROILabel, RowLabelRef, ColumnLabelRef, 60)
  51. reduce_domain (Image, TemplateLabelRegion, ImageReduced)
  52. *根据金字塔层数1, 和对比度25检查要生成的模板。所谓的金字塔层数就是对图像的二次抽样,
  53. *如等比例抽样,把图像的像素个数每次抽取 一半,也就是每次的高宽各减一半,这样图像 层数越高,
  54. *抽样的像素点越少。ImageReduced为输入图像,ModelImages为ImageReduced对应输出的图像,
  55. *ModelRegions为输出的模板金字塔区域
  56. inspect_shape_model (ImageReduced, ModelImages, ModelRegions, 1, 25)
  57. *
  58. create_shape_model (ImageReduced, 5, rad(-3), rad(6), 0, 'auto', 'use_polarity', 25, 5, ModelIDLabel1)
  59. create_shape_model (ImageReduced, 5, rad(180 - 3), rad(6), 0, 'auto', 'use_polarity', 25, 5, ModelIDLabel2)
  60. ModelIDsLabel := [ModelIDLabel1,ModelIDLabel2]
  61. *
  62. dev_display (Image)
  63. dev_set_color ('forest green')
  64. dev_display (TemplateLabelRegion)
  65. dev_set_color ('slate blue')
  66. dev_display (ModelRegions)
  67. disp_message (WindowHandle, 'create label shape model', 'window', 12, 12, 'black', 'true')
  68. disp_continue_message (WindowHandle, 'black', 'true')
  69. stop ()
  70. *
  71. * 循环读取图片,在图片上查找标签的瓶子相对位置
  72. for Index := 1 to 13 by 1
  73.     read_image (Image, 'packaging/shampoo_' + Index

  74. .2')
  75.     dev_display (Image)
  76.     disp_message (WindowHandle, 'check label position', 'window', 12, 12, 'black', 'true')
  77.     count_seconds (s1)
  78.     reduce_domain (Image, SearchROIBottle, ImageReduced)
  79.     *在图像ImageReduced上查找模板ModelIDBottle,-rad(3), rad(6)分别为模板搜索的起始角度和角度范围
  80.     *, 0.7为被找到模板实例 的最小分数也就是模板 有多少部分的像素 被找到,为百分比形式。
  81.     *1表示要找几个实例,这里只找一个模板就好, 0.5表示被找到实例 的最大重叠 度,最多 重叠 遮挡 多大比例还表示找到,
  82.     *least_squares'表示是否采用亚像素查找,这里采用least_squares,none为不采用,
  83.     *0, 0.9分别表示金字塔层数和贪婪度,贪婪值越大,搜索速度越快,精度越低。
  84.     * RowBottle, ColumnBottle, AngleBottle, ScoreBottle分别为找到模板实例的中心坐标,角度及匹配分数值。
  85.     find_shape_model (ImageReduced, ModelIDBottle, -rad(3), rad(6), 0.7, 1, 0.5, 'least_squares', 0, 0.9, RowBottle, ColumnBottle, AngleBottle, ScoreBottle)
  86.     * 在图像 中准备搜索ROI
  87.     *将两个图形对象合并到第三个参数中,这里将SearchROILabel放入SearchROIs。
  88.     concat_obj (SearchROILabel, SearchROILabel, SearchROIs)
  89.     *对要搜索的区域添加灰度图像,也就是获取Image在区域SearchROIs的图像 数据,
  90.     add_channels (SearchROIs, Image, GrayRegions)
  91.     * 同时搜索多个模板实例,GrayRegions, ModelIDsLabel为要搜索的图像及模板句柄 。
  92.     *[rad(-3),rad(180 - 3)]为模板开始的搜索角度,这里表示从两个起始角度开始搜索,
  93.     *[rad(6),rad(6)]为模板搜索的角度范围,对应前面的起始角度。
  94.     *0.6被查找模板的最小分数值, 1查找一个模板实例, 1被找模板实例的最大重叠 度。
  95.     *'interpolation'采用interpolation方式查找板式, 0表示金字塔层数,
  96.     *0.9贪婪度, Row, Column, Angle, Score, FoundModel为找到模板实例的中心点,角度,分值和找到模板实例的索引
  97.     find_shape_models (GrayRegions, ModelIDsLabel, [rad(-3),rad(180 - 3)], [rad(6),rad(6)], 0.6, 1, 1, 'interpolation', 0, 0.9, Row, Column, Angle, Score, FoundModel)
  98.     count_seconds (s2)
  99.     *如果瓶子模板或标签模板没有找到,信息提示。
  100.     if (|Score| != 1 or |ScoreBottle| != 1)
  101.         disp_message (WindowHandle, 'Model not found', 'window', 40, 12, 'red', 'true')
  102.     else
  103.         if (ModelIDsLabel[FoundModel] == ModelIDLabel2)
  104.             disp_message (WindowHandle, 'Label rotated by 180°', 'window', 40, 12, 'red', 'true')
  105.         else
  106.             * 计算列坐标偏差。这里是用找到的瓶子中心Y坐标减去找到的标签中心Y坐标,
  107.             *等到的差减去在参考图片计算所得的差(RowBottleRef - RowLabelRef),最终得Y偏差。
  108.             Diffy := (RowBottle - Row) - (RowBottleRef - RowLabelRef)
  109.             *同样计算X偏差
  110.             Diffx := (ColumnBottle - Column) - (ColumnBottleRef - ColumnLabelRef)
  111.             *瓶子角度减去标签角度,得到两者角度偏差。
  112.             Diffa := deg(AngleBottle - Angle)
  113.             Time := s2 - s1
  114.             * 根据X,Y,角度偏差,显示结果
  115.             Color := 'black'
  116.             ModelColor := 'forest green'
  117.             if (abs(Diffx) > 3)
  118.                 Color := [Color,'red']
  119.                 ModelColor := 'red'
  120.             else
  121.                 Color := [Color,'forest green']
  122.             endif
  123.             if (abs(Diffy) > 1)
  124.                 Color := [Color,'red']
  125.                 ModelColor := 'red'
  126.             else
  127.                 Color := [Color,'forest green']
  128.             endif
  129.             if (abs(Diffa) > 1)
  130.                 Color := [Color,'red']
  131.                 ModelColor := 'red'
  132.             else
  133.                 Color := [Color,'forest green']
  134.             endif
  135.             dev_display_shape_matching_results (ModelIDsLabel, ['slate blue',ModelColor], Row, Column, Angle, 1, 1, FoundModel)
  136.             disp_message (WindowHandle, ['Time       = ' + (Time * 1000)

  137. .2' + ' ms','Diff x     = ' + Diffx

  138. .2','Diff y     = ' + Diffy

  139. .2','Diff angle = ' + Diffa

  140. .2'], 'window', 35, 12, Color, 'true')
  141.         endif
  142.         *
  143.     endif
  144.     if (Index < 13)
  145.         disp_continue_message (WindowHandle, 'black', 'true')
  146.         stop ()
  147.     else
  148.         disp_message (WindowHandle, 'Program finished', 'window', 450, 430, Color, 'true')
  149.     endif
  150. endfor
  151. stop ()
  152. clear_shape_model (ModelIDLabel1)
  153. clear_shape_model (ModelIDLabel2)
  154. clear_shape_model (ModelIDBottle)
  155. set_system ('clip_region', 'true')
复制代码



回复

使用道具 举报

快速回复 返回列表 客服中心 搜索