Halcon测量专栏-圆弧测量

1.前言

1.1什么是圆弧

圆上任意两点间的部分叫做圆弧。由于圆弧有正反的特性,即为有顺时针方向和逆时针方向,在确定圆弧时,也需要确定圆弧的方向。

1.2halcon实现方式

针对圆弧的问题。1:它与圆是相似的,都具备中心坐标和半径,还有起始和终点角度;2:定义一个圆弧方向,以顺时针为测量方向。

2.halcon程序

2.1halcon程序


read_image (Image, 'D:/1NewWork/work/2.26/.png')

get_image_size (Image, Width, Height)
*获得圆上初始采样点
row:=[296,949,2046]
column:=[2555,3063,1192]
********************************拟合弧形采样ROI*****************
gen_contour_polygon_xld (Contour, row, column)
fit_circle_contour_xld (Contour, 'algebraic', -1, 0, 0, 3, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder)
gen_circle_contour_xld (ContCircle, Row, Column, Radius, EndPhi,StartPhi,  'positive', 1)
*gen_circle_contour_xld (ContCircle, Row, Column, Radius, 1,EndPhi,  'positive', 1)
dev_display (Image)
dev_display (ContCircle)
row1:=[]
column1:=[]
gen_empty_obj (EmptyObject)
gen_empty_obj (EmptyObject2)

phi:=3.14*2-StartPhi

tuple_abs (StartPhi-EndPhi+3.14*2, Abs)
tuple_ceil (Abs/3.1415926*90, Ceil)
**********************************弧形采样*********************
for Index := 0to Ceil-1 by 1
    tuple_sin(phi+rad(Index*2),Sin)
    tuple_cos(phi+rad(Index*2),Cos)
    *创建测量矩形
    gen_measure_rectangle2 (Row+Radius*Sin, Column+Radius*Cos, -Index*3.1415926/180*2-phi, 50, 5, Width, Height, 'nearest_neighbor', MeasureHandle)
    *绘制测量矩形轮廓用于显示
    gen_rectangle2_contour_xld (Rectangle,Row+Radius*Sin, Column+Radius*Cos, -Index*3.1415926/180*2-phi, 50, 5)
    *开启测量
    measure_pos (Image, MeasureHandle, 2, 20, 'all', 'last', RowEdge, ColumnEdge, Amplitude, Distance)
    *绘制测量结果
    gen_cross_contour_xld (Cross, RowEdge, ColumnEdge, 20, 1)
    concat_obj (Cross, EmptyObject, EmptyObject)
    concat_obj (EmptyObject2, Rectangle, EmptyObject2)

    row1:=[row1,RowEdge]
    column1:=[column1,ColumnEdge]
endfor

gen_contour_polygon_xld (Contour1, row1, column1)
*********************输出结果横纵坐标与半径,起始与结束的角度*****************
fit_circle_contour_xld (Contour1, 'algebraic', -1, 0, 0, 3, 2, Row2, Column2, Radius2, StartPhi2, EndPhi2, PointOrder2)
gen_circle_contour_xld (ContCircle2, Row2, Column2, Radius2,EndPhi2, StartPhi2,  'positive', 1)
dev_display (Image)
dev_display (ContCircle)
dev_display (EmptyObject2)
dev_display (EmptyObject)
dev_display (ContCircle2)

2.2halcon程序讲解

2.2.1读取图像和绘制ROI

read_image (Image, 'D:/1NewWork/work/2.26/.png')
get_image_size (Image, Width, Height)
*获得圆上初始采样点
row:=[296,949,2046]
column:=[2555,3063,1192]
********************************拟合弧形采样ROI*****************
gen_contour_polygon_xld (Contour, row, column)
fit_circle_contour_xld (Contour, 'algebraic', -1, 0, 0, 3, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder)

找圆弧与找圆是类似的,都需要一个基准的ROI区域,但是圆弧在于,它需要起始点和终点,中间点为圆心位置。根据3点绘制圆的方式,所以ROI选取,3个采样点即可

2.2.2拟合采样点,并绘制弧线ROI

gen_contour_polygon_xld (Contour, row, column)
fit_circle_contour_xld (Contour, 'algebraic', -1, 0, 0, 3, 2, Row, Column, Radius, StartPhi, EndPhi, PointOrder)
gen_circle_contour_xld (ContCircle, Row, Column, Radius, EndPhi,StartPhi,  'positive', 1)
*gen_circle_contour_xld (ContCircle, Row, Column, Radius, 1,EndPhi,  'positive', 1)
dev_display (Image)
dev_display (ContCircle)

通过选取的3点ROI拟合一个圆,获取到圆心坐标,半径,圆弧的起始和终点

2.2.3圆弧检测

row1:=[]
column1:=[]
gen_empty_obj (EmptyObject)
gen_empty_obj (EmptyObject2)

phi:=3.14*2-StartPhi

