Halcon轮廓的处理
文章目录
- Halcon轮廓的处理
- 1. 轮廓分割
- 2. 轮廓的筛选
- 3. 轮廓的连接
- 4. 轮廓的拟合
输出了目标的轮廓后,接下来还需要对轮廓进行处理,这主要基于以下3个原因。
(1)对于某些测量任务而言,并不需要分析目标的整个轮廓,可能只需要局部的一段轮廓就够了。而有时由于 ROI(感兴趣区域)选择得过大,因此需要对提取的轮廓进行分割,以得到所需的部分。
(2)在提取轮廓或线条的过程中,可能会有一些杂点或背景区域被误认为是轮廓也被提取了出来,所以需要做一些剔除,以得到完全需要的区域。
(3)提取出的轮廓线条可能会有一些不连续,而某些检测中需要轮廓是闭合的,因此需要做一些连接或者填补。
1. 轮廓分割
首先要介绍的是轮廓分割,可以使用segment_contours_xId 算子将轮廓分割成线段、圆弧或着椭圆等预定义的形状,分割出的各个线段可以使用select_obj算子单独进行选择。
如果只需要分割成线段,则可以使用gen_polygons_xld算子和split_contours_xld算子的组合,这两步操作的结果类似于segment_contours_xld算子的功能。两种方式的区别主要在于对轮廓进行分割后的处理,使用两步组合法,将生成XLD多边形类型的轮廓。
2. 轮廓的筛选
对于轮廓处理来说,很重要的一步是抑制不相关的轮廓,可以使用select_shape_xld算子实现这一功能。该算子的功能非常强大,与select_shape算子类似,它使用一步操作就能提取输入区域的多种特征并进行筛选。该算子提供了30多种不同的形状特征,通过指定不同特征的阈值并结合多种特征进行评估,能非常灵活地提取出理想的轮廓部分。也可以选择select_contours_xld算子,它包含了更多线性结构的典型特征。如果需要用鼠标进行交互操作,如实时选择一些轮廓,可以使用select_xld_point算子,通过单击鼠标来选取轮廓。
3. 轮廓的连接
如果轮廓的线条是不连续的,那么断开的部分会被当成独立的部分,后续的处理过程会更加棘手。这时可以试着将断开的部分连接起来,使用union_collinear_contours_xld算子或者 union_straight_contours_xld算子,就可以实现这一功能。前者适用于共线的连接,后者适用于同方向的邻近轮廓。还可以选择 union_adjacent_contours_xld算子,它适用于端点邻近的情况。
Halcon 也提供了一个shape_trans_xld算子用于修改形状,把轮廓转换成包围的圆或者矩形等。还可以使用union2_closed_contours_xld等算子合并闭合轮廓。
下面以一个简单的例子进行说明。图(a)为输入的图像;图(b)为使用edges_sub_pix 算子提取出的亚像素边缘的图像,分别用不同的颜色显示;图(c)为使用 segment_contours_xld 算子对上一步的轮廓进行分割,并使用select_contours_xld算子选择较长的边缘得到的结果;图(d)为对相邻但不相连的边缘使用union_adjacent_contours_xld算子进行连接的效果。
实现代码如下:
dev_close_window ()
read_image (Image, 'data/shapes')
rgb1_to_gray (Image, GrayImage)
get_image_size (Image, Width, Height)
dev_open_window (0, 0, Width , Height, 'black', WindowHandle)
*提取出的亚像素边缘edge的图像,得到了一个初始的轮廓
edges_sub_pix (GrayImage, Edges, 'canny', 2.5, 15, 40)
*对上一步的轮廓进行分割
segment_contours_xld (Edges, ContoursSplit, 'lines_circles', 5, 4, 2)
*提取出轮廓中较长的部分线段
select_contours_xld (ContoursSplit, SelectedContours, 'contour_length', 20, Width / 2, -0.5, 0.5)
*对相邻的轮廓段进行连接
union_adjacent_contours_xld (SelectedContours, UnionContours, 20, 1, 'attr_keep')
本例中使用edges_sub_pix算子提取出亚像素边缘的图像,在得到了初始轮廓之后,使用segment_contours_xld算子对上一步的轮廓进行分割,这是为了测试后面的轮廓合并。由于分割轮廓后会得到许多小的线段,为了移除这些小线段,为后面测试轮廓合并留下空间,需要使用select_contours_xld 算子提取出轮廓中较长的部分线段。选择的特征是contour_length,也可以选择其他特征,如direction 表示方向,curvature表示曲率等。还可以根据线段两端的距离阈值选择closed或者open。
选择出符合条件的轮廓之后,再对相邻的轮廓段进行连接。因为这幅图中的非连续线段不存在共线或者方向相同,而只有端点比较邻近,所以这种情况就选择使用union_ adjacent_contours_xld算子。这里设置了一个判断值20,如果两个端点之间的距离小于该值,就可以将它们相连。连接的顺序是,距离短的优先连接。
后面的attrkeep 参数表示输出的轮廓保留之前的cdges sub_pix算子提取出的各种特征。如果要计算的轮廓比较多,而计算速度是一个比较重要的考量点,或者某些轮廓在合并后特征将发生改变,保留原来的特征将失去意义,那么这里也可以选择 attr_forget 参数,不对输出的轮廓复制它们原有的特征。
4. 轮廓的拟合
前面得到的轮廓有可能是不规则的,实际检测中可能需要将其进行拟合,以得到规则的轮廓,便于后续处理。Halcon 提供了几种不同形状的拟合算子,简要介绍如下。
(1)拟合直线使用fitline_contour_xld算子,该算子提供了多种拟合的方法,大部分都是用于抑制非相关轮廓线的。该算子会返回线段和线段两端的坐标。其配合gen_contour_polygon_xld算子可以查看直线的显示结果。
(2)拟合圆形使用fit_circle_contour_xld算子,其也有许多拟合方法可选,将返回圆的中心坐标和半径。可以使用gen_circle_contour_xld算子查看拟和结果。
(3)拟合矩形选择fitrectangle2_contour_xld算子,该算子返回的主要是矩形的中心坐标和边长,以及矩形的旋转角度。其配合gen_rectangle2_contour_xld算子可以显示拟合结果。
(4)拟合椭圆形可以用fit_ellipse_contour_xld算子,将返回椭圆的中心坐标、长轴和短轴的半径,以及椭圆的角度和方向特征。其搭配使用gen_ellipse_contour_xld算子,可以显示轮廓曲线。
举例说明,如图所示。图(a)为输入的图像,图(b)为经阈值处理后得到的区域图像。图(c)为生成的亚像素轮廓图。图(d)为使用fit_circle_contour_xld算子和gen_circle_contour xld算子进行轮廓拟合后得到的圆形轮廓图。
实现代码如下:
dev_close_window ()
*读取了图像并创建显示窗口
read_image (Image, 'data/flower')
rgb1_to_gray (Image, GrayImage)
get_image_size (Image, Width, Height)
dev_open_window (0, 0, Width , Height, 'black', WindowHandle)
dev_set_color ('white')
*对图像进行阈值处理
threshold (GrayImage, Region, 130, 255)
*使用闭运算进行填充
closing_circle (Region, Region, 20.5)
*获取前景目标的初始轮廓
gen_contour_region_xld (Region, Contour, 'border')
*拟合圆形轮廓
fit_circle_contour_xld (Contour, 'atukey', -1, 2, 0, 10, 1, Row, Column, Radius, StartPhi, EndPhi, PointOrder)
*生成该拟合的圆形轮廓
gen_circle_contour_xld (ContCircle, Row, Column, Radius, 0, 4 * acos(0), 'positive', 1)
本例中先对图像进行阈值处理,提取出较亮的前景部分。由于提取出的较亮部分存在许多断开的部分和小的缝隙,因此使用闭运算进行填充,图(b)为闭运算后的结果;然后使用gen_contour_region_xld 算子获取前景目标的初始轮廓,即图(b)中白色部分的轮廓,结果显示在图(c)中;最后,使用fit_circle_contour_xld算子拟合圆形轮廓,得出圆形的特征参数,并用gen_circle_contour_xld算子生成该圆形轮廓。这样就实现了轮廓的拟合。