Halcon测量专栏-平行度

1.前言

1.1什么是平行度

平行度指两平面或者两直线平行的程度,指一平面(边)相对于另一平面(边)平行的误差最大允许值。
平行度评价直线之间、平面之间或直线与平面之间的平行状态。其中一个直线或平面是评价基准,而直线可以是被测样品的直线部分或直线运动轨迹,平面可以是被测样品的平面部分或运动轨迹形成的平面。

1.2平行度评价方式

测量线对线平行度误差
公差要求是测量孔的轴线相对于基准孔的轴线的平行度误差。需要用心轴模拟被测要素和基准要素,将两根心轴装于基准孔和被测孔内,形成稳定接触,

1.3halcon实现方式

针对线线平行度的评价标准,所以预先定义直线1作为基准线,直线2作为被测线。对直线2上的2个端点对基准线计算距离,并求2个距离的差值,差值的数额即为平行度的误差

2.程序

2.1C#和halcon程序

#region // 计算平行度(直线1的2个端点,到直线2的距离,的差值)
public static bool parallel(HObject Image, bool FastSet,
                 HTuple ROIBeginRow1, HTuple ROIBeginCloumn1, HTuple ROIEndRow1,  HTuple ROIEndCloumn1,
                 HTuple ROIBeginRow2, HTuple ROIBeginCloumn2, HTuple ROIEndRow2,  HTuple ROIEndCloumn2,
                 out HObject lineContours1, out HTuple resultRowBegin1,
                 out HTuple resultColumnBegin1, out HTuple resultRowEnd1, out HTuple resultCloumnEnd1,
                 out HObject lineContours2, out HTuple resultRowBegin2,
                 out HTuple resultColumnBegin2, out HTuple resultRowEnd2, out HTuple resultCloumnEnd2,
                 out double Distance)
{
    Distance = -1;
    HOperatorSet.GenEmptyObj(out lineContours1);
    HOperatorSet.GenEmptyObj(out lineContours2);
    resultRowBegin1 = -1;
    resultColumnBegin1 = -1;
    resultRowEnd1 = -1;
    resultCloumnEnd1 = -1;
    resultColumnBegin2 = -1;
    resultRowBegin2 = -1;
    resultRowEnd2 = -1; 
    resultCloumnEnd2 = -1;
    try
    {
        bool line1 = false, line2 = false;
        if (FastSet)
        {
            line1 = Module.LineMeasure_(Image, ROIBeginRow1, ROIBeginCloumn1, ROIEndRow1,  ROIEndCloumn1,
                        30, 5, 2, 20, "uniform", "first", out  lineContours1, out  resultRowBegin1,
                         out  resultColumnBegin1, out  resultRowEnd1, out  resultCloumnEnd1);
            line2 = Module.LineMeasure_(Image, ROIBeginRow2, ROIBeginCloumn2, ROIEndRow2,  ROIEndCloumn2,
                        30, 5, 2, 20, "uniform", "first", out  lineContours2, out  resultRowBegin2,
                        out  resultColumnBegin2, out  resultRowEnd2,  out  resultCloumnEnd2);
            if (!line1 || !line2)
            {
                return false;
            }
            HOperatorSet.DistancePl(resultRowBegin1, resultColumnBegin1, resultRowBegin2, resultColumnBegin2,
                        resultRowEnd2, resultCloumnEnd2, out HTuple distance1);
            HOperatorSet.DistancePl(resultRowEnd1, resultCloumnEnd1, resultRowBegin2, resultColumnBegin2,
                        resultRowEnd2, resultCloumnEnd2, out HTuple distance2);
            double d1= distance1,d2= distance2;
            Distance = Math.Abs(d1 - d2);
        }
        return true;
    }
    catch (Exception)
    {
        return false;
    }
}
#endregion
#region // 直线查找
/// <summary>
/// 直线查找
/// </summary>
/// <param name="image">输入图像</param>
/// <param name="BeginRow">输入ROI的开始横坐标</param>
/// <param name="EndRow">输入ROI的结束横坐标</param>
/// <param name="BeginColumn">输入ROI开始列坐标</param>
/// <param name="EndColumn">输入ROI的结束列坐标</param>
/// <param name="MeasureHeight">输入测量矩形高度</param>
/// <param name="MeasureWide">输入测量矩形宽度</param>
/// <param name="Sigma">输入测量矩形的高斯滤波值</param>
/// <param name="Threshold">输入最小边缘对比度</param>
/// <param name="Measure_Set">选择拟合边1(“uniform”:最接近ROI轮廓的拟合边;“positive”:由亮到暗,“negative”:由暗到亮)</param>
/// <param name="Measure_Place">选择拟合边2(“first”:所有轮廓的第一条边,“last”:所有轮廓的最后一个边,“all”:最接近ROI轮廓的拟合边)</param>
/// <param name="LineContours">结果轮廓</param>
/// <param name="ResultRowBegin">结果轮廓开始横坐标</param>
/// <param name="ResultRowEnd">结果轮廓结束横坐标</param>
/// <param name="ResultColumnBegin">结果轮廓开始列坐标</param>
/// <param name="ResultCloumnEnd">结果轮廓结束列坐标</param>
/// <returns>拟合成功返回true,拟合失败返回false</returns>
static public bool LineMeasure_(HObject image, HTuple BeginRow, HTuple BeginColumn, HTuple EndRow, 
            HTuple EndColumn, HTuple MeasureHeight, HTuple MeasureWide, HTuple Sigma, HTuple Threshold,
            HTuple Measure_Set, HTuple Measure_Place, out HObject LineContours,
            out HTuple ResultRowBegin, out HTuple ResultColumnBegin, out HTuple ResultRowEnd, 
            out HTuple ResultCloumnEnd)
{
    HOperatorSet.GenEmptyObj(out LineContours);
    ResultRowBegin = null;
    ResultColumnBegin = null;
    ResultCloumnEnd = null;
    ResultRowEnd = null;
    try
    {

        HOperatorSet.CreateMetrologyModel(out HTuple metrologyHandle);
        HOperatorSet.AddMetrologyObjectLineMeasure(metrologyHandle, BeginRow, BeginColumn, EndRow, EndColumn,
                MeasureHeight, MeasureWide, Sigma, Threshold, new HTuple(), new HTuple(), out HTuple index);

        HOperatorSet.SetMetrologyObjectParam(metrologyHandle, new HTuple("all"), (new HTuple("measure_transition")
                                 ).TupleConcat("measure_select"), (new HTuple(Measure_Set)
                                 ).TupleConcat(Measure_Place));
        //HOperatorSet.SetMetrologyObjectParam(metrologyHandle, new HTuple("all"), new HTuple("min_score"), 0.1);
        HOperatorSet.ApplyMetrologyModel(image, metrologyHandle);
        HOperatorSet.GetMetrologyObjectResultContour(out LineContours, metrologyHandle, new HTuple("all"), new HTuple("all")
                , new HTuple(1.5));
        HOperatorSet.GetMetrologyObjectResult(metrologyHandle, index, new HTuple("all"), new HTuple("result_type"),
                       new HTuple("row_begin"), out ResultRowBegin);
        HOperatorSet.GetMetrologyObjectResult(metrologyHandle, index, new HTuple("all"), new HTuple("result_type"),
                    new HTuple("row_end"), out ResultRowEnd);
        HOperatorSet.GetMetrologyObjectResult(metrologyHandle, index, new HTuple("all"), new HTuple("result_type"),
                    new HTuple("column_begin"), out ResultColumnBegin);
        HOperatorSet.GetMetrologyObjectResult(metrologyHandle, index, new HTuple("all"), new HTuple("result_type"),
                    new HTuple("column_end"), out ResultCloumnEnd);
        HOperatorSet.TupleLength(ResultRowBegin, out HTuple length);
        if (length == 0)
        {
            return false;
        }
        return true;
    }
    catch (Exception ex)
    {
        return false;
    }


}
#endregion

