halcon案例:金属工件几何测量

描述

一、提要

对于官方帮助文件的案例,需要逐一跟踪代码,掌握这些技能不很容易,因为这需要多种算子互相搭配,可以说每一个案例都针对一个测量场景,因此,学习halcon不要从一个一个算子做起,而要从案例做起。因为具体问题不同,方法也不同,比如,地图的边缘提取,和加工零件的边缘提取做法有不同,注意这种细节。

二、必要的算子介绍

2.1 dev_set_draw

dev_set_draw 定义区域的填充模式。如果 DrawMode 设置为“filled”,则区域显示为填充,如果设置为“margin”,则仅显示轮廓。在 'margin' 模式下,轮廓的外观会受到 dev_set_line_width、set_line_approx 和 set_line_style 的影响。

1)算子形式

dev_set_draw( : : DrawMode : )

2)参数描述

DrawMode参数两个选项(“filled”,和 “margin”),设定完后,显示区域方式就变了,如图:

.2 area_center 

获得区域的面积和中心位置。

运算符 area_center 计算输入区域的面积和中心。面积定义为一个区域的像素数。中心分别计算为所有像素的行坐标或列坐标的平均值。如果传递了多个区域,则结果存储在元组中,元组中值的索引对应于输入区域的索引。在空白区域的情况下,如果没有设置其他行为,则所有参数的值都为 0.0(参见 set_system)。

1)算子形式

area_center(Regions : : : Area, Row, Column)

2)参数描述

Regions :输入区域

Area, 区域面积

Row, 行坐标

Column,列坐标

2.3 orientation_region

运算符orientation_region 计算区域的方向。运算符基于 elliptic_axis。此外,计算轮廓上与重心距离最大的点。如果在旋转坐标系中,该点的列坐标小于重心的列坐标,则将 的值加到角度上。如果传递了多个区域,则结果存储在元组中,元组中值的索引对应于输入中区域的索引。

1)算子形式

orientation_region(Regions : : : Phi)

2)参数描述

Regions :输入区域

Phi,  输出角度,就是区域不对称的旋转角度。也就是外接矩形的角

算法

disp_cross (WindowID, RowCenterRegion, ColumnCenterRegion, 15, 0)

disp_arrow (WindowID, RowCenterRegion, ColumnCenterRegion, RowCenterRegion - 60 * sin(OrientationRegion), ColumnCenterRegion + 60 * cos(OrientationRegion), 2)

显示十字叉、箭头。

三、边缘提取算子

3.1 edges_sub_pix

edges_sub_pix 使用递归实现的滤波器(根据 Deriche、Lanser 和 Shen)或 Canny 提出的传统实现的“高斯导数”滤波器(使用滤波器掩码)检测阶梯边缘。

1)算子形式

edges_sub_pix(Image : Edges : Filter, Alpha, Low, High : )

2)参数解释

Image : 输入图像

Edges : 输出边缘像素

Filter,:算法选择,可选择算法是【'deriche1', 'lanser1', 'deriche2', 'lanser2', 'shen', 'mshen', 'canny', 'sobel', and 'sobel_fast'】

Alpha,

Low,

High :

3)参数详细

edges_sub_pix 使用递归实现的滤波器(根据 Deriche、Lanser 和 Shen)或 Canny 提出的传统实现的“高斯导数”滤波器(使用滤波器掩码)检测阶梯边缘。因此,可以使用以下边缘运算符:“deriche1”、“lanser1”、“deriche2”、“lanser2”、“shen”、“mshen”、“canny”、“sobel”和“sobel_fast”

(参数过滤器)。

提取的边缘在 Edges 中作为亚像素精确的 XLD 轮廓返回。对于除 'sobel_fast' 之外的所有边缘运算符,为每个边缘点定义了以下属性(参见 get_contour_attrib_xld):

'edge_direction' 边缘方向

'angle' 法线向量到轮廓的方向(当轮廓从起点到终点遍历时,法线向量指向轮廓的右侧;角度是相对于图像的行轴给出的) .)

“响应”边缘幅度(梯度幅度)

