Halcon计算点到平面的距离没有那么简单
Halcon计算点到平面距离
- 1. 一些基本概念
- 2. 浅谈有无符号的距离
- 2.1 无符号距离的用武之地
- 2.2 有符号距离的必要性
- 3. 无符号距离怎么算
- 3.1 创建一个无限延展的基准平面,对距离有什么影响?
- Halcon代码
- 图示
- 3.2 创建一个小小小的基准平面,对距离有什么影响?
- halcon代码
- 图示
- 3.3 直接使用点云拟合基准平面,可行吗?
- halcon代码
- 图示
- 4. 有符号距离怎么算
- 4.1 诡异的平面法向量方向
- 4.1.1 下面的halcon代码展示了如何获得平面单位法向量,或者说如何获得平面方程一般式 A、B、C、D
- 4.1.2 Halcon如何解释 A、B、C、D
- 4.1.3 我们如何理解A、B、C、D
- 4.1.4 如何修改法向量
- 4.2 封装计算带符号距离的方法
- 4.3 全部测试代码
1. 一些基本概念
- 三维点:就是三维空间中的点(X,Y,Z)
- 平面:三维空间中的平面
- 平面方程:一般式:AX+BY+CZ+D=0
- 点到平面距离:过点做平面垂线,点到垂足的距离。(投影)
2. 浅谈有无符号的距离
2.1 无符号距离的用武之地
- 不带符号的距离相对简单,它不用理会平面方程法向量的方向,以及坐标系原点与平面之间的关系。
- Halcon中有很好用的算子,只需要设置合适的参数,就能非常方便的计算出三维点到平面的距离。
- 当然这个距离是没有符号的,也就是说你是无法通过这个距离来判断点与平面的位置关系的。点在平面上方, 还是在平面下方?(平面的上方下方这种表达并不准确,应该和平面法向量方向作比较)。那么这种计算距离的方法还有用武之地吗?当然,如果你确定你测量的点一定在基准面的一侧,那么你就可以放心大胆的使用此方法了,不是吗?
- 下图中,如果你想测量黑色元器件到PCB板的相对高度(距离),使用这种方法就非常合适,因为元器件上表面上的点到PCB的距离不可能小于0。
2.2 有符号距离的必要性
- 如下图,如果要测量元器件周围白色胶水到元件的高度呢?工艺要求是,胶水要比元件高,但是很有可能胶水点少了,胶高就低于元件了。这样如果还只是测量无符号距离的话,就很可能造成误判。
3. 无符号距离怎么算
3.1 创建一个无限延展的基准平面,对距离有什么影响?
Halcon代码
X:=[0,1,2,3,\0,1,2,3,\0,1,2,3,\0,1,2,3]
Y:=[0,0,0,0,\1,1,1,1,\2,2,2,2,\3,3,3,3]
Z:=[0.5,0,0,0,\0,0.1,0,0,\0,0.1,0,0,\0,0,0,0]
* 使用一组三维点创建三维点云物体模型
gen_object_model_3d_from_points (X, Y, Z, MeasurePoints)
* 创建一个基准平面
gen_plane_object_model_3d ([0,0,0,0,0,0,0], [], [], BasePlane)
* 计算三维点到基准平面的距离
distance_object_model_3d (MeasurePoints, BasePlane, [], 0, 'distance_to', 'primitive')
* 获取距离数据
get_object_model_3d_params (MeasurePoints, '&distance', distances)
图示
- 从图中可以看出,由于创建的平面是无限延展的,所以点云中的所有点都无法逃脱平面的掌控,这样计算距离是不会有问题的。
3.2 创建一个小小小的基准平面,对距离有什么影响?
halcon代码
- 在3.1的代码中修改一下基准的范围,如下图,现在基准平面完全hold不住所有点。
* 创建一个基准平面
gen_plane_object_model_3d ([0,0,0,0,0,0,0], [0,0,1,1], [0,1,1,0], BasePlane)
图示
- 通过观察上面的距离数据,你就会发现,这里计算点到平面距离,基准平面并不是默认为无限延展的,如果基准面不够大,那么没有在平面势力范围内的点就会找平面里离它最近的一个点。
3.3 直接使用点云拟合基准平面,可行吗?
halcon代码
- 你是说你使用点云上的所有点拟合成一个平面,这个平面作为基准平面,然后再计算点云里所有的点到基准平面的距离? 这种方法当然是可行的。
* 创建一个基准平面
fit_primitives_object_model_3d (ObjectModel3D, ['primitive_type','fitting_algorithm'], \['plane','least_squares_tukey'], BasePlane)
gen_plane_object_model_3d ([0,0,0,0,0,0,0], [0,0,1,1], [0,1,1,0], BasePlane)
- 不用担心这个基准面不够大,经过我的验证,这个平面刚刚好,够用就行了,不是非要无限延展不可。
图示
4. 有符号距离怎么算
- 其实我写到这里已经累了,但是又不想半途而废,所以坚持写完吧。
4.1 诡异的平面法向量方向
4.1.1 下面的halcon代码展示了如何获得平面单位法向量,或者说如何获得平面方程一般式 A、B、C、D
* 计算带符号的三维点到平面的距离
X:=[1,2,3,4,\1,2,3,4,\1,2,3,4,\1,2,3,4]
Y:=[1,1,1,1,\2,2,2,2,\3,3,3,3,\4,4,4,4]Z:=[0,0,0,0,\0,1,1,0,\0,1,1,0,\0,0,0,0]dev_get_window (WindowHandle)gen_object_model_3d_from_points (X, Y, Z, ObjectModel3D)
fit_primitives_object_model_3d (ObjectModel3D, ['primitive_type','fitting_algorithm'], \['plane','least_squares_tukey'], ObjectModel3DOut)
visualize_object_model_3d (WindowHandle, [ObjectModel3DOut,ObjectModel3D], \[], [], ['disp_pose','color_0','color_1'], ['true','gray','blue'], [], [], [], PoseOut)get_object_model_3d_params (ObjectModel3DOut, 'primitive_parameter', GenParamValue) //GenParamValue里面有四个参数,就是平面方程的A、B、C、D
4.1.2 Halcon如何解释 A、B、C、D
- 但是halcon对于A、B、C、D的解释并非我们想的那样自然,以下是get_object_model_3d_params 的参数解释,以及豆包的翻译。
4.1.3 我们如何理解A、B、C、D
- 先不说别的,我给出两组数据,观察一下结果:
- 我们观察到,当平面高于 Z=0 平面时,单位法向量 (A,B,C) 指向与Z轴的正方向相反;
- 而当平面低于 Z=0 平面时,单位法向量 (A,B,C) 指向与Z轴的正方向相同;
- 为了观察的更仔细,我再给两组数据,
- 从这两组数据可以看出,平面单位法向量的方向和平面与Z轴的交点有关,如果交点在原点上方,那么法向量的方向与Z轴正方向所成的夹角是钝角,或者简单说成法向量指向下方。反之,法向量指向上方。
- 我为什么这么在意法向量指向那一侧呢?因为这能帮助我们判断一个三维点在平面的哪一侧。如果我们想一个办法,可以让平面的法向量永远向上指(法向量与Z轴夹角为锐角),那这个问题就可以画上句号了。
4.1.4 如何修改法向量
- 如果 (A,B,C) 是平面 Plane 的单位法向量,那么 (-A,-B,-C) 也是它的法向量,只不过和前面的那个法向量方向相反。
- 从4.1.2中我们了解到,可以通过 D 的符号来判断原点位于平面的哪一侧,确定了这件事情后,我们也就知道平面法向量指向哪一侧了。
- 然后,我们通过一些处理,让法向量永远指向我们想要的方向。
- 不想再解释了,现在真的累了,直接给代码吧。
4.2 封装计算带符号距离的方法
GetPointToPlaneDistance (PlaneA, PlaneB, PlaneC, PlaneD, X, Y, Z, Distance)
if (PlaneC<0)PlaneA:=-PlaneAPlaneB:=-PlaneBPlaneC:=-PlaneC
elsePlaneD:=-PlaneD
endifNumPoints := |X|
Distance := []for I := 0 to NumPoints-1 by 1Numerator := PlaneA * X[I] + PlaneB * Y[I] + PlaneC * Z[I] + PlaneDSignedDistance := NumeratorDistance := [Distance, SignedDistance]
endfor
return ()
4.3 全部测试代码
* 计算带符号的三维点到平面的距离
X:=[1,2,3,4,\1,2,3,4,\1,2,3,4,\1,2,3,4]
Y:=[1,1,1,1,\2,2,2,2,\3,3,3,3,\4,4,4,4]Z:=[1,0,0,0,\0,0,0,0,\0,0,0,0,\0,0,0,0]dev_get_window (WindowHandle)gen_object_model_3d_from_points (X, Y, Z, ObjectModel3D)
fit_primitives_object_model_3d (ObjectModel3D, ['primitive_type','fitting_algorithm'], \['plane','least_squares_tukey'], ObjectModel3DOut)get_object_model_3d_params (ObjectModel3DOut, 'primitive_parameter', GenParamValue)PlaneA:=GenParamValue[0]
PlaneB:=GenParamValue[1]
PlaneC:=GenParamValue[2]
PlaneD:=GenParamValue[3]GetPointToPlaneDistance (PlaneA, PlaneB, PlaneC, PlaneD, X, Y, Z, Distance)* visualize_object_model_3d (WindowHandle, [ObjectModel3DOut,ObjectModel3D], \[], [], ['disp_pose','color_0','color_1'], ['true','gray','blue'], [], [], [], PoseOut)
相关文章:

Halcon计算点到平面的距离没有那么简单
Halcon计算点到平面距离 1. 一些基本概念2. 浅谈有无符号的距离2.1 无符号距离的用武之地2.2 有符号距离的必要性 3. 无符号距离怎么算3.1 创建一个无限延展的基准平面,对距离有什么影响?Halcon代码图示 3.2 创建一个小小小的基准平面,对距离…...
基于DenseNet的医学影像辅助诊断系统开发教程
本文源码地址: https://download.csdn.net/download/shangjg03/90873921 1. 简介 本教程将使用DenseNet开发一个完整的医学影像辅助诊断系统,专注于胸部X光片的肺炎检测。我们将从环境搭建开始,逐步介绍数据处理、模型构建、训练、评估以及最终的系统部署。 2. 环境准备<…...

数据中台如何设计?中台开发技术方案,数据治理方案,大数据建设方案合集
中台的价值与核心理念 中台的核心在于“企业级能力复用”,其价值体现在四大维度: 能力整合:将分散的数字化能力(如营销、供应链)集中管理,形成核心竞争力; 业务创新:通过跨领域融合…...
Python爬虫设置IP代理
设置代理(Proxy) 作用: 当网站检测到某个IP的访问频率过高时,可能会封禁该IP。通过使用代理服务器,可以定期更换IP地址,避免被识别和封锁。 优势: 让网站无法追踪真实请求来源,提升…...

Adminer 连接mssql sqlserver
第一步 docker-compose.yml adminer部分: version: 3.8 services: adminer: image: adminer:latest container_name: adminer restart: unless-stopped volumes: - ./freetds/freetds.conf:/etc/freetds.conf:rw # 确保 :rw 可读写 co…...

C++系统IO
C系统IO 头文件的使用 1.使用系统IO必须包含相应的头文件,通常使用#include预处理指令。 2.头文件中包含了若干变量的声明,用于实现系统IO。 3.头文件的引用方式有双引号和尖括号两种,区别在于查找路径的不同。 4.C标准库提供的头文件通常没…...
利用 Python 爬虫获取唯品会 VIP 商品详情:实战指南
在当今电商竞争激烈的环境中,VIP 商品往往是商家的核心竞争力所在。这些商品不仅代表着品牌的高端形象,更是吸引高价值客户的关键。因此,获取 VIP 商品的详细信息对于市场分析、竞品研究以及优化自身产品策略至关重要。Python 作为一种强大的…...

DELL EMC PowerStore BBU更换手册
写在前面 上周给客户卖了一个BBU电池,客户要写一个更换方案。顺利完成了更换,下面就把这个更换方案给大家share出来,以后客户要写,您就Ctrlc 和Ctrlv就可以了。 下面的步骤是最理想的方式,中间没有任何的问题ÿ…...

css五边形
五边形 .fu{width: 172rpx;height: 204rpx;overflow: hidden;border-radius: 10rpx;clip-path: polygon(0% 0%, 100% 0%, 100% 75%, 50% 100%, 0% 75%, 0% 25%); }六边形 clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);...

三种常见脉冲神经网络编码方式解读
速率编码(rate coding) 速率编码使用输入特征来确定尖峰频率,例如将静态输入数据(如 MNIST 图像)转换为时间上的脉冲(spike)序列。它是将神经元发放脉冲的频率与输入值(如像素强度)…...
Go语言实战:使用 excelize 实现多层复杂Excel表头导出教程
Go 实现支持多层复杂表头的 Excel 导出工具 目录 项目介绍依赖说明核心结构设计如何支持多层表头完整使用示例总结与扩展 项目介绍 在实际业务系统中,Excel 文件导出是一项常见功能,尤其是报表类需求中常见的复杂多级表头,常规表格组件往…...

STM32F103 HAL多实例通用USART驱动 - 高效DMA+RingBuffer方案,量产级工程模板
导言 《STM32F103_LL库寄存器学习笔记12.2 - 串口DMA高效收发实战2:进一步提高串口接收的效率》前阵子完成的LL库与寄存器版本的代码,有一个明显的缺点是不支持多实例化。最近,计划基于HAL库系统地梳理一遍bootloader程序开发。在bootloader程…...

HTML回顾
html全称:HyperText Markup Language(超文本标记语言) 注重标签语义,而不是默认效果 规则 块级元素包括: marquee、div等 行内元素包括: span、input等 规则1:块级元素中能写:行内元素、块级元素&…...

机器视觉6-halcon高级教程
机器视觉6-halcon高级教程 双目立体视觉原理视差外极线几何双目标定 双目立体视觉之Halcon标定一.标定结果二.Halcon标定过程1.获取左右相机图像中标定板的区域;2.提取左右相机图像中标定板的MARK点坐标和摄像机外部参数;3.执行双目标定;4.获取非标准外极线几何到标…...

YOLOv8 的双 Backbone 架构:解锁目标检测新性能
一、开篇:为何踏上双 Backbone 探索之路 在目标检测的领域中,YOLOv8 凭借其高效与精准脱颖而出,成为众多开发者和研究者的得力工具。然而,传统的单 Backbone 架构,尽管已经在诸多场景中表现出色,但仍存在一…...

1.4 TypeScript 编译是如何工作的?
TypeScript 是 JavaScript 的超集,最显著的优势是引入了静态类型检查。它能帮助开发者在编写代码阶段捕获错误,从而提升代码的健壮性和可维护性。虽然 TypeScript 本身不能直接在浏览器或 Node.js 中运行,但它可以被编译成标准的 JavaScript&…...
【HTML-4】HTML段落标签:构建内容结构的基础
在网页开发中,段落标签<p>是最基础也是最重要的HTML元素之一。这篇博客将深入探讨段落标签的用法、最佳实践以及相关技术细节。 1. 段落标签的基本用法 HTML段落标签用于定义文本段落,浏览器会自动在段落前后添加一定的空白(margin&a…...
国际前沿知识系列五:时间序列建模方法在头部撞击运动学测量数据降噪中的应用
目录 国际前沿知识系列五:时间序列建模方法在头部撞击运动学测量数据降噪中的应用 一、引言 二、时间序列建模方法 (一)ARIMA 模型 (二)指数平滑法 (三)小波变换 三、实际案例分析 &…...
未授权访问漏洞利用链实战总结
一、渗透测试核心思路 攻击链路径: 未授权访问 → 接口信息泄露 → 敏感数据获取 → 账户爆破 → 权限提升 → 系统控制 二、关键步骤拆解与分析 信息收集阶段 初始突破口: 系统登录页看似无效,但通过JS文件分析发现隐藏接口(如 …...
Centos上搭建 OpenResty
一、OpenResty简介 OpenResty 是基于 Nginx 的扩展平台,完全兼容 Nginx 的核心功能(如 HTTP 服务和反向代理),同时通过内嵌 LuaJIT 支持,允许开发者用 Lua 脚本灵活扩展业务逻辑。它简化了动态逻辑的实现。 二、安装…...

Web 服务、 Nfs 服务器以及 Dns 服务器综合实验
要求: 1.web 服务的资源文件通过 nfs 服务器共享 www.luntan.com 2.确保所有主机时间同步 3.定义本地 dns 服务器解析 web 主机域名 实验: 主机服务程序192.168.96.142dns、nfs192.168.96.132web 服务器说明: 设备 IP服务端 192…...
保证数据库 + redis在读写分离场景中事务的一致性
在 Spring Boot 中实现数据库与 Redis 的一致性,特别是处理读写分离时,确保数据修改的事务一致性是一个常见的挑战。因为 Redis 是一个内存数据库,通常用于缓存,而关系型数据库是持久化存储,两者之间的数据同步和一致性…...

汇编语言的子程序魔法:解锁四则运算的奥秘
在嵌入式系统的世界里,汇编语言就像是魔法师手中的魔杖,能够直接操控硬件,实现各种神奇的功能。今天,我将带你走进一场充满乐趣的实验:如何用汇编语言实现四则运算,并将它们封装成子程序。这不仅是一次技术…...

快速解决Linux 中yum镜像拉取失败问题
在linux中使用yum命令拉取镜像的时候,如果出现如下类似报错: 我这里是安装Erlang环境也是同样报错: 其实就是网络环境的问题,更换为国内的镜像源就行了,可以选择cmd的ssh连接方式(命令:ssh root192.168.xxx…...
C#核心概念解析:析构函数、readonly与this关键字
🔍 析构函数:资源清理的最后防线 核心作用 析构函数(~ClassName)在对象销毁前执行,专用于释放非托管资源(如文件句柄、非托管内存)。托管资源(如.NET对象)由GC自动回收…...

HarmonyOS基础组件:Button三种类型的使用
简介 HarmonyOS在明年将正式不再兼容Android原生功能,这意味着对于客户端的小伙伴不得不开始学习HarmonyOS开发语言。本篇文章主要介绍鸿蒙中的Button使用。 HarmonyOS中的Button相较于Android原生来说,功能比较丰富,扩展性高,减…...
深入理解设计模式之适配器模式
深入理解设计模式之适配器模式 1. 适配器模式概述 适配器模式(Adapter Pattern)是一种结构型设计模式,它允许将一个类的接口转换为客户端所期望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的类能够协同工作,扮演了"转换器&quo…...
预训练模型:深度学习的通用特征引擎
预训练模型是深度学习领域的重要技术,其核心思想是通过大规模数据预先学习通用特征,再迁移到具体任务中进行微调。以下是其定义、原理及与其他模型的对比分析: 一、预训练模型的定义与原理 基本概念 预训练模型(Pre-trained Model…...
C++题解(33)2025年顺德区中小学生程序设计展示活动(初中组C++)U560876 美丽数(一)和 U560878 美丽数(二)题解
U560876 美丽数(一) 题目描述 小明很喜欢3和5这两个数字,他将能被3或5整除的数叫做美丽数。现在给你一个整数n,你能告诉小明第n个美丽数是多少吗? 输入格式 输入有多行,每行只有一个整数${n_i}$。 输出格式…...

产业互联网+三融战略:重构企业增长密码
产业互联网时代:用"三融"重构企业增长飞轮 在产业互联网浪潮下,企业面临资源分散、资金短缺、人才难聚的三重挑战。本文提出的"融人、融资、融资源"顶层设计,正为新时代企业构建增长新引擎。 一、三级合伙人体系&#x…...