1. 简单的差分

案例1:检测毛刺

fin.hdev
这个案例还是比较简单的,主要思想就是利用图像差分的思想。

Halcon

* 检测毛刺
ImageFiles := []
ImageFiles[0] := './fin1.png'
ImageFiles[1] := './fin2.png'
ImageFiles[2] := './fin3.png'
for Index := 0 to |ImageFiles| - 1 by 1
       read_image (Image, ImageFiles[Index])
       binary_threshold (Image, Region, 'max_separability', 'light', UsedThreshold)
       closing_circle (Region, RegionClosing, 203.5)
       reduce_domain (Image, RegionClosing, ImageReduced)
       reduce_domain (Image, Region, ImageReduced1)
       *差分
       difference (ImageReduced, ImageReduced1, RegionDifference)
       opening_circle (RegionDifference, RegionOpening, 3)
      
       dev_set_draw ('margin')
       dev_set_line_width (5)
       dev_display (Image)
       dev_display (RegionOpening)
       stop()
endfor


案例2:电路板线路缺陷检测

pcb_inspection.hdev
在这里插入图片描述

*检测电路板上断开和突出的缺陷 差分思想
read_image(Image, './pcb.png')

*灰度图的形态学处理:
*灰度图开运算和膨胀是增加亮像素,闭运算和腐蚀是减少亮像素
gray_closing_shape (Image, ImageClosing, 7, 7, 'octagon')//八边形
gray_opening_shape (Image, ImageOpening, 7, 7, 'octagon')

dyn_threshold (ImageClosing, ImageOpening, RegionDynThresh, 75, 'light')

dev_set_color ('blue')
dev_set_line_width (3)
dev_display (Image)
dev_display (RegionDynThresh)

案例3:瓶口破损缺陷检测

inspect_bottle_mouth.hdev

这个案例要注意直角坐标系和极坐标系之间的转换。
在这里插入图片描述

在这里插入图片描述
halcon代码:

dev_get_window (WindowHandle)
set_display_font (WindowHandle, 46, 'mono', 'true', 'false')
*dev_set_draw ('margin')
dev_set_line_width (3)

list_files ('./', ['files','follow_links'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)
for Index := 0 to |ImageFiles| - 1 by 1
       read_image (Image, ImageFiles[Index])
       get_image_size (Image, Width, Height)
       threshold (Image, Regions, 0, 60)
       fill_up (Regions, RegionFillUp)
       connection (RegionFillUp, ConnectedRegions)
       select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 23131.1, 97562.3)
       smallest_circle (SelectedRegions, Row, Column, Radius) 
       polar_trans_image_ext(Image, PolarTransImage,Row, Column, 0, 6.28319, Radius-60, Radius, 2*Radius*3.14, 60, 'nearest_neighbor')
       *拉开图像的对比度
       scale_image_max (PolarTransImage, ImageScaleMax)
       mean_image (ImageScaleMax, ImageMean, 500, 3)
       dyn_threshold (ImageScaleMax, ImageMean, RegionDynThresh, 65, 'not_equal')
       *opening_circle (RegionDynThresh, RegionOpening, 2.5)
       connection (RegionDynThresh, ConnectedRegions1)
       
       select_shape (ConnectedRegions1, SelectedRegions1, 'height', 'and', 9, 1000)
       count_obj (SelectedRegions1, Number)
       union1 (SelectedRegions1, RegionUnion)
       polar_trans_region_inv (RegionUnion, XYTransRegion, Row, Column, 0, rad(360), Radius-60, Radius, 2*Radius*3.14, 60, 1280, 1024, 'nearest_neighbor')
          
       dev_display (Image)          
       dev_display (XYTransRegion)             
       if(Number>0)
           Text:='NG'  
       else
           Text:='OK'    
       endif       
       disp_message (WindowHandle, Text, 'image', 82, 82, 'black', 'true')
       stop()
endfor

2. 模板匹配定位+差分

这种方法用来检测印刷上的缺陷有时还是蛮好用的。
这一块的例子都在halcon 例程:方法-变化的模板中

基于形状的模板匹配定位+差分方法的基本步骤:

  1. create_variation_model —— 创建一个变化模板
  2. get_variation_model —— 获得变化模板
  3. train_variation_model —— 训练变化模板
  4. prepare_variation_model —— 准备变化模板
  5. compare_variation_model —— 比较模板与实例
  6. clear_variation_model —— 清除变化模板

说的再多都没有用,详细的思路都已经卸载代码里了。Talk is cheap, show me code.

案例1:印刷质量缺陷检测(standard)

print_check.hdev

在这里插入图片描述
在这里插入图片描述

Halocn代码:

* 显示设置
dev_update_off ()
dev_get_window (WindowHandle)
dev_set_line_width (3)
set_display_font (WindowHandle, 66, 'mono', 'true', 'false')
dev_set_draw ('margin')

* 读入图像
list_files ('./', ['files','follow_links'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)

* 选择第1张图像创建形状模板
read_image (Image, ImageFiles[0])

* 把我感兴趣的区域抠出来,原则上范围越小越好,因为这样创建模板时干扰会少很多
gen_rectangle1 (ROI_0, 77.5719, 39.3148, 216.784, 414.913)
reduce_domain (Image, ROI_0, ImageReduced)
threshold (ImageReduced, Regions, 0, 119)
reduce_domain (ImageReduced, Regions, ImageReduced1)
opening_circle (Regions, RegionOpening, 2.5)
shape_trans (RegionOpening, RegionTrans, 'convex')
dilation_circle (RegionTrans, RegionDilation, 8.5)
reduce_domain (ImageReduced, RegionDilation, ImageReduced2)

* 获得抠图区域的中心,这是参考点
area_center (RegionDilation, Area, RowRef, ColumnRef)

* 创建模板
create_shape_model (ImageReduced2, 3, rad(-5), rad(10), 'auto', 'pregeneration', 'use_polarity', 20, 10, ModelID)
* 获得模板轮廓,看一下质量怎么样,非常完美
get_shape_model_contours (ModelContours, ModelID, 1)

* 创建可变模板
get_image_size (Image, Width, Height)
create_variation_model (Width, Height, 'byte', 'standard', VarModelID)//这里使用'standard'

* 文件夹中前15张图片是质量良好的,可以用来训练模板
for Index := 0 to 14 by 1
       read_image (Image, ImageFiles[Index])
       * 先寻找模板的实例
       find_shape_model (Image, ModelID, rad(-5), rad(10), 0.5, 1, 0.5, 'least_squares', 0, 0.9, Row, Column, Angle, Score)
       if(|Row|>0)
              * 使用仿射变换,将当前图像平移旋转到与模板图像重合,注意是当前图像转向模板图像
              vector_angle_to_rigid (Row, Column, Angle, RowRef, ColumnRef, 0, HomMat2D)
              affine_trans_image (Image, ImageAffineTrans, HomMat2D, 'bilinear', 'false')
       endif
       * 既然当前图像已经转到和第一张图像重合了,我就可以使用第一张图像抠图使用的区域进行抠图了
       reduce_domain(ImageAffineTrans, RegionDilation, ImageReduced3)       
       * 训练可变模板
       train_variation_model (ImageReduced3, VarModelID)            
endfor


* 获得变形模型
get_variation_model (Image1, VarImage, VarModelID)
dev_display (VarImage)
stop()

* 做检测之前可以先用下面这个算子对可变模型进行设参,这是一个经验值,需要调试者调整
prepare_variation_model (VarModelID, 20, 2)

* 可变模板训练完成后,我们终于可以进入主题,马上对所有图像进行缺陷检测,思想就是差分
for Index := 0 to |ImageFiles|-1 by 1
       read_image (Image, ImageFiles[Index])
       * 要注意做差分的两幅图像分辨率相同,当然也需要通过仿射变换把待检测的图像转到与模板图像重合
       * 先寻找模板的实例
       find_shape_model (Image, ModelID, rad(-5), rad(10), 0.5, 1, 0.5, 'least_squares', 0, 0.9, Row, Column, Angle, Score)
       if(|Row|>0)
              * 使用仿射变换,将当前图像平移旋转到与模板图像重合,注意是当前图像转向模板图像
              vector_angle_to_rigid (Row, Column, Angle, RowRef, ColumnRef, 0, HomMat2D)
              affine_trans_image (Image, ImageAffineTrans, HomMat2D, 'bilinear', 'false')
       endif
       * 抠图
       reduce_domain (ImageAffineTrans, RegionDilation, ImageReduced4)
       * 差分 (就是检查两幅图像相减,剩下的区域就是不同的地方了,与模板图像不同的地方就是缺陷)
       * 这里可不能用difference做差分啊,halcon为变形模板提供了专门的差分算子:compare_variation_model
       compare_variation_model (ImageReduced4, Region, VarModelID)
       
       * 图像分割
       connection (Region, ConnectedRegions)
       
       * 特征选择:用一些特征来判断这幅图像印刷是否有缺陷,这里使用面积
       * 其实可以考虑利用区域面积的大小来判断缺陷的严重程度,这里就不过多讨论了
       select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 25, 99999)

            
       * 显示
       dev_display (ImageAffineTrans)
       count_obj (SelectedRegions, Number)
       disp_message (WindowHandle, '第'+(Index+1)+'张','image', 12, 300, 'black', 'true')
       if(Number>0)
              disp_message (WindowHandle, 'NG', 'image', 12, 12, 'red', 'false')
              dev_set_color ('red')
       else
              disp_message (WindowHandle, 'OK', 'image', 12, 12, 'green', 'false')             
              dev_set_color ('green')
       endif      
       dev_display (SelectedRegions)
       stop()
endfor
dev_update_on ()  
* 结语:如果发现前面作为训练变形模板的良好图像也被判定为NG,
*      可以调整prepare_variation_model参数
*      或者调整select_shape特征筛选的标准


案例2:检测工件孔洞毛刺缺陷 - 局部变形(direct)

  • 和上一个案例不同的是,这个案例的工件发生了局部变形,所以定位需要使用局部变形模板,这样才能找到实例并且定位。而且在这个案例中,create_variation_model (Width, Height, ‘byte’, ‘direct’, VariationModelID) 使用的方法是’direct’,因此是不需要训练变化的模板而可以直接使用的。具体用法还是看代码吧:
  • 值得高兴的是,局部变形模板匹配这种方法是自动矫正的,因此我们可以省掉仿射变换的步骤了。
    在这里插入图片描述在这里插入图片描述
    Talk is cheap. Show me your code.
*1.读入图像
dev_update_off ()
dev_get_window (WindowHandle)
set_display_font (WindowHandle, 36, 'mono', 'true', 'false')
dev_set_draw ('margin')

read_image (ModelImage, 'gasket/gasket_model')
get_image_size (ModelImage, Width, Height)
read_image (Image, 'gasket/gasket_01')
*2.创建变形模型
create_variation_model (Width, Height, 'byte', 'direct', VariationModelID)
sobel_amp (ModelImage, EdgeAmplitude, 'sum_abs', 3)
*3.直接设参数+标准图像+边缘幅度图像
prepare_direct_variation_model (ModelImage, EdgeAmplitude, VariationModelID, 20, 2)
*4.创建模板
create_local_deformable_model (ModelImage, 'auto', [], [], 'auto', 0.9, [], 'auto', 0.9, [], 'auto', 'none', 'use_polarity', 'auto', 'auto', [], [], ModelID)
get_deformable_model_contours (ModelContours, ModelID, 1)
area_center (ModelImage, Area, Row, Column)

for Index := 1 to 7 by 1
    read_image (Image, './gasket_' + Index$'02')
    get_image_size (Image, Width1, Height1)
    *5.查找
    find_local_deformable_model (Image, ImageRectified, VectorField, DeformedContours, ModelID, \
    rad(-10), rad(20), 1, 1, 1, 1, 0.93, 1, 0.7, 0, 0.4,\
                                 ['image_rectified','vector_field','deformed_contours'], \
                                 ['deformation_smoothness','expand_border','subpixel'], \
                                 [25,0,1], Score, Row, Column)
    *6.差分
    compare_variation_model (ImageRectified, Region, VariationModelID)
    connection (Region, ConnectedRegions)
    select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 60, 99999)
    count_obj (SelectedRegions, Number)
    
    * 7.注意:这里显示的是修正过的图像  
    dev_display (ImageRectified)
    if(Number>0)          
           disp_message (WindowHandle, 'NG', 'image', 12, 12, 'red', 'false')
    else           
           disp_message (WindowHandle, 'OK', 'window', 12, 12, 'magenta', 'false')
    endif   
    dev_set_color ('red')
    dev_display (ConnectedRegions)
    stop()
endfor
dev_update_on ()

3. 拓展一下

1. 卡尺+差分

  • Halcon在例程-方法-变化的模板- point_line_to_hom_mat2d.hdev 这个案例中使用了卡尺定位,这种方法我个人感觉不是很好:卡尺没有形状匹配那么稳定,而且搜索的范围小,目标偏得远一点就找不到了,使用起来也没有形状匹配那么方便。
  • 而且这个案例中,
  • 这里非要使用这种方法,是为了凑数吗?这不是脱了裤子放屁——多此一举吗。
    在这里插入图片描述

2. 喷涂获得图像

  • Halcon在例程-方法-变化的模板- variation_model_single.hdev 这个案例中,是通过向区域中喷涂获得图像的(VarImage)
  • prepare_direct_variation_model (Image, VarImage, VarModelID, 15, 4)

喷涂算子:

  • paint_gray
  • paint_region
  • paint_xld

4. 资源下载地址

这里是代码和图片的下载地址,喜欢的小伙伴请关注我:

https://download.csdn.net/download/weixin_38566632/18217257