除了'sobel'和'sobel_fast'之外的所有边缘算子的“滤波器宽度”(即平滑量)可以任意选择,可以通过调用info_edges来估计参数Alpha的具体值。对于所有过滤器(Deriche、Lanser 和 Shen 过滤器),“过滤器宽度”随着 Alpha 的增加而减小。唯一的例外是 Canny 过滤器,其中增加的 Alpha 也会导致“过滤器宽度”的增加。“宽”滤波器对噪声表现出更大的不变性,但检测小细节的能力也有所下降。非递归过滤器,例如 Canny 过滤器,是使用过滤器掩码实现的,因此增加过滤器宽度会增加执行时间。相反,递归过滤器的执行时间不取决于过滤器的宽度。因此,使用 Derche、Lanser 和 Shen 过滤器可以实现任意过滤器宽度,而不会增加操作员的运行时间。与 Canny 算子相比,由此产生的速度优势自然会随着更大的过滤器宽度而增加。作为边界处理,递归算子假设图像在图像之外为零,而 Canny 算子在图像边界处重复灰度值。可通过以下 Alpha 选择获得可比较的过滤器宽度:

3.2 get_contour_attrib_xld 

获取线段的属性特征参数值。

1)算子格式

get_contour_attrib_xld(Contour : : Name : Attrib)

2)参数解释

Contour:输入曲线对象XLD

Name:属性名称,值域为【 'regr_norm_row', 'regr_norm_col', 'regr_mean_dist', 'regr_dev_dist', 'cont_approx', 'bright_dark', 'is_hole'】

Attrib:输出属性值,1表示肯定,0表示否定

3)参数详细

用query_contour_global_attribs_xld(SingleSegment,Attribs)函数可以获取属性,只有【cont_approx】一项,因此,其它选项都不能用。

Name参数的值的意义:

cont_approx:有曲率的曲线,此时,Attrib=-1,直线;Attrib=0,椭圆;Attrib=1,圆

四、距离测量项目

4.1 项目描述

在下列工件中,测量出四个圆周的圆心之间距离。项目需要以下知识点:

如何区域生成?

如何边缘提取?

如何xld生成

如何xld分段?

xld分段如何访问?

如何获取曲线特征参数?

如何中心点距离测量?

4.2 参考代码

read_image (Image, 'metal-parts/metal-parts-01')

get_image_size (Image, Width, Height)

dev_close_window ()

dev_open_window (0, 0, Width, Height, 'light gray', WindowID)

dev_set_draw ('fill')

threshold (Image, Region, 100, 255)

clear_window(WindowID)

disp_region(Region, WindowID)

edges_sub_pix (Image, Edges, 'canny', 0.6, 30, 70)

segment_contours_xld (Edges, ContoursSplit, 'lines_circles', 6, 4, 4)

dev_clear_window ()

dev_set_colored (12)

dev_display (ContoursSplit)

count_obj (ContoursSplit, NumSegments)

dev_display (Image)

NumCircles := 0

RowsCenterCircle := []

ColumnsCenterCircle := []

for i := 1 to NumSegments by 1

select_obj (ContoursSplit, SingleSegment, i)

get_contour_global_attrib_xld (SingleSegment, 'cont_approx', Attrib)

if (Attrib == 1)

NumCircles := NumCircles + 1

fit_circle_contour_xld (SingleSegment, 'atukey', -1, 2, 0, 5, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder)

gen_circle_contour_xld (ContCircle, Row, Column, Radius, 0, rad(360), 'positive', 1)

RowsCenterCircle := [RowsCenterCircle,Row]

ColumnsCenterCircle := [ColumnsCenterCircle,Column]

dev_display (ContCircle)

endif

endfor

distance_pp (RowsCenterCircle[1], ColumnsCenterCircle[1], RowsCenterCircle[2], ColumnsCenterCircle[2], Distance_2_3)

distance_pp (RowsCenterCircle[0], ColumnsCenterCircle[0], RowsCenterCircle[2], ColumnsCenterCircle[2], Distance_1_3)

distance_pp (RowsCenterCircle[3], ColumnsCenterCircle[3], RowsCenterCircle[4], ColumnsCenterCircle[4], Distance_4_5)

编辑:黄飞

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分