2.2程序讲解

2.2.1读取图像和绘制ROI,并拟合直线

 line1 = Module.LineMeasure_(Image, ROIBeginRow1, ROIBeginCloumn1, ROIEndRow1,  ROIEndCloumn1,
             30, 5, 2, 20, "uniform", "first", out  lineContours1, out  resultRowBegin1,
              out  resultColumnBegin1, out  resultRowEnd1, out  resultCloumnEnd1);
 line2 = Module.LineMeasure_(Image, ROIBeginRow2, ROIBeginCloumn2, ROIEndRow2,  ROIEndCloumn2,
             30, 5, 2, 20, "uniform", "first", out  lineContours2, out  resultRowBegin2,
             out  resultColumnBegin2, out  resultRowEnd2,  out  resultCloumnEnd2);

2.2.计算平行度

HOperatorSet.DistancePl(resultRowBegin1, resultColumnBegin1, resultRowBegin2, resultColumnBegin2,
            resultRowEnd2, resultCloumnEnd2, out HTuple distance1);
HOperatorSet.DistancePl(resultRowEnd1, resultCloumnEnd1, resultRowBegin2, resultColumnBegin2,
            resultRowEnd2, resultCloumnEnd2, out HTuple distance2);
double d1= distance1,d2= distance2;
Distance = Math.Abs(d1 - d2);

总结

由于2D检测中并不适配面测量,所以文中仅设定线线平行度。当计算平行度误差过大是,可能出现直线的直线度过大造成的误差。

Hi~ 可私信我了解后再进行下载~ 本资源上传时,遗漏了两个文件,分别是:data_filter_keep_order_output_index.hdvp 以及 IntensityImageToPiontsCloudImage.hdvp,购买了该资源的同学,给我留言,我会私信发给你们。 1.基于halcon算法平台; 2.提供深图源文件以及解压密码; 3.代码预览: */****************************** * @文档名称: 基于点云的平面测量。 * @作者: hugo * @版本: 1.1 * @日期: 2021-6-20 * @描述: 该方法支持点云的平面的平面测量。 ********************************/ dev_update_window ('on') dev_get_window (WindowHandle) read_image (imageReal, './replay_38893_2021-6-7.tif') xResolution:=0.06 yResolution:=0.06 zResolution:=0.001 ScaleFactor:=[xResolution,yResolution,zResolution] *采样区域1 create_drawing_object_rectangle2 (300, 120, rad(90), 30, 20, DrawID) set_drawing_object_params (DrawID, 'color', 'forest green') set_drawing_object_params (DrawID, 'line_width', 1) attach_drawing_object_to_window (WindowHandle, DrawID) .......... *平面 height:=theta/zScale*0.001 *可视化高差效果 visParamName := ['lut','alpha_0','intensity','color_1'] visParamValue := ['hsi',0.7,'coord_z','yellow'] Labels := ['','平面:'+height+'mm',''] objs:=[ObjectModel3Ds[2],final_ObjectModel3Ds] visualize_object_model_3d (WindowHandle, objs, [], [], visParamName, visParamValue, 'Edited by AmazingRobot+', [Labels], '', PoseOut) *stop () clear_object_model_3d (plane_balls) for Index := 0 to |final_ObjectModel3Ds|-1 by 1 clear_object_model_3d (final_ObjectModel3Ds[Index]) endfor return () 谢谢您的信任~
### 使用 Halcon 实现基于深图像的平行测量 #### 方法概述 要实现基于深图像的平行测量,主要步骤包括读取深图像、提取感兴趣区域(ROI)内的边缘特征、计算这些边缘之间的角差异来评估平行。通过使用Halgon内置工具和算子可以高效完成此过程。 对于深图中的物体表面分析,通常先利用`binocular_disparity_to_gray`转换立体匹配得到视差图为灰形式便于后续处理[^1]。接着应用形态学操作如开运算(`gray_opening_shape`)去除噪声并平滑边界以便更精确地定位目标轮廓线[^2]。 当涉及到具体几何参数求解时,则依赖于诸如`edges_sub_pix`高精亚像素级边沿检测以及`fit_line_contour_xld`拟合直线模型等功能强大而灵活多样的专用函数库来进行细致入微的操作[^3]。 #### 示例代码 下面给出一段Python风格伪代码作为概念验证: ```python import halcon as hl # 加载深图像 depth_image = hl.read_image('path/to/your/depth/image') # 转换为灰图像(如果必要) if not isinstance(depth_image, hl.HObject): gray_image = hl.binocular_disparity_to_gray(depth_image) # 形态学滤波去噪和平滑化 filtered_image = hl.gray_opening_shape(gray_image, 7, 7, 'octagon') # 边缘检测 edges = hl.edges_sub_pix(filtered_image, 'canny', 0.8, 20, 40) # 提取感兴趣的两条或多条可能代表平面结构的主要线条 regions_of_interest = ... # 用户交互或其他方式指定ROI main_lines = [] for region in regions_of_interest: line_segments = hl.fit_line_contour_xld(edges.select_obj(region)) main_lines.append(line_segments) # 计算每一对选定线段间的夹角偏差以衡量其相对位置关系即所谓的‘平行’ parallelism_errors = [] for i in range(len(main_lines)): for j in range(i + 1, len(main_lines)): angle_diff = abs(hl.angle_lxld(main_lines[i], main_lines[j])) parallelism_errors.append(angle_diff) print(f'Parallelism errors between detected lines are {parallelism_errors}') ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值