金属零件的多个参数测量

对应示例程序:
measure_metal_part_extended.hdev

目标:金属零件的多个方面检测,包括金属块的中心点,方向,平行线,最小外接矩形等。主要是一些常用的测量算子的简单应用。

思路为:
      读取图像,设置窗口,字体等
      NO.1 阈值分割后,利用算子area_center 计算金属块区域的面积和中心点坐标
      NO.2 先亚像素边缘检测,再用算子area_center_xld计算金属轮廓的中心点坐标
      NO.3 利用算子segment_contours_xld将轮廓分为直线和圆弧,并对其进行拟合和显示
      NO.4 Fórstner算法检测角点
      NO.5 利用算子angle_ll计算两条直线的夹角
      NO.6 用算子gen_polygons_xld 多边形拟合轮廓,再用算子gen_parallels_xld检测轮廓中的平行线,最后将平行线间的端点作为线之间的距离
      NO.7 计算最小外接矩形smallest_rectangle2

图像:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码:

dev_update_off ()
* 
* step: acquire image
* 读取图像   设置窗口
read_image (Image, 'metal-parts/metal-parts-01')
init_visualization (Image, 3, 'white', 'margin', Width, Height, WindowID)
set_display_font (WindowID, 16, 'mono', 'true', 'false')
disp_continue_message (WindowID, 'black', 'true')
stop ()
* //第一个显示:显示测量得到的区域面积 中心点坐标
* step: get center, area, and orientation via region processing
* 通过区域处理获得中心、区域和方向
dev_set_draw ('fill')
count_seconds (T1)  //记录时间
threshold (Image, Region, 100, 255)   //阈值分割
area_center (Region, AreaRegion, RowCenterRegion, ColumnCenterRegion)  //计算金属块区域的面积和中心点坐标

orientation_region (Region, OrientationRegion)  //区域的方向
count_seconds (T2) 

dev_display (Region)
set_tposition (WindowID, 10, 10)
write_string (WindowID, 'Region Processing')
set_tposition (WindowID, 10, 300)
write_string (WindowID, 'Time: ' + ((T2 - T1) * 1000)$'.2' + ' ms')
set_tposition (WindowID, 50, 10)
write_string (WindowID, 'Center Row: ' + RowCenterRegion$'.5')
set_tposition (WindowID, 50, 300)
write_string (WindowID, 'Center Column: ' + ColumnCenterRegion$'.5')
set_tposition (WindowID, 80, 10)
write_string (WindowID, 'Area: ' + AreaRegion + ' pixels')
set_tposition (WindowID, 80, 300)
write_string (WindowID, 'Orientation: ' + OrientationRegion$'.3' + ' rad')
dev_set_color ('gray')
disp_cross (WindowID, RowCenterRegion, ColumnCenterRegion, 10, 0)
smallest_rectangle2 (Region, Row_Region, Column_Region, Phi_Region, Length1_Region, Length2_Region)
gen_rectangle2 (Rectangle, Row_Region, Column_Region, Phi_Region, Length1_Region, Length2_Region)
disp_continue_message (WindowID, 'black', 'true')
stop ()
* 
* step: create contours
* 第二个显示:显示图像的边缘中心点 方向

//采用先形态学 再亚像素边缘  而不是直接亚像素边缘  应该是为了节省时间
count_seconds (T3)
threshold (Image, Region, 100, 255)   //阈值分割

boundary (Region, RegionBorder, 'inner')   //形态学处理  获取边缘  这里是一个边缘区域

dilation_circle (RegionBorder, RegionDilation, 1.5)   //膨胀

reduce_domain (Image, RegionDilation, ImageReduced)   //裁剪
edges_sub_pix (ImageReduced, Edges, 'lanser2', 0.5, 40, 90)  //亚像素边缘  这里是多个边缘区域
* 
* step: get center, area, and orientation via contour processing
* 通过轮廓处理获得中心、区域和方向
area_center_xld (Edges, AreaContours, RowCenterContours, ColumnCenterContours, PointOrderContours) //xld的中心
AreaOfRegionByContours := AreaContours[0] - AreaContours[1] - AreaContours[2] - AreaContours[3]
orientation_xld (Edges, OrientationContours)  //xld的方向
count_seconds (T4)
dev_set_color ('light gray')
dev_display (Edges)
set_tposition (WindowID, 330, 10)
write_string (WindowID, 'Contour Processing')
set_tposition (WindowID, 330, 300)
write_string (WindowID, 'Time: ' + ((T4 - T3) * 1000)$'.3' + ' ms')
set_tposition (WindowID, 370, 10)
write_string (WindowID, 'Center Row: ' + RowCenterContours[0]$'.4')
set_tposition (WindowID, 370, 300)
write_string (WindowID, 'Center Column: ' + ColumnCenterContours[0]$'.4')
set_tposition (WindowID, 400, 10)
write_string (WindowID, 'Area: ' + AreaOfRegionByContours[0] + ' pixels')
set_tposition (WindowID, 400, 300)
write_string (WindowID, 'Orientation: ' + OrientationContours[0]$'.3' + ' rad')
disp_cross (WindowID, RowCenterContours, ColumnCenterContours, 6, 0)
disp_cross (WindowID, RowCenterContours[0], ColumnCenterContours[0], 10, 0)
smallest_rectangle2_xld (Edges, Row_Contours, Column_Contours, Phi_Contours, Length1_Contours, Length2_Contours)
disp_continue_message (WindowID, 'black', 'true')
stop ()
* 
* step: segment and sort contours
* 第三个显示:将获得的边缘 分为直线和圆弧   拟合直线和圆弧  并给出直线段的距离 和圆的半径
segment_contours_xld (Edges, ContoursSplit, 'lines_circles', 6, 4, 4) //根据直线和圆弧 分离边缘

sort_contours_xld (ContoursSplit, SortedContours, 'upper_left', 'true', 'column')  //边缘排序
dev_clear_window ()
dev_set_colored (12)
dev_display (SortedContours)
stop ()
* 
* step: open zoom window
* 
open_zoom_window (0, round(Width / 2), 115, 225, 395, 535, 2, WindowHandleZoom)  //缩放窗口
set_display_font (WindowHandleZoom, 14, 'mono', 'true', 'false')
* 
* step: fit circles and lines into contours
* 
count_obj (SortedContours, NumSegments)
dev_display (Image)
NumCircles := 0
NumLines := 0
gen_empty_obj (Lines)
RowsBegin := []
ColsBegin := []
RowsEnd := []
ColsEnd := []
dev_set_color ('white')
set_tposition (WindowHandleZoom, 120, 230)
write_string (WindowHandleZoom, 'Line lengths and circle radii: ')
for i := 1 to NumSegments by 1
    select_obj (SortedContours, 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_ellipse_contour_xld (ContEllipse, Row, Column, 0, Radius, Radius, 0, rad(360), 'positive', 1.0)
        dev_set_color ('white')
        dev_display (ContEllipse)
        //计算轮廓到拟合出的圆的距离   用来评估偏离值
        dist_ellipse_contour_xld (SingleSegment, 'algebraic', -1, 0, Row, Column, 0, Radius, Radius, MinDist, MaxDist, AvgDist, SigmaDist) //计算轮廓到椭圆的距离
        //显示位置和格式设置
        set_tposition (WindowHandleZoom, Row - Radius - 10, Column)
        write_string (WindowHandleZoom, 'C' + NumCircles)
        ResultText := 'C' + NumCircles + ': Radius = ' + Radius$'.3' + ' / MaxDeviation: ' + MaxDist$'.3'
    else    //直线
        NumLines := NumLines + 1
        fit_line_contour_xld (SingleSegment, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist) //拟合直线
        gen_contour_polygon_xld (Line, [RowBegin,RowEnd], [ColBegin,ColEnd])
        dev_set_color ('yellow')
        dev_display (Line)
        distance_pp (RowBegin, ColBegin, RowEnd, ColEnd, Length)   //直线段起始点和终点的距离
        set_tposition (WindowHandleZoom, (RowBegin + RowEnd) / 2 - Nr * 10, (ColBegin + ColEnd) / 2)
        write_string (WindowHandleZoom, 'L' + NumLines)
        ResultText := 'L' + NumLines + ': Length = ' + Length$'.4'
        concat_obj (Lines, Line, Lines)
        RowsBegin := [RowsBegin,RowBegin]
        ColsBegin := [ColsBegin,ColBegin]
        RowsEnd := [RowsEnd,RowEnd]
        ColsEnd := [ColsEnd,ColEnd]
    endif
    set_tposition (WindowHandleZoom, 275 + i * 10, 230)
    write_string (WindowHandleZoom, ResultText)
endfor
disp_continue_message (WindowHandleZoom, 'black', 'true')
stop ()
* 第四个显示:显示角点
* step: get corner points, two approaches (Foerstner, Intersection_ll)
* and the angle between the lines building the corners
* *步骤:获取角点、两条引道(Foerstner、Intersection_ll)和构成拐角的直线之间的角度
dev_display (Image)
dev_set_color ('white')
//使用Fórstner算法检测感兴趣的点,也就是角点
points_foerstner (Image, 1, 2, 3, 200, 0.3, 'gauss', 'false', RowJunctions, ColJunctions, CoRRJunctions, CoRCJunctions, CoCCJunctions, RowArea, ColArea, CoRRArea, CoRCArea, CoCCArea)

//用十字表示角点
gen_cross_contour_xld (CrossFoerstner, RowJunctions, ColJunctions, 10, 0)

dev_display (CrossFoerstner)
set_tposition (WindowHandleZoom, RowJunctions[0] - 10, ColJunctions[0] + 10)
write_string (WindowHandleZoom, 'P2')
set_tposition (WindowHandleZoom, RowJunctions[1] - 10, ColJunctions[1] + 10)
write_string (WindowHandleZoom, 'P1')
set_tposition (WindowHandleZoom, 120, 230)
write_string (WindowHandleZoom, 'Foerstner Points')
disp_continue_message (WindowHandleZoom, 'black', 'true')
stop ()
* 
* intersection points and angles calculated
* by the lines obtained by line-fitting
* 
*由直线拟合得到的直线计算的交点和角度
dev_set_color ('yellow')
write_string (WindowHandleZoom, ' vs. intersection_l_l: ')
//由P1附近的两条直线的交点 确定的P1的坐标
intersection_lines (RowsBegin[0], ColsBegin[0], RowsEnd[0], ColsEnd[0], RowsBegin[1], ColsBegin[1], RowsEnd[1], ColsEnd[1], RowIntersect1, ColumnIntersect1, IsOverlapping1)
gen_cross_contour_xld (CrossIntersection1, RowIntersect1, ColumnIntersect1, 10, 0.785398)
dev_display (CrossIntersection1)
dev_set_color ('white')
distance_pp (RowJunctions[1], ColJunctions[1], RowIntersect1, ColumnIntersect1, Distance1)  //P1和交点之间的距离
//显示由Fórstner算法检测出的角点  和直线交点确定的角点  之间的距离
set_tposition (WindowHandleZoom, 325, 230)
write_string (WindowHandleZoom, 'Distance between Foerstner points and')
set_tposition (WindowHandleZoom, 335, 230)
write_string (WindowHandleZoom, 'points obtained by intersection_ll:')
set_tposition (WindowHandleZoom, 355, 230)
write_string (WindowHandleZoom, 'in P1: ' + Distance1$'.3' + ' pixels')
dev_set_color ('yellow')
//同理 计算P2 和直线交点  的距离
intersection_lines (RowsBegin[0], ColsBegin[0], RowsEnd[0], ColsEnd[0], RowsBegin[2], ColsBegin[2], RowsEnd[2], ColsEnd[2], RowIntersect2, ColumnIntersect2, IsOverlapping2)
distance_pp (RowJunctions[0], ColJunctions[0], RowIntersect2, ColumnIntersect2, Distance2)
gen_cross_contour_xld (CrossIntersection2, RowIntersect2, ColumnIntersect2, 10, 0.785398)
dev_display (CrossIntersection2)
dev_set_color ('white')
set_tposition (WindowHandleZoom, 370, 230)
write_string (WindowHandleZoom, 'in P2: ' + Distance2$'.3' + ' pixels')
disp_continue_message (WindowHandleZoom, 'black', 'true')
stop ()


*第五个显示:显示两条直线间的夹角
dev_display (Image)
//P1 附近两条直线之间的夹角
angle_ll (RowsBegin[0], ColsBegin[0], RowsEnd[0], ColsEnd[0], RowsBegin[1], ColsBegin[1], RowsEnd[1], ColsEnd[1], Angle1) //计算两条直线之间的夹角
set_tposition (WindowHandleZoom, RowsBegin[0] - 10, ColsBegin[0] + 10)
write_string (WindowHandleZoom, 'P2')
set_tposition (WindowHandleZoom, RowsEnd[0] - 10, ColsEnd[0] + 10)
write_string (WindowHandleZoom, 'P1')
set_tposition (WindowHandleZoom, 120, 230)
write_string (WindowHandleZoom, 'Angle in P1: ' + deg(Angle1)$'.3' + ' degrees')
disp_arrow (WindowHandleZoom, RowsEnd[0], ColsEnd[0], RowsBegin[0], ColsBegin[0], 1)
disp_arrow (WindowHandleZoom, RowsBegin[1], ColsBegin[1], RowsEnd[1], ColsEnd[1], 1)
disp_continue_message (WindowHandleZoom, 'black', 'true')
stop ()
//P2 附近两条直线之间的夹角
dev_display (Image)
angle_ll (RowsBegin[0], ColsBegin[0], RowsEnd[0], ColsEnd[0], RowsBegin[2], ColsBegin[2], RowsEnd[2], ColsEnd[2], Angle2)
set_tposition (WindowHandleZoom, RowsBegin[0] - 10, ColsBegin[0] + 10)
write_string (WindowHandleZoom, 'P2')
set_tposition (WindowHandleZoom, RowsEnd[0] - 10, ColsEnd[0] + 10)
write_string (WindowHandleZoom, 'P1')
set_tposition (WindowHandleZoom, 120, 230)
write_string (WindowHandleZoom, 'Angle in P2: ' + deg(Angle2)$'.3' + ' degrees')
disp_arrow (WindowHandleZoom, RowsBegin[0], ColsBegin[0], RowsEnd[0], ColsEnd[0], 1)
disp_arrow (WindowHandleZoom, RowsEnd[2], ColsEnd[2], RowsBegin[2], ColsBegin[2], 1)
disp_continue_message (WindowHandleZoom, 'black', 'true')
stop ()
* 
* step: get parallels with maximum lengths and the distances between them
* 第六个显示:检测图像中的平行线以及他们之间的距离

gen_polygons_xld (ContoursSplit, Polygons, 'ramer', 2)  //通过多边形近似XLD轮廓  通过多边形近似拟合之前根据圆和直线分离开的轮廓
gen_parallels_xld (Polygons, Parallels, 80, 75, 0.15, 'true')  //提取平行XLD多边形  找图形中的平行轮廓
count_obj (Parallels, NumberParallels)
dev_display (Image)
for i := 1 to NumberParallels by 1
    dev_set_color ('white')
    select_obj (Parallels, SelectedParallel, i)
    dev_display (SelectedParallel)
    //返回平行XLD轮廓的数据
    get_parallels_xld (SelectedParallel, Row1Parallels, Col1Parallels, Length1Parallels, Phi1Parallels, Row2Parallels, Col2Parallels, Length2Parallels, Phi2Parallels)
    * 
    //计算两个点之间的距离  也就是平行线 对应的两个端点之间的距离
    distance_pp (Row1Parallels[0], Col1Parallels[0], Row2Parallels[1], Col2Parallels[1], Distance2)
    distance_pp (Row1Parallels[1], Col1Parallels[1], Row2Parallels[0], Col2Parallels[0], Distance1)
    * 
    set_tposition (WindowHandleZoom, 120, 230)
    write_string (WindowHandleZoom, 'Distance BC: ' + Distance1$'.4' + ' pixels')
    set_tposition (WindowHandleZoom, 140, 230)
    write_string (WindowHandleZoom, 'Distance AD: ' + Distance2$'.4' + ' pixels')
    set_tposition (WindowHandleZoom, 340, 230)
    write_string (WindowHandleZoom, 'Orientation AB: ' + deg(Phi1Parallels)$'.3' + ' degrees')
    set_tposition (WindowHandleZoom, 360, 230)
    write_string (WindowHandleZoom, 'Orientation DC: ' + deg(Phi2Parallels)$'.3' + ' degrees')
    set_tposition (WindowHandleZoom, Row1Parallels[0] + 10, Col1Parallels[0])
    write_string (WindowHandleZoom, 'A')
    set_tposition (WindowHandleZoom, Row1Parallels[1] + 10, Col1Parallels[1])
    write_string (WindowHandleZoom, 'B')
    set_tposition (WindowHandleZoom, Row2Parallels[0] + 10, Col2Parallels[0])
    write_string (WindowHandleZoom, 'C')
    set_tposition (WindowHandleZoom, Row2Parallels[1] + 10, Col2Parallels[1])
    write_string (WindowHandleZoom, 'D')
    * 
    dev_set_color ('yellow')
    disp_line (WindowHandleZoom, Row1Parallels[0], Col1Parallels[0], Row2Parallels[1], Col2Parallels[1])
    disp_line (WindowHandleZoom, Row1Parallels[1], Col1Parallels[1], Row2Parallels[0], Col2Parallels[0])
    disp_continue_message (WindowHandleZoom, 'black', 'true')
    stop ()
endfor
* 
* step: ualvisize width of object obtained by the smallest enclosing rectangle
* 第七个显示:显示最小外接矩形 长边与短边的比值
dev_set_color ('white')
dev_set_draw ('margin')
dev_display (Image)
dev_display (Rectangle)
set_tposition (WindowHandleZoom, 120, 230)
write_string (WindowHandleZoom, 'Lenght / Width of smallest enclosing rectangle:')
set_tposition (WindowHandleZoom, 140, 230)
write_string (WindowHandleZoom, (2 * Length1_Region)$'.4' + ' / ' + (2 * Length2_Region)$'.4' + ' pixels')
disp_continue_message (WindowHandleZoom, 'black', 'true')
stop ()
dev_set_window (WindowHandleZoom)
dev_close_window ()

用到的几个算子:
    area_center --计算区域的面积和中心点坐标
    orientation_region – 计算区域的方向
    area_center_xld–计算XLD的面积和中心点坐标
    orientation_xld --计算XLD的方向
    segment_contours_xld-- 将亚像素轮廓分割为直线段、圆、或圆弧(三种方式:直线,直线和圆,直线和弧,根据实际图像进行选择)
    get_contour_global_attrib_xld -返回XLD轮廓的全局属性值 判断轮廓是否适合被划分为圆 返回值:-1 适合直线 0适合圆弧 1 适合圆
    points_foerstner–使用Fórstner算法检测感兴趣的点,也就是角点
    intersection_linesr–计算两条直线的交点
    angle_ll --计算两条直线之间的夹角
    gen_polygons_xld --通过多边形近似XLD轮廓
    gen_parallels_xld --提取平行XLD多边形 找图形中的平行轮廓
    distance_pp–计算两个点的距离
    smallest_rectangle2–最小外接矩形

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值