前言
基于Halcon的差异模型完整性检测
一、思路
①获取图像使用的图像分为两类,一类是用于训练差异模型的图像;另一类是用于测试的图像,即实际检测图像。其中,图像如果是彩色的,需要将其转换成灰度图。如果存在一定的噪声,需要通过平滑去噪等预处理。当然,如果图片质量不佳或者ROI细节不够突出,也可以考虑重新采集,使图像的检测细节更为清晰。
②创建差异模型
图像预处理完之后,使用create_veriation_model算子创建一个用于对比的差异模型。
③图像对齐
由于用于训练差异模型的图像对每个点的灰度偏差都要进行计算,因此,参考图像或者是待检测的ROI需要先经过严格的对齐,避免可能的旋转和位移影响准确性,同样地,测试图像也需要对齐,只有对齐后的图像才可以进行点对点的灰度值比较。
具体过程为,确定一个ROI,再根据ROI建立形状模型,并在待对齐图像上通过形状模板匹配获得该ROI及其仿射参数。而后使用affine_trans_image算子将图像进行仿射变换,可使图像与ROI进行重合,便于后续的对比点的灰度值。
④训练差异模型
为了使理想的差异模型适应正常的容错范围,可以使用train_variation_model算子对多张良品样本对差异模型进行训练。
⑤准备差异模型参数
如果是多张图像的话,就使用prepare_variation_model算子设置模型参数,若是单张图像的话,则可使用prepare_direct_model算子将理想图像与差异模型图像关联起来。
⑥差异模型的比对
先对检测图像进行形状匹配,找到ROI,而后应用仿射变换使之与参考图像的ROI对齐,使用compare_variation_model将ROI跟差异模型进行对比,得到存在差异的局部区域。
⑦清除模型
待检查完毕,使用clear_variation_model算子清除模型,释放系统资源。
二、实现
三、源码
*清空显示窗口。
dev_close_window ()
*读取参考图像。这里读取图像是为了创建模板。
read_image (Image, 'D:/USER/Desktop/design/dataset/pen01.jpg')
*因为参考图像因为拍摄的原因会有一些噪声,因此使用均值滤波对图像进行平滑。
mean_image (Image, ImageMean, 3, 3)
*获取图像的宽和高用于窗口显示
get_image_size (Image, Width, Height)
*设置窗口显示参数,包括设置绘制线条的颜色和线宽等
dev_close_window ()
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
dev_set_color ('red')
dev_display (Image)
dev_set_draw ('margin')
dev_set_line_width(3)
*对原图进行阈值分割,粗略的提取出印刷图案的区域
threshold (ImageMean, Region, 0, 42)
*对印刷图案区域做一定的膨胀,使选区完全包围印刷图案部分
dilation_circle (Region, RegionDilation, 8.5)
*将选择转化为包围的形状
shape_trans (RegionDilation, RegionTrans, 'convex')
*将形状区域作为感兴趣区域从原图中分割出来
reduce_domain (ImageMean, RegionTrans, ImageReduced)
*检查形状模板参数,为后续的形状模板匹配检查合适的层级参数。
*这里只用了1层的金字塔图像,因为该形状已经可以满足检测的需求了
inspect_shape_model (ImageReduced, ModelImages, ModelRegions, 1, 20)
*创建形状的轮廓,为了显示形状便于检查形状选择的是否完整
gen_contours_skeleton_xld (ModelRegions, Model, 1, 'filter')
*获取图像的面积和几何中心点坐标
area_center (RegionTrans, Area, RowRef, ColumnRef)
*创建形状模板。
*金字塔层级为。因为测试图像与参考图像在光照,坐标方面的变化比较小,因此按默认值设置即可
create_shape_model (ImageReduced, 1, rad(-10), rad(10), 'auto', 'none', 'use_polarity', 20, 10, ShapeModelID)
*创建一个用于对比的差异模型,返回模型句柄VariationModelID
create_variation_model (Width, Height, 'byte', 'standard', VariationModelID)
*使用良品的训练图像对检查模板进行训练。
*其中为了将各个图像进行对齐,避免可能的位移和旋转,先对图像做个仿射变换。
*然后使用对变换后的良品图像进行训练,得到良品的检查模板。
for Num := 1 to 2 by 1
read_image (Image, 'D:/USER/Desktop/design/dataset/pen0' + Num)
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 (Model)
endif
endfor
*准备检查模板。设置两个阈值AbsThreshold, VarThreshold。
*前者定义了检测图像与检查模板的灰度差的绝对值的允许阈值。
*后者定义了与理想图像的差异程度
prepare_variation_model (VariationModelID, 20, 2)
*读取待检测的图像,这里开始正式检测。
*也可以连接相机进行拍摄,图像如果是彩色的,需要转换为单通道图像。
stop()
for Num := 1 to 3 by 1
read_image (Image2, 'D:/USER/Desktop/design/dataset/pen'+Num)
*进行模板匹配。寻找图中的形状
find_shape_model (Image2, ShapeModelID, rad(-10), rad(20), 0.5, 1, 0.5, 'least_squares', 4, 0.9, Row, Column, Angle, Score)
if (|Score| == 1)
*如果匹配成功,现将图像进行仿射变换用于和模板对齐。
vector_angle_to_rigid (Row, Column, Angle, RowRef, ColumnRef, 0, HomMat2D)
affine_trans_image (Image2, ImageTrans2, HomMat2D, 'constant', 'false')
*然后裁剪出感兴趣区域。对后面的比对做准备
reduce_domain (ImageTrans2, RegionTrans, ImageReduced2)
*将裁剪后的感兴趣区域图像与检查模板图像进行比对。提取出有差异的部分
compare_variation_model (ImageReduced2, RegionDiff, VariationModelID)
*将差异部分的区域分割开来
connection (RegionDiff, ConnectedRegions)
*对差异图像区域进行筛选,根据差异的面积排除掉极微小的无意义的差别部分。
select_shape (ConnectedRegions, RegionsError, 'area', 'and', 20, 1000000)
*计算提取出的差异的个数,作为缺陷数量。这是为了判别最终结果
count_obj (RegionsError, NumError)
*将缺陷部位标记出来。如果是良品,则显示的是没有标记的测试图像
dev_clear_window ()
dev_display (ImageTrans2)
dev_display (RegionsError)
*打印结果。
*如果结果为0,可以认为是良品,没有发生缺陷
*如果缺陷个数不为0,则认为是次品
set_tposition (WindowHandle, 20, 20)
if (NumError == 0)
write_string (WindowHandle, 'OK')
else
write_string (WindowHandle, 'Not OK')
endif
endif
stop()
endfor
总结
希望对你有所帮助,如有疑惑欢迎留言交流。