Halcon:刮胡刀锯齿缺陷检测

图像处理结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

主要思想:
1.创建模板,建立检测区域
2.在待检测区域,使用measure_pairs检测每一对锯齿的距离
3.使用距离进行OK,NG判断

代码如下:
*基于形状匹配的检测
*测刮胡刀的锯齿,断还是没断
USING_TRANSLATE_MEASURE := 0
dev_update_window (‘off’)
*读取图像
read_image (ModelImage, ‘razors1’)
*获取图像的数据信息
get_image_pointer1 (ModelImage, Pointer, Type, Width, Height)
dev_close_window ()
*打开窗口
dev_open_window (0, 0, Width, Height, ‘white’, WindowHandle)
dev_set_part (0, 0, Height - 1, Width - 1)
*显示图像
dev_display (ModelImage)
*设置颜色
dev_set_color (‘cyan’)
*填充方式
dev_set_draw (‘margin’)
*设置线宽为2个像素
dev_set_line_width (2)
stop ()
*画
Row1 := 46
Column1 := 57
Row2 := 79
Column2 := 94
*手动画一个区域,将这个区域的图像做模板匹配
gen_rectangle1 (ROIPart1, Row1, Column1, Row2, Column2)
*手动画一个区域,将这个区域的图像做模板匹配
gen_rectangle1 (ROIPart2, Row1 + 364, Column1 + 13, Row2 + 364, Column2 + 13)
*两个区域的联合
union2 (ROIPart1, ROIPart2, ModelROI)
*获得区域的中心坐标
area_center (ModelROI, Area, CenterROIRow, CenterROIColumn)
dev_display (ModelImage)
*显示模板区域
dev_display (ModelROI)
stop ()
*图像选择
reduce_domain (ModelImage, ModelROI, ImageROI)
*将刚刚上面确定的两个区域,联合起来,做为一个区域,做一个模板
create_shape_model (ImageROI, 4, 0, 0, ‘auto’, ‘none’, ‘use_polarity’, 30, 10, ModelID)
*创建形状模型的表示,可以理解为模板的骨架
inspect_shape_model (ImageROI, ShapeModelImage, ShapeModelRegion, 1, 30)
*获得模板的区域轮廓
get_shape_model_contours (ShapeModel, ModelID, 1)
*清空窗口
dev_clear_window ()
*设置颜色
dev_set_color (‘blue’)
*显示模板轮廓
dev_display (ShapeModelRegion)
stop ()

  • 形成两个待测区域的矩形,待测区域的坐标是模板匹配的坐标,待测区域的长度是人工手动设定的
    Rect1Row := 244
    Rect1Col := 73
    DistColRect1Rect2 := 17
    Rect2Row := Rect1Row
    Rect2Col := Rect1Col + DistColRect1Rect2
    RectPhi := rad(90)
    RectLength1 := 122
    RectLength2 := 2
    *左边待测区域
    gen_rectangle2 (MeasureROI1, Rect1Row, Rect1Col, RectPhi, RectLength1, RectLength2)
    *右边待测区域
    gen_rectangle2 (MeasureROI2, Rect2Row, Rect2Col, RectPhi, RectLength1, RectLength2)
    *显示待测图片
    dev_display (ModelImage)
    dev_set_color (‘yellow’)
    dev_display (MeasureROI1)
    dev_display (MeasureROI2)
  • translate measurement ROIs to lie on XLD model (without clipping!)
    get_system (‘clip_region’, OriginalClipRegion)
    set_system (‘clip_region’, ‘false’)
    move_region (MeasureROI1, MeasureROI1Ref, -CenterROIRow, -CenterROIColumn)
    move_region (MeasureROI2, MeasureROI2Ref, -CenterROIRow, -CenterROIColumn)
    set_system (‘clip_region’, OriginalClipRegion)
    DistRect1CenterRow := Rect1Row - CenterROIRow
    DistRect1CenterCol := Rect1Col - CenterROIColumn
    DistRect2CenterRow := Rect2Row - CenterROIRow
    DistRect2CenterCol := Rect2Col - CenterROIColumn
    if (USING_TRANSLATE_MEASURE != 0)
    • -> measure objects are created only once in advance and then translated later
      *建立测量区域的句柄
      gen_measure_rectangle2 (Rect1Row, Rect1Col, RectPhi, RectLength1, RectLength2, Width, Height, ‘bilinear’, MeasureHandle1)
      gen_measure_rectangle2 (Rect2Row, Rect2Col, RectPhi, RectLength1, RectLength2, Width, Height, ‘bilinear’, MeasureHandle2)
      endif
      stop ()
      *读取待测图像
      read_image (SearchImage, ‘razors2’)
      dev_display (SearchImage)
      *找到对应的模板
      find_shape_model (SearchImage, ModelID, 0, 0, 0.8, 0, 0.5, ‘least_squares’, 0, 0.7, RowCheck, ColumnCheck, AngleCheck, Score)
      *|Score|代表一共找到多少个对应的模板
      if (|Score| > 0)
      for i := 0 to |Score| - 1 by 1
      *创建一个待测区域的变换矩阵
      vector_angle_to_rigid (0, 0, 0, RowCheck[i], ColumnCheck[i], AngleCheck[i], MovementOfObject)
      *获取模板的轮廓
      affine_trans_contour_xld (ShapeModel, ModelAtNewPosition, MovementOfObject)
      *显示轮廓
      dev_display (ModelAtNewPosition)
      • 测试每个锯齿之间的距离
        *将左右的待测区域,变换到目前的测试图像上
        affine_trans_region (MeasureROI1Ref, MeasureROI1AtNewPosition, MovementOfObject, ‘constant’)
        affine_trans_region (MeasureROI2Ref, MeasureROI2AtNewPosition, MovementOfObject, ‘constant’)
        dev_display (MeasureROI1AtNewPosition)
        dev_display (MeasureROI2AtNewPosition)
        *应用仿射变换,变换到到像素坐标。
        affine_trans_pixel (MovementOfObject, DistRect1CenterRow, DistRect1CenterCol, Rect1RowCheck, Rect1ColCheck)
        affine_trans_pixel (MovementOfObject, DistRect2CenterRow, DistRect2CenterCol, Rect2RowCheck, Rect2ColCheck)
        if (USING_TRANSLATE_MEASURE != 0)
        • -> translate the already created measure objects
          translate_measure (MeasureHandle1, Rect1RowCheck, Rect1ColCheck)
          translate_measure (MeasureHandle2, Rect2RowCheck, Rect2ColCheck)
          measure_pairs (SearchImage, MeasureHandle1, 2, 25, ‘negative’, ‘all’, RowEdge11, ColEdge11, Amp11, RowEdge21, ColEdge21, Amp21, Width1, Distance1)
          measure_pairs (SearchImage, MeasureHandle2, 2, 25, ‘negative’, ‘all’, RowEdge12, ColEdge12, Amp12, RowEdge22, ColEdge22, Amp22, Width2, Distance2)
          else
          *建立测量的句柄
          RectPhiCheck := RectPhi + AngleCheck[i]
          gen_measure_rectangle2 (Rect1RowCheck, Rect1ColCheck, RectPhiCheck, RectLength1, RectLength2, Width, Height, ‘bilinear’, MeasureHandle1)
          gen_measure_rectangle2 (Rect2RowCheck, Rect2ColCheck, RectPhiCheck, RectLength1, RectLength2, Width, Height, ‘bilinear’, MeasureHandle2)
        • 使用measure_pairs,一对一对的测量
          measure_pairs (SearchImage, MeasureHandle1, 2, 25, ‘negative’, ‘all’, RowEdge11, ColEdge11, Amp11, RowEdge21, ColEdge21, Amp21, Width1, Distance1)
          measure_pairs (SearchImage, MeasureHandle2, 2, 25, ‘negative’, ‘all’, RowEdge12, ColEdge12, Amp12, RowEdge22, ColEdge22, Amp22, Width2, Distance2)
          close_measure (MeasureHandle1)
          *关闭测量句柄
          close_measure (MeasureHandle2)
          endif
          *左边的锯齿数量
          NumberTeeth1 := |Width1|
          *右边的锯齿数量
          NumberTeeth2 := |Width2|
          dev_set_color (‘red’)
          *如果左边的数量<37
          if (NumberTeeth1 < 37)
          for j := 0 to NumberTeeth1 - 2 by 1
          *计算每一对锯齿之间的角度
          if (Distance1[j] > 4.0)
          RowFault := round(0.5 * (RowEdge11[j + 1] + RowEdge21[j]))
          ColFault := round(0.5 * (ColEdge11[j + 1] + ColEdge21[j]))
          *将超过4像素的区域显示出来
          disp_rectangle2 (WindowHandle, RowFault, ColFault, 0, 4, 4)
          新开一个8080大小的窗口,显示在原来窗口的右边
          dev_open_window (0, Width + 20, 80, 80, ‘black’, WindowHandleZoom)
          *显示区域
          dev_set_part (RowFault - 10, ColFault - 10, RowFault + 10, ColFault + 10)
          *显示缺陷图像
          dev_display (SearchImage)
          *再在小窗口上显示缺牙区域
          disp_rectangle2 (WindowHandleZoom, RowFault, ColFault, 0, 4, 4)
          stop ()
          *关闭窗口
          dev_close_window ()
          dev_set_part (0, 0, Height - 1, Width - 1)
          endif
          endfor
          endif
          *和左边一样,看上文注释即可
          if (NumberTeeth2 < 37)
          for j := 0 to NumberTeeth2 - 2 by 1
          if (Distance2[j] > 4.0)
          RowFault := round(0.5 * (RowEdge12[j + 1] + RowEdge22[j]))
          ColFault := round(0.5 * (ColEdge12[j + 1] + ColEdge22[j]))
          disp_rectangle2 (WindowHandle, RowFault, ColFault, 0, 4, 4)
          dev_open_window (0, Width + 20, 80, 80, ‘black’, WindowHandleZoom)
          dev_set_part (RowFault - 10, ColFault - 10, RowFault + 10, ColFault + 10)
          dev_display (SearchImage)
          disp_rectangle2 (WindowHandleZoom, RowFault, ColFault, 0, 4, 4)
          stop ()
          dev_close_window ()
          dev_set_part (0, 0, Height - 1, Width - 1)
          endif
          endfor
          endif
          dev_set_color (‘yellow’)
          stop ()
          endfor
          endif
  • ------------------- end of the application -----------------
  • clean up
    if (USING_TRANSLATE_MEASURE != 0)
    *关闭测量句柄
    close_measure (MeasureHandle1)
    close_measure (MeasureHandle2)
    endif
    dev_update_window (‘on’)
    *清空模板
    clear_shape_model (ModelID)

对应示例程序:
align_measurements.hdev

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值