Halcon 《机器视觉算法及应用》十例(其三)

***该实例由于锯片很薄,采用漫反射背光照明

* 该程序演示了如何通过测量图像中的角度来检查锯片的齿。

* 初始化一些常量

PI := rad(180)
PI_2 := rad(90)

* 显示初始化
dev_update_off ()
read_image (Image, 'saw_blade/saw_01')
get_image_size (Image, Width, Height)
dev_close_window ()
dev_open_window_fit_image (Image, 0, 0, 640, 640, WindowHandleMain)
set_display_font (WindowHandleMain, 16, 'mono', 'true', 'false')
get_window_extents (WindowHandleMain, WindowRow, WindowColumn, WindowWidth, WindowHeight)
dev_open_window (400, WindowWidth / 2, 300, 300, 'black', WindowHandleZoom)
dev_set_line_width (2)

* 主循环:处理不同的图像
for Index1 := 1 to 7 by 1 //循环所以图像
    read_image (Image, 'saw_blade/saw_' + Index1$'02')
    * 
    *通过亚像素精确的阈值获得锯的轮廓。
    threshold_sub_pix (Image, Border, 128) //以亚像素精度从图像中提取crossing,而是将灰度值小于Threshold的区域与灰度值大于Threshold的区域分割线返回Border
    * 
    * 分割,选择和分类线性轮廓零件
    segment_contours_xld (Border, ContoursSplit, 'lines_circles', 5, 6, 4) //将XLD轮廓分割为线段、圆弧或椭圆弧
    select_shape_xld (ContoursSplit, SelectedContours, 'contlength', 'and', 30, 200) //使用形状特征选择轮廓或多边形
    count_obj (SelectedContours, Number) //计算区域的数量
    gen_empty_obj (ToothSides) //生成空数组对象
    for Index2 := 1 to Number by 1
        select_obj (SelectedContours, SelectedContour, Index2) //循环所有对象
        *获得全局轮廓属性
        get_contour_global_attrib_xld (SelectedContour, 'cont_approx', Attrib) //获得全局轮廓属性,

如果Attrib =0,这一部分轮廓最适合被拟合为椭圆弧。

如果Attrib =1,这一部分轮廓最适合被拟合为圆弧。

如果Attrib =-1,这一部分轮廓最适合被拟合为-直线。

        * *属性“ cont_approx”已由操作员设置 
        * segment_contours, 对于直线,该值为-1。

        if (Attrib == -1)
            concat_obj (ToothSides, SelectedContour, ToothSides) //两个区域组合到一起,生成新区域ToothSides
        endif
    endfor
    sort_contours_xld (ToothSides, ToothSidesSorted, 'upper_left', 'true', 'column') //根据轮廓的相对位置对轮廓进行排序
    * 
    * 计算锯齿每侧的方向
    fit_line_contour_xld (ToothSidesSorted, 'tukey', -1, 0, 5, 2, Rows1, Columns1, Rows2, Columns2, Nr, Nc, Dist) //对一些线段的XLD做近似计算直线计算


fit_line_contour_xld( Contours : : Algorithm, MaxNumPoints, ClippingEndPoints, Iterations, ClippingFactor : RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist )

Contours(in):输入轮廓

Algorithm(in):形成线的算法

MaxNumPoints(in):用于计算的最大轮廓点个数

ClippingEndPoints(in):在逼近过程中被忽略的开始及末尾点个数

Iterations(in):迭代的最大次数

ClippingFactor(in):消除异常值的裁剪因子

RowBegin(out):线段开始点的行坐标

ColBegin(out):线段开始的列坐标

RowEnd(out):线段结尾的行坐标

ColEnd(out):线段结尾的列坐标

Nr(out):线参数:法向量的行坐标

Nc(out):法向量的列坐标

Dist(out):原点到该线的距离


    line_orientation (Rows1, Columns1, Rows2, Columns2, Orientations)  //返回直线的角度:-90到90之间
    * 测量属于同一锯齿角度
    Angles := []
    * 检查第一颗锯齿是否完全可见。

    *如果没有,请从第二颗锯齿开始测量。
    if (Rows1[0] > Rows2[0]) //如果起始坐标Rows1>结束坐标 Rows2,说明是锯齿的右侧,则第一颗锯齿没有左侧,第一颗锯齿可以跳过不计算了
        Start := 1
    else
        Start := 2
    endif
    for Index2 := Start to |Orientations| - 1 by 2
        Angle := abs(Orientations[Index2 - 1] - Orientations[Index2])
        * 确保角度在[0,PI / 2]度的范围内。
        if (Angle > PI_2)
            Angle := PI - Angle
        endif
        * 
        * 显示结果
        dev_display_tooth (Image, ToothSides, Index2, Rows1, Columns1, Rows2, Columns2, WindowHandleMain, WindowHandleZoom)
        dev_set_window (WindowHandleMain)
        dev_disp_text ('Tooth ' + (Index2 + 1) / 2, 'window', 10, 10, 'black', [], [])
        dev_disp_text ('Included Angle: ' + deg(Angle)$'.2f' + ' deg', 'window', 35, 10, 'black', [], [])
        dev_disp_text ('Press Run (F5) to continue', 'window', 'bottom', 'right', 'black', [], [])
        Angles := [Angles,Angle]
        stop ()
    endfor
endfor

dev_set_window (WindowHandleMain)
dev_disp_text ('      End of program      ', 'window', 'bottom', 'right', 'black', [], [])
dev_set_window (WindowHandleZoom)
dev_close_window ()

值得借鉴:

1.将锯齿从背景中分割,使用亚像素精度算法。通常有两种亚像素精度算法:亚像素轮廓精度提取算法(边缘提取)、亚像素阈值分割算法(阈值分割),亚像素阈值分割算法适合此例子(背光照射使得背景为白色、锯齿为黑色),阈值采用均值128。

2.将每个锯齿分割,使用segment_contours_xld将轮廓分割为线段、直线以及椭圆,并出去过长、过短的线段。

3.进一步除去锯齿间的圆弧 get_contour_global_attrib_xld

4.从左至右 对轮廓排序,并使用fit_line_contour_xld 对直线拟合

5.计算拟合直线的方向,line_orientation得到的直线方向范围是[-90,90]

6.通过相邻两侧拟合直线(同一锯齿)相减, 计算每个锯齿的角度

计算锯齿没测的方向,直接的方法是图(b)用过轮廓起点、终点的直线角度,但锯齿顶部不一定是理想的尖端,因此用轮廓线上的所有点(拟合直线)更好。

图(c)可以看出,亚像素精度下,拟合直线的角度与真实直线的角度(a)几乎相等。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值