【测量篇】(3)标定+定位+1D测量综合实例

2019-06-19 15:53:35 浏览数 (1)

“高端市场人抬人,低端市场人踩人!”

在后台收到信息,莫名其妙被人投诉了,不知触犯了哪些人的利益,本人依然会本着分享交流的精神,共促行业的繁荣。如果您能一路跟过来,halcon视觉入门到提高,完全没问题。


测量需求:火花塞间隙尺寸

测量项目一般使用远心镜头 平行背光

远心镜头可以最大程度避免图像畸变

平行背光可以清晰得到图像边缘轮廓

原图如下

- 算法思路 -

1. 相机标定,减少镜头畸变以及得到公有制单位 2. 模板匹配 仿射变换 定位 3. 1D测量边缘对

1

相机标定

采集多幅不同位姿、清晰的标定板图片

例程采集14幅

以下为其中2幅

首先指定相机标定的一些初始值,标定目标,相机内参初始值,设置标定数据模型的对象和参数等

代码语言:javascript复制
*------指定标定初始值-----------*
*指定标定描述文件
CaltabName := 'caltab_10mm.descr'
*由于使用远心镜头,放大倍率为0.17,径向畸变的初始值为0,世界坐标系的物理尺寸为66um,主点位于图像中心 
gen_cam_par_area_scan_telecentric_division (0.17, 0, 6.6e-06, 6.6e-06, 320, 240, 640, 480, StartCamParam)
*创建标定数据模型
create_calib_data ('calibration_object', 1, 1, CalibDataID)
*设置标定板描述文件
set_calib_data_calib_object (CalibDataID, 0, CaltabName)
*设置相机参数
set_calib_data_cam_param (CalibDataID, 0, [], StartCamParam)

通过find_calib_object、calibrate_cameras完成所有标定图片的相机标定,最终通过calibrate_cameras得到相机内部参数

内参可以将图像测量用世界单位表示,不需要知道火花塞在世界坐标系的具体位置,所以只需标定内参即可

代码语言:javascript复制
*----------标定所有图片-------*
for Index := 1 to 14 by 1
    read_image (Image, 'spark_plug/spark_plug_calib_'   Index$'02')
    dev_display (Image)
    dev_disp_text ('Collect calibration data', 'window', 12, 12, 'black', [], [])
    *获取标定对象,并添加到数据模型中
    find_calib_object (Image, CalibDataID, 0, 0, Index, [], []) 
    *得到标定数据轮廓
    get_calib_data_observ_contours (Contours, CalibDataID, 'marks', 0, 0, Index)
    dev_set_color ('green')
    dev_display (Contours)
endfor
dev_disp_text ('Calibration of the telecentric camera', 'window', 12, 12, 'black', [], [])
*计算标定数据的内部参数
calibrate_cameras (CalibDataID, Error)
*查询标定数据模型中存储的数据
get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam)
dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', [], [])
stop ()

远心镜头标定

2

模板匹配

为了确定火花塞在图像中的位置,

使用鲁棒性比较好的形状模板匹配

模板需要选取所有火花塞共有的、唯一的、不变的特征

红色十字是模型的重心,为在线测量时能正确匹配的参考点

由于所有火花塞方向大致相同,模型创建的时候仅需要考虑 -30°

此部分代码

代码语言:javascript复制
read_image (ModelImage, 'spark_plug/spark_plug_01')
gen_rectangle1 (ModelRegion, 120, 230, 220, 445)
reduce_domain (ModelImage, ModelRegion, TemplateImage)
*创建形状模型
create_shape_model (TemplateImage, 'auto', rad(-30), rad(60), 'auto', 'none', 'use_polarity', 'auto', 'auto', ModelID)
area_center (ModelRegion, Area, RefRow, RefCol)
*得到形状模型轮廓
get_shape_model_contours (ModelContours, ModelID, 1)
get_shape_model_contour_ref (ModelRegion, ModelContoursTrans, ModelID)
gen_cross_contour_xld (CrossRef, RefRow, RefCol, 20, 0)
dev_display (ModelImage)
dev_set_color ('magenta')
dev_display (ModelContoursTrans)
dev_display (CrossRef)
dev_disp_text ('Contour and reference point of the shape model', 'window', 12, 12, 'black', [], [])
dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', [], [])
stop ()

3

测量矩形

相对模型参考点,定义测量矩形

矩形方向使其与主轴测量方向一致

4

在线测量

以上测量均为离线的

在线检测首先读图,然后利用模式匹配在图像上找到火花塞

代码语言:javascript复制
 read_image (Image, 'spark_plug/spark_plug_'   Index$'02')
    * Find the spark plug in the image
    find_shape_model (Image, ModelID, rad(-30), rad(60), 0.7, 1, 0.5, 'least_squares', 0, 0.9, Row, Column, Angle, Score)

根据匹配到位姿,利用仿射变换矩阵,创建测量矩形

代码语言:javascript复制
   vector_angle_to_rigid (0, 0, 0, Row, Column, Angle, HomMat2D)
        * Display the match
        affine_trans_contour_xld (ModelContours, ModelContoursTrans, HomMat2D)
        dev_set_color ('magenta')
        dev_display (ModelContoursTrans)
        * Transform the model reference point
        affine_trans_pixel (HomMat2D, RectRelRow, RectRelCol, TransRow, TransCol)
        * Display measurement rectangle
        gen_rectangle2_contour_xld (MeasureRectangle, TransRow, TransCol, Angle   RectRelPhi, RectLen1, RectLen2

使用一维测量算子measure_pairs实际测量边缘对

代码语言:javascript复制
        measure_pairs (Image, MeasureHandle, 1, 30, 'positive_strongest', 'all', Row1, Col1, Amplitude1, Row2, Col2, Amplitude2, IntraDistance, InterDistance)

利用标定得到的内参CamParam将测量结果转换至世界单位制

通过简单几何知识计算缝隙距离

代码语言:javascript复制
  get_line_of_sight ([Row1,Row2], [Col1,Col2], CamParam, X, Y, Z, XH, YH, ZH)
            DX := X[1] - X[0]
            DY := Y[1] - Y[0]
            GapSize := sqrt(DX * DX   DY * DY)

根据确定的尺寸公差,判断所测得距离是否合格

后续根据所测结果,决定是否剔除不合格产品

代码语言:javascript复制
* Specify the tolerance of the gap in meters
            GapSizeMin := 0.78e-3
            GapSizeMax := 0.88e-3
            * Evaluate the result
            if (GapSize < GapSizeMin)
                * Gap size is too small
                StatusText := 'Gap size too small'
                dev_set_color ('red')
            elseif (GapSize > GapSizeMax)
                * Gap size is too large
                StatusText := 'Gap size too large'
                dev_set_color ('red')
            else
                * Gap size is within tolerances
                StatusText := 'Gap size ok'
                dev_set_color ('green')
            endif

在此对在线检测流程进行总结

首先,使用模板匹配得到火花塞位姿,并对其进行二维刚性变换,使得模型与图像中的火花塞重合

其次,利用得到的变换对测量矩形中心的相对位置进行变换,使得矩形方向与火花塞方向一致

最后,利用标定得到的内参将测量结果转换至世界单位制,计算缝隙距离,并根据公差判断产品是否合格

测量结果如下图

注:本次例程来书籍《机器视觉算法与应用》,是行业入门与提高的不二之选, 书籍pdf与所有案例的halcon程序以及原图,请见如下百度云连接:

链接:https://pan.baidu.com/s/1FuD3prrc5ApBl4Ewqmqz6w

提取码:208c

0 人点赞