前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【测量篇】(3)标定+定位+1D测量综合实例

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

作者头像
threeQing
发布2019-06-19 15:53:35
1.7K0
发布2019-06-19 15:53:35
举报

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

在后台收到信息,莫名其妙被人投诉了,不知触犯了哪些人的利益,本人依然会本着分享交流的精神,共促行业的繁荣。如果您能一路跟过来,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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器视觉那些事儿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档