tuple_abs (StartPhi-EndPhi+3.14*2, Abs)
tuple_ceil (Abs/3.1415926*90, Ceil)
**********************************弧形采样*********************
for Index := 0to Ceil-1 by 1
    tuple_sin(phi+rad(Index*2),Sin)
    tuple_cos(phi+rad(Index*2),Cos)
    *创建测量矩形
    gen_measure_rectangle2 (Row+Radius*Sin, Column+Radius*Cos, -Index*3.1415926/180*2-phi, 50, 5, Width, Height, 'nearest_neighbor', MeasureHandle)
    *绘制测量矩形轮廓用于显示
    gen_rectangle2_contour_xld (Rectangle,Row+Radius*Sin, Column+Radius*Cos, -Index*3.1415926/180*2-phi, 50, 5)
    *开启测量
    measure_pos (Image, MeasureHandle, 2, 20, 'all', 'last', RowEdge, ColumnEdge, Amplitude, Distance)
    *绘制测量结果
    gen_cross_contour_xld (Cross, RowEdge, ColumnEdge, 20, 1)
    concat_obj (Cross, EmptyObject, EmptyObject)
    concat_obj (EmptyObject2, Rectangle, EmptyObject2)

    row1:=[row1,RowEdge]
    column1:=[column1,ColumnEdge]
endfor

gen_contour_polygon_xld (Contour1, row1, column1)
*********************输出结果横纵坐标与半径,起始与结束的角度*****************
fit_circle_contour_xld (Contour1, 'algebraic', -1, 0, 0, 3, 2, Row2, Column2, Radius2, StartPhi2, EndPhi2, PointOrder2)
gen_circle_contour_xld (ContCircle2, Row2, Column2, Radius2,EndPhi2, StartPhi2,  'positive', 1)
dev_display (Image)
dev_display (ContCircle)
dev_display (EmptyObject2)
dev_display (EmptyObject)
dev_display (ContCircle2)

根据定义的圆弧,以初始点为起始点,顺时针旋转,旋转指定角度,并使用测量矩形对每个采样区域进行采样,将所有采样点重新拟合为圆即可得到最终结果
在这里插入图片描述

2.2.4注意事项

尤为要注意圆弧是有方向的,文中预先定义圆弧方向为顺时针方向

3.C#程序工具实现

