当前位置 博文首页 > 唯有自己强大:halcon——缺陷检测常用方法总结(模板匹配(定位
机器视觉中缺陷检测分为一下几种:
本篇主要总结一下缺陷检测中的定位+差分的方法。即用形状匹配,局部变形匹配去定位然后用差异模型去检测缺陷。
??整体思路(形状匹配):
模板匹配(定位)+差分的方法主要用来检测物品损坏,凸起,破洞,缺失,以及质量检测等。
??halcon例程分析:
1,印刷质量缺陷检测(print_check.hdev)
该例程用到了差异模型,将一个或多个图像同一个理想图像做对比,去找到明显的不同。进而鉴定出有缺陷的物体。差异模型的优势是可以直接通过它们的灰度值做比较,并且通过差异图像,比较可以被空间地加权。
变化模型检测缺陷的整体思路:
dev_update_off () * 选择第1张图像创建形状模板 read_image (Image, 'pen/pen-01') get_image_size (Image, Width, Height) dev_close_window () dev_open_window (0, 0, Width, Height, 'black', WindowHandle) set_display_font (WindowHandle, 16, 'mono', 'true', 'false') dev_set_color ('red') dev_display (Image) * 把我感兴趣的区域抠出来,原则上范围越小越好,因为这样创建模板时干扰会少很多 threshold (Image, Region, 100, 255) fill_up (Region, RegionFillUp) difference (RegionFillUp, Region, RegionDifference) shape_trans (RegionDifference, RegionTrans, 'convex') dilation_circle (RegionTrans, RegionDilation, 8.5) reduce_domain (Image, RegionDilation, ImageReduced) inspect_shape_model (ImageReduced, ModelImages, ModelRegions, 1, 20) gen_contours_skeleton_xld (ModelRegions, Model, 1, 'filter') * 获得抠图区域的中心,这是参考点 area_center (RegionDilation, Area, RowRef, ColumnRef) * 创建形状模板 create_shape_model (ImageReduced, 5, rad(-10), rad(20), 'auto', 'none', 'use_polarity', 20, 10, ShapeModelID)* 创建变化模型(用于和缺陷比较) create_variation_model (Width, Height, 'byte', 'standard', VariationModelID) * 文件夹中前15张图片是质量良好的,可以用来训练模板 for I := 1 to 15 by 1 read_image (Image, 'pen/pen-' + I$'02d') * 先寻找模板的实例 find_shape_model (Image, ShapeModelID, rad(-10), rad(20), 0.5, 1, 0.5, 'least_squares', 0, 0.9, Row, Column, Angle, Score) if (|Score| == 1) * 使用仿射变换,将当前图像平移旋转到与模板图像重合,注意是当前图像转向模板图像 vector_angle_to_rigid (Row, Column, Angle, RowRef, ColumnRef, 0, HomMat2D) affine_trans_image (Image, ImageTrans, HomMat2D, 'constant', 'false') * 训练差异模型 train_variation_model (ImageTrans, VariationModelID) dev_display (ImageTrans) dev_display (Model) endif endfor * 获得差异模型 get_variation_model (MeanImage, VarImage, VariationModelID) * 做检测之前可以先用下面这个算子对可变模型进行设参,这是一个经验值,需要调试者调整 prepare_variation_model (VariationModelID, 20, 3) dev_set_draw ('margin') NumImages := 30 * 可变模板训练完成后,我们终于可以进入主题,马上对所有图像进行缺陷检测,思想就是差分 for I := 1 to 30 by 1 read_image (Image, 'pen/pen-' + I$'02d') * 要注意做差分的两幅图像分辨率相同,当然也需要通过仿射变换把待检测的图像转到与模板图像重合 * 先寻找模板的实例 find_shape_model (Image, ShapeModelID, rad(-10), rad(20), 0.5, 1, 0.5, 'least_squares', 0, 0.9, Row, Column, Angle, Score) if (|Score| == 1) * 使用仿射变换,将当前图像平移旋转到与模板图像重合,注意是当前图像转向模板图像 vector_angle_to_rigid (Row, Column, Angle, RowRef, ColumnRef, 0, HomMat2D) affine_trans_image (Image, ImageTrans, HomMat2D, 'constant', 'false') * 抠图 reduce_domain (ImageTrans, RegionDilation, ImageReduced) * 差分 (就是检查两幅图像相减,剩下的区域就是不同的地方了,与模板图像不同的地方就是缺陷) * 这里可不能用difference做差分啊,halcon为变形模板提供了专门的差分算子:compare_variation_model compare_variation_model (ImageReduced, RegionDiff, VariationModelID) connection (RegionDiff, ConnectedRegions) * 特征选择:用一些特征来判断这幅图像印刷是否有缺陷,这里使用面积 * 其实可以考虑利用区域面积的大小来判断缺陷的严重程度,这里就不过多讨论了 select_shape (ConnectedRegions, RegionsError, 'area', 'and', 20, 1000000) count_obj (RegionsError, NumError) dev_clear_window () dev_display (ImageTrans) dev_set_color ('red') dev_display (RegionsError) set_tposition (WindowHandle, 20, 20) if (NumError == 0) dev_set_color ('green') write_string (WindowHandle, 'Clip OK') else dev_set_color ('red') write_string (WindowHandle, 'Clip not OK') endif endif if (I < NumImages) disp_continue_message (WindowHandle, 'black', 'true') stop () endif endfor * 结语:如果发现前面作为训练变形模板的良好图像也被判定为NG, * 可以调整prepare_variation_model参数 * 或者调整select_shape特征筛选的标准
相关算子分析:
create_variation_model(Width, Height, Type, Mode ,ModelID)
//创建一个ID为ModelID,宽为Width,高为Height,类型为Type的差异模型参数
参数Mode决定了创建标准图像和相应的变化图像的方法。(可选三种方法)
get_variation_model(Image, VarImage ,ModelID )
//返回差异模型中的标准图像(Image)和差异图像(VarImage),此算子主要用来检视创建的差异模型是否OK。
train_variation_model(Images, ModelID )
prepare_variation_model( : : ModelID, AbsThreshold, VarThreshold : ) //设置variation model(差异模型)的绝对阈值和相对阈值。 //绝对阈值即待检测图像与标准图像的差值, //相对阈值即待检测图像与variation model与VarThreshold乘积的差值。
compare_variation_model(Image : Region : ModelID : ) //待检测图像与variation model进行比较,超过阈值的区域在Rgion参数中返回。
同threshold一样,返回的区域被看做一个区域,可以使用connection算子进行连通性分析,然后根据区域的特征(如面积)对区域进行选择。
总结:
差异模型(Variation Model)使用标准图像与待检测图像灰度值相比较,来判断产品是否OK,适用于印刷品检测及产品表面检测。
从实际算法过程可以看出,此检测实际可分为两部分:
所以在实际应用中,应根据实际情况设置AbsThreshold和VarThreshold的值。
2,检测工件孔洞毛刺缺陷 - 局部变形匹配(inspect_gasket_local_deformable.hdev)
在日常工程应用中,我们通常通过halcon的形状匹配(shape-based matching)进行各种定位,正如上篇例程,当待匹配物体有轻微变形时,并不影响得到的匹配结果,然后当待匹配物体有较大变形时,如塑料产品在成形时变形、纺织产品的花纹因为褶皱变形等,要想得到精确的定位结果就显得捉襟见肘,如下图所示,工件如果有较大变形,在用形状匹配时,定位结果就不尽如人意,因为形状匹配本身得到的匹配结果只是一个点(row,col)。
因此本篇例程使用了局部变形匹配(local deformable matching),匹配结果可以根据待匹配物体自动进行变形。而且在这个案例中,create_variation_model (Width, Height, ‘byte’, ‘direct’, VariationModelID) 使用的方法是’direct’,因此是不需要训练差异模型而可以直接使用的。
1??读入标准图像,创建差异模型以及匹配模板
*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)
标准图像:
这里由于是用单幅图像创建的差异模型,因此参数Mode设置的’direct’,故不需要再去训练,而是直接使用prepare_direct_variation_model (ModelImage, EdgeAmplitude, VariationModelID, 20, 2)得到差异模型。
2??通过匹配模板将待检测工件定位矫正
for Index := 1 to 7 by 1 read_image (Image, 'gasket/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) if (|Score| > 0) gen_warped_mesh_region (VectorField, MeshRegion, 25