#region // 圆弧测量
/// <summary>
/// 圆弧测量
/// </summary>
/// <param name="image">输入图像</param>
/// <param name="Row1">点1横坐标</param>
/// <param name="Column1">点1列坐标</param>
/// <param name="Row2">点2横坐标</param>
/// <param name="Column2">点2列坐标</param>
/// <param name="Row3">点3横坐标</param>
/// <param name="Column3">点3列坐标</param>
/// <param name="Sigma">高斯滤波值</param>
/// <param name="Threshold">最小二值化</param>
/// <param name="Measure_Set">选择拟合边1(“all”:最接近ROI轮廓的拟合边;“positive”:由亮到暗,“negative”:由暗到亮)</param>
/// <param name="Measure_Place">选择拟合边2(“first”:所有轮廓的第一条边,“last”:所有轮廓的最后一个边,“all”:最接近ROI轮廓的拟合边)</param>
/// <param name="ConCircle">输出弧形轮廓</param>
/// <param name="CenterRow">输出圆弧中心横坐标</param>
/// <param name="CenterColumn">输出圆弧中心列坐标</param>
/// <param name="ResultR">输出圆弧半径</param>
/// <param name="StartPhi">输出圆弧起始角度</param>
/// <param name="EndPhi">输出圆弧最终角度</param>
/// <returns></returns>
public static bool ArcMeasure(HObject image,HTuple Row1,HTuple Column1,HTuple Row2,HTuple Column2,
            HTuple Row3,HTuple Column3, HTuple Sigma, HTuple Threshold,HTuple Measure_Set,HTuple Measure_Place,
            out HObject ConCircle,out HTuple CenterRow,out HTuple CenterColumn,out HTuple ResultR,
            out HTuple StartPhi,out HTuple EndPhi)
{
    HOperatorSet.GenEmptyObj(out ConCircle);
    CenterRow = -1;
    CenterColumn = -1;
    ResultR = -1;
    StartPhi = -1;
    EndPhi = -1;

    try
    {
        HOperatorSet.GetImageSize(image, out HTuple width, out HTuple height);
        HTuple Row = new HTuple(),Column=new HTuple();
        Row[0] = Row1; Row[1] = Row2; Row[2] = Row3;
        Column[0]= Column1; Column[1]= Column2; Column[2] = Column3;
        HOperatorSet.GenContourPolygonXld(out HObject  Contour, Row, Column);
        HOperatorSet.FitCircleContourXld(Contour, "algebraic", -1, 0, 0, 3, 2, out HTuple row,
                out HTuple column, out HTuple radius, out HTuple startPhi, out HTuple endPhi, out HTuple pointOrder);
        HTuple row1=new HTuple(),column1=new HTuple(),phi=0;
        HOperatorSet.GenEmptyObj(out HObject emptyObject);
        HOperatorSet.GenEmptyObj(out HObject emptyObject2);
        phi = Math.PI*2 - startPhi;
        HOperatorSet.TupleAbs(startPhi - endPhi+Math.PI*2, out HTuple abs);
        HOperatorSet.TupleCeil(abs / Math.PI * 90, out HTuple ceil);

        

        for (int i = 0; i < ceil-1; i++)
        {
            HOperatorSet.TupleSin(phi + i * 2 * Math.PI / 180 , out HTuple sin);
            HOperatorSet.TupleCos(phi + i * 2 * Math.PI / 180 , out HTuple cos);

            HOperatorSet.GenMeasureRectangle2(row + radius * sin, column + radius * cos, ((((-i) * 3.1415926) / 180) * 2) - phi ,
                50, 5, width, height, new HTuple("nearest_neighbor"), out HTuple measureHandle);
            HOperatorSet.MeasurePos(image, measureHandle, Sigma, Threshold, Measure_Set, Measure_Place, out HTuple rowEdge,
                out HTuple columnEdge, out HTuple amplitude, out HTuple distance);
            row1 = row1.TupleConcat(rowEdge);
            column1 = column1.TupleConcat(columnEdge);
        }
        HOperatorSet.GenContourPolygonXld(out HObject contour, row1, column1);
        HOperatorSet.FitCircleContourXld(contour, new HTuple("algebraic"), -1, 0, 0, 3, 2, out CenterRow, out CenterColumn,
            out ResultR, out StartPhi, out EndPhi , out HTuple pointOrder2);
        HOperatorSet.TupleLength(CenterRow, out HTuple length);
        if (length == 0)
        {
            return false;
        }
        HOperatorSet.GenCircleContourXld(out ConCircle, CenterRow, CenterColumn, ResultR, EndPhi, StartPhi, new HTuple("positive"), 1);
        return true;
    }
    catch (Exception)
    {
        return false;
    }
}
#endregion
#region // 单点查找
/// <summary>
/// 单个点查找
/// </summary>
/// <param name="Image">输入图像</param>
/// <param name="Row1">输入直线起始横坐标</param>
/// <param name="Column1">输入直线起始列坐标</param>
/// <param name="Row2">输入直线终点横坐标</param>
/// <param name="Column2">输入直线终点列坐标</param>
/// <param name="MeasureWide">输入测量矩形宽度</param>
/// <param name="Sigma">输入测量矩形的高斯滤波值</param>
/// <param name="Thrashold">输入最小边缘对比度</param>
/// <param name="ResultRow">输出结果横坐标</param>
/// <param name="ResultColumn">输出结果列坐标</param>
/// <returns>拟合成功返回true,拟合失败返回false</returns>
static public bool PointMeasure_(HObject Image, HTuple Row1, HTuple Column1,HTuple Row2,HTuple Column2,
            HTuple MeasureWide, HTuple Sigma, HTuple Thrashold, 
            out HTuple ResultRow, out HTuple ResultColumn)
{
    ResultRow = -1; ResultColumn = -1;
    try
    {
        HTuple hv_TmpCtrl_Row, hv_TmpCtrl_Column, hv_TmpCtrl_Dr, hv_TmpCtrl_Dc, hv_TmpCtrl_Phi,
                hv_TmpCtrl_Len1;
        HOperatorSet.GetImageSize(Image, out HTuple width, out HTuple height);
            hv_TmpCtrl_Row = 0.5 * (Row1 + Row2);
            hv_TmpCtrl_Column = 0.5 * (Column1 + Column2);
            hv_TmpCtrl_Dr = Row1 - Row2;
            hv_TmpCtrl_Dc = Column2 - Column1;
            hv_TmpCtrl_Phi = hv_TmpCtrl_Dr.TupleAtan2( hv_TmpCtrl_Dc);
            hv_TmpCtrl_Len1 = 0.5 * ((((hv_TmpCtrl_Dr * hv_TmpCtrl_Dr) + (hv_TmpCtrl_Dc * hv_TmpCtrl_Dc))).TupleSqrt());
        HOperatorSet.GenMeasureRectangle2(hv_TmpCtrl_Row, hv_TmpCtrl_Column, hv_TmpCtrl_Phi,
            hv_TmpCtrl_Len1, MeasureWide, width, height, "nearest_neighbor", out HTuple measureHandle);
        HOperatorSet.MeasurePos(Image, measureHandle, Sigma, Thrashold, new HTuple("all"), new HTuple("first"), out ResultRow,
            out ResultColumn, out HTuple amplitude, out HTuple distance);
        HOperatorSet.TupleLength(ResultRow, out HTuple length);
        if (length==0)
        {
            return false;
        }
        return true;
    }
    catch (Exception)
    {
        return false;
    }
}
#endregion

总结

弧形检测,与圆检测依旧类型,都是通过一定量的采样点去拟合出几何图形。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值