CloudCompare——拟合空间球

目录

  • 1.拟合球
  • 2.软件操作
  • 3.算法源码
  • 4.相关代码

在这里插入图片描述

本文由CSDN点云侠原创,CloudCompare——拟合空间球,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT生成的文章。

1.拟合球

  源码里用到了四点定球,具体计算原理如下

  已知空间内不共面的四个点,设其坐标为 A ( x 1 , y 1 , z 1 ) A(x_1,y_1,z_1) A(x1,y1,z1) B ( x 2 , y 2 , z 2 ) B(x_2,y_2,z_2) B(x2,y2,z2) C ( x 3 , y 3 , z 3 ) 、 D ( x 4 , y 4 , z 4 ) C(x_3,y_3,z_3)、D(x_4,y_4,z_4) C(x3,y3,z3)D(x4,y4,z4),设半径为 r r r,球心 O O O坐标为 ( x , y , z ) (x,y,z) (x,y,z)。利用四点到球心距离相等的性质得到如下四个方程。
( x − x 1 ) 2 + ( y − y 1 ) 2 + ( z − z 1 ) 2 = r 2 ; ( x − x 2 ) 2 + ( y − y 2 ) 2 + ( z − z 2 ) 2 = r 2 ; ( x − x 3 ) 2 + ( y − y 3 ) 2 + ( z − z 3 ) 2 = r 2 ; ( x − x 4 ) 2 + ( y − y 4 ) 2 + ( z − z 4 ) 2 = r 2 ; (x-x_1)^2 + (y-y_1)^2 +(z-z_1)^2 =r^2;\\ (x-x_2)^2 + (y-y_2)^2 +(z-z_2)^2 =r^2;\\ (x-x_3)^2 + (y-y_3)^2 +(z-z_3)^2 =r^2;\\ (x-x_4)^2 + (y-y_4)^2 +(z-z_4)^2 =r^2; (xx1)2+(yy1)2+(zz1)2=r2;(xx2)2+(yy2)2+(zz2)2=r2;(xx3)2+(yy3)2+(zz3)2=r2;(xx4)2+(yy4)2+(zz4)2=r2;

展开得:
x 2 + y 2 + z 2 − 2 ( x 1 x + y 1 y + z 1 z ) + x 1 2 + y 1 2 + z 1 2 = r 2 ① x 2 + y 2 + z 2 − 2 ( x 2 x + y 2 y + z 2 z ) + x 2 2 + y 2 2 + z 2 2 = r 2 ② x 2 + y 2 + z 2 − 2 ( x 3 x + y 3 y + z 3 z ) + x 3 2 + y 3 2 + z 3 2 = r 2 ③ x 2 + y 2 + z 2 − 2 ( x 4 x + y 4 y + z 4 z ) + x 4 2 + y 4 2 + z 4 2 = r 2 ④ x^2 + y^2 + z^2- 2(x_1x+y_1y+z_1z)+x_1^2+y_1^2 + z_1^2 = r^2 ①\\ x^2 + y^2 + z^2- 2(x_2x+y_2y+z_2z)+x_2^2+y_2^2 + z_2^2 = r^2②\\ x^2 + y^2 + z^2- 2(x_3x+y_3y+z_3z)+x_3^2+y_3^2 + z_3^2 = r^2③\\ x^2 + y^2 + z^2- 2(x_4x+y_4y+z_4z)+x_4^2+y_4^2 + z_4^2 = r^2④ x2+y2+z22(x1x+y1y+z1z)+x12+y12+z12=r2x2+y2+z22(x2x+y2y+z2z)+x22+y22+z22=r2x2+y2+z22(x3x+y3y+z3z)+x32+y32+z32=r2x2+y2+z22(x4x+y4y+z4z)+x42+y42+z42=r2

分别作①-②、③ - ④、② - ③得:
( x 1 − x 2 ) x + ( y 1 − y 2 ) y + ( z 1 − z 2 ) z = 1 / 2 ( x 1 2 − x 2 2 + y 1 2 − y 2 2 + z 1 2 − z 2 2 ) ( x 3 − x 4 ) x + ( y 3 − y 4 ) y + ( z 3 − z 4 ) z = 1 / 2 ( x 3 2 − x 4 2 + y 3 2 − y 4 2 + z 3 2 − z 4 2 ) ( x 2 − x 3 ) x + ( y 2 − y 3 ) y + ( z 2 − z 3 ) z = 1 / 2 ( x 2 2 − x 3 2 + y 2 2 − y 3 2 + z 2 2 − z 3 2 ) (x_1-x_2)x+(y_1-y_2)y+(z_1-z_2)z=1/2(x_1^2 -x_2^2 + y_1^2 -y_2^2 + z_1^2 -z_2^2 )\\ (x_3-x_4)x+(y_3-y_4)y+(z_3-z_4)z=1/2(x_3^2 -x_4^2 + y_3^2 -y_4^2 + z_3^2 -z_4^2 )\\ (x_2-x_3)x+(y_2-y_3)y+(z_2-z_3)z=1/2(x_2^2 -x_3^2 + y_2^2 -y_3^2 + z_2^2 -z_3^2 )\\ (x1x2)x+(y1y2)y+(z1z2)z=1/2(x12x22+y12y22+z12z22)(x3x4)x+(y3y4)y+(z3z4)z=1/2(x32x42+y32y42+z32z42)(x2x3)x+(y2y3)y+(z2z3)z=1/2(x22x32+y22y32+z22z32)

其对应的系数行列式可设为:

D = ∣ a b c a 1 b 1 c 1 a 2 b 2 c 2 ∣ D=\left| \begin{matrix} a & b & c\\ a_1 & b_1 & c_1 \\ a_2 & b_2 & c_2 \end{matrix} \right| D= aa1a2bb1b2cc1c2

则: a = ( x 1 − x 2 ) , b = ( y 1 − y 2 ) , c = ( z 1 − z 2 ) , a 1 = ( x 3 − x 4 ) , b 1 = ( y 3 − y 4 ) , c 1 = ( z 3 − z 4 ) , a 2 = ( x 2 − x 3 ) , b 2 = ( y 2 − y 3 ) , c 2 = ( z 2 − z 3 ) a=(x_1-x_2),b=(y_1-y_2),c=(z_1-z_2),\\a_1=(x_3-x_4),b_1=(y_3-y_4),c_1=(z_3-z_4),\\ a_2=(x_2-x_3),b_2=(y_2-y_3),c_2=(z_2-z_3) a=(x1x2),b=(y1y2),c=(z1z2),a1=(x3x4),b1=(y3y4)c1=(z3z4),a2=(x2x3),b2=(y2y3)c2=(z2z3)

常数项行列式为:

L = ∣ P Q R ∣ L=\left| \begin{matrix} P\\ Q \\ R \end{matrix} \right| L= PQR

则:
P = 1 2 ( x 1 2 − x 2 2 + y 1 2 − y 2 2 + z 1 2 − z 2 2 ) P=\frac{1}{2}(x_1^2 -x_2^2 + y_1^2 -y_2^2 + z_1^2 - z_2^2 ) P=21(x12x22+y12y22+z12z22)
Q = 1 2 ( x 3 2 − x 4 2 + y 3 2 − y 4 2 + z 3 2 − z 4 2 ) Q=\frac{1}{2}(x_3^2 -x_4^2 + y_3^2 -y_4^2 + z_3^2 - z_4^2 ) Q=21(x32x42+y32y42+z32z42)
R = 1 2 ( x 2 2 − x 3 2 + y 2 2 − y 3 2 + z 2 2 − z 3 2 ) R=\frac{1}{2}(x_2^2 -x_3^2 + y_2^2 -y_3^2 + z_2^2 - z_3^2 ) R=21(x22x32+y22y32+z22z32)

现设:
D x = ∣ P b c Q b 1 c 1 R b 2 c 2 ∣ Dx=\left| \begin{matrix} P & b & c\\ Q & b_1 & c_1 \\ R & b_2 & c_2 \end{matrix} \right| Dx= PQRbb1b2cc1c2

D y = ∣ a P c a 1 Q c 1 a 2 R c 2 ∣ Dy=\left| \begin{matrix} a & P & c\\ a_1 & Q & c_1 \\ a_2 &R & c_2 \end{matrix} \right| Dy= aa1a2PQRcc1c2

D z = ∣ a b P a 1 b 1 Q a 2 b 2 R ∣ Dz=\left| \begin{matrix} a & b & P\\ a_1 & b_1 & Q \\ a_2 &b_2 & R \end{matrix} \right| Dz= aa1a2bb1b2PQR

由线性代数中的克拉默法则可知:
x = D x D x=\frac{Dx}{D} x=DDx

y = D y D y=\frac{Dy}{D} y=DDy

z = D z D z=\frac{Dz}{D} z=DDz

2.软件操作

  通过菜单栏的'Tools > Fit > Sphere'找到该功能。
在这里插入图片描述

  选择一个或多个点云,然后启动此工具。CloudCompare将在每个点云上拟合球体基元。在控制台中,将输出以下信息:

  • center(也可以在球体实体属性中找到球体边界框的中心)
  • radius(也可以在sphere实体属性中找到)
  • 球体拟合RMS(在默认球体实体名称中调用)注意:理论上球体拟合算法可以处理高达50%的异常值。

球形点云
在这里插入图片描述
拟合结果
在这里插入图片描述
控制台输出
在这里插入图片描述

3.算法源码

GeometricalAnalysisTools::ErrorCode GeometricalAnalysisTools::DetectSphereRobust(GenericIndexedCloudPersist* cloud,double outliersRatio,CCVector3& center,PointCoordinateType& radius,double& rms,GenericProgressCallback* progressCb/*=nullptr*/,double confidence/*=0.99*/,unsigned seed/*=0*/)
{if (!cloud){assert(false);return InvalidInput;}unsigned n = cloud->size();if (n < 4)return NotEnoughPoints;assert(confidence < 1.0);confidence = std::min(confidence, 1.0 - FLT_EPSILON);//we'll need an array (sorted) to compute the mediansstd::vector<PointCoordinateType> values;try{values.resize(n);}catch (const std::bad_alloc&){//not enough memoryreturn NotEnoughMemory;}//number of samplesunsigned m = 1;const unsigned p = 4;if (n > p){m = static_cast<unsigned>(log(1.0 - confidence) / log(1.0 - pow(1.0 - outliersRatio, static_cast<double>(p))));}//for progress notificationNormalizedProgress nProgress(progressCb, m);if (progressCb){if (progressCb->textCanBeEdited()){char buffer[64];sprintf(buffer, "Least Median of Squares samples: %u", m);progressCb->setInfo(buffer);progressCb->setMethodTitle("Detect sphere");}progressCb->update(0);progressCb->start();}//now we are going to randomly extract a subset of 4 points and test the resulting sphere each timeif (seed == 0){std::random_device randomGenerator;   // non-deterministic generatorseed = randomGenerator();}std::mt19937 gen(seed);  // to seed mersenne twister.std::uniform_int_distribution<unsigned> dist(0, n - 1);unsigned sampleCount = 0;unsigned attempts = 0;double minError = -1.0;std::vector<unsigned> indexes;indexes.resize(p);while (sampleCount < m && attempts < 2*m){//get 4 random (different) indexesfor (unsigned j = 0; j < p; ++j){bool isOK = false;while (!isOK){indexes[j] = dist(gen);isOK = true;for (unsigned k = 0; k < j && isOK; ++k)if (indexes[j] == indexes[k])isOK = false;}}assert(p == 4);const CCVector3* A = cloud->getPoint(indexes[0]);const CCVector3* B = cloud->getPoint(indexes[1]);const CCVector3* C = cloud->getPoint(indexes[2]);const CCVector3* D = cloud->getPoint(indexes[3]);++attempts;CCVector3 thisCenter;PointCoordinateType thisRadius;if (ComputeSphereFrom4(*A, *B, *C, *D, thisCenter, thisRadius) != NoError)continue;//compute residualsfor (unsigned i = 0; i < n; ++i){PointCoordinateType error = (*cloud->getPoint(i) - thisCenter).norm() - thisRadius;values[i] = error*error;}const unsigned int	medianIndex = n / 2;std::nth_element(values.begin(), values.begin() + medianIndex, values.end());//the error is the median of the squared residualsdouble error = static_cast<double>(values[medianIndex]);//we keep track of the solution with the least errorif (error < minError || minError < 0.0){minError = error;center = thisCenter;radius = thisRadius;}++sampleCount;if (progressCb && !nProgress.oneStep()){//progress canceled by the userreturn ProcessCancelledByUser;}}//too many failures?!if (sampleCount < m){return ProcessFailed;}//last step: robust estimationReferenceCloud candidates(cloud);if (n > p){//e robust standard deviation estimate (see Zhang's report)double sigma = 1.4826 * (1.0 + 5.0 /(n-p)) * sqrt(minError);//compute the least-squares best-fitting sphere with the points//having residuals below 2.5 sigmadouble maxResidual = 2.5 * sigma;if (candidates.reserve(n)){//compute residuals and select the pointsfor (unsigned i = 0; i < n; ++i){PointCoordinateType error = (*cloud->getPoint(i) - center).norm() - radius;if (error < maxResidual)candidates.addPointIndex(i);}candidates.resize(candidates.size());//eventually estimate the robust sphere parameters with least squares (iterative)if (RefineSphereLS(&candidates, center, radius)){//replace input cloud by this subset!cloud = &candidates;n = cloud->size();}}else{//not enough memory!//we'll keep the rough estimate...}}//update residuals{double residuals = 0;for (unsigned i = 0; i < n; ++i){const CCVector3* P = cloud->getPoint(i);double e = (*P - center).norm() - radius;residuals += e*e;}rms = sqrt(residuals/n);}return NoError;
}

4.相关代码

[1]C++实现:PCL RANSAC拟合空间3D球体
[2]python实现:Open3D——RANSAC三维点云球面拟合
[3] Open3D 最小二乘拟合球
[4] Open3D 非线性最小二乘拟合球

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/612215.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[笔记]学习做微信小程序

学习视频&#xff1a;前端微信小程序开发教程 本篇文章 只对关键内容笔记&#xff0c;用于自用。 这里写目录标题 注册、下载、安装我的小程序ID&#xff1a;wxe1fbd6939d8797d8我的小游戏ID&#xff1a;wx8b2c3e47ac9127b7开发者工具外观代理设置 创建第一个小程序主界面5个组…

QT开发 2024最新版本优雅的使用vscode开发QT

▬▬▬▬▬▶VS开发QT◀▬▬▬▬▬ &#x1f384;先看效果 &#x1f384;编辑环境变量 如图添加环境变量&#xff01;&#xff01;&#xff01; 东西全在QT的安装目录&#xff01;&#xff01;&#xff01; 找到的按照我的教程再装一次&#xff01;&#xff01;&#xff01; 点…

postman 之 接口请求

一、前言 1. 安装 2. 主界面 3. 请求区域 Body下主要包含以下4中格式 form-data&#xff1a;混合表单&#xff0c;支持上传文件x-www-form-urlencoded&#xff1a;文本表单raw&#xff1a;原始格式&#xff0c;支持JSON/XML格式&#xff08;后面可选择&#xff09;binary&am…

Camunda Event Based Gateway

一&#xff1a;bpmn 二&#xff1a;java 如果没有收到信号&#xff0c;超过等待时间&#xff0c;流程进入总经理审批&#xff0c;如果在等待时间内收到信号&#xff0c;流程进入副总经理审批。 示例1&#xff1a;发送信号事件&#xff0c;流程进入副总经理审批。 repository…

yolo 分割label格式标注信息图片显示可视化查看

参考: https://github.com/ultralytics/ultralytics/issues/3137 https://blog.csdn.net/weixin_42357472/article/details/135218349?spm=1001.2014.3001.5501 需要把坐标信息在图片上显示 代码 1)只画出了坐标边缘 import cv2 import numpy as np from random impor…

AlexNet论文精读

1:该论文解决了什么问题&#xff1f; 图像分类问题 2&#xff1a;该论文的创新点&#xff1f; 使用了大的深的卷积神经网络进行图像分类&#xff1b;采用了两块GPU进行分布式训练&#xff1b;采用了Relu进行训练加速&#xff1b;采用局部归一化提高模型泛化能力&#xff1b;…

通过反射修改MultipartFile类文件名

1、背景 项目上有这样一个需求&#xff0c;前端传文件过来&#xff0c;后端接收后按照特定格式对文件进行重命名。(修改文件名需求其实也可以在前端处理的) //接口类似于下面这个样子 PosMapping("/uploadFile") public R uploadFile(List<MultipartFile> fil…

uniapp 字母索引列表插件(组件版) Ba-SortList

简介&#xff08;下载地址&#xff09; Ba-SortList 是一款字母索引列表组件版插件&#xff0c;可自定义样式&#xff0c;支持首字母字母检索、首字检索、搜索等等&#xff1b;支持点击事件。 支持首字母字母检索支持首字检索支持搜索支持点击事件支持长按事件支持在uniapp界…

Mac安装nvm以及使用nvm安装node

1. 安装nvm命令 git clone https://gitee.com/mirrors/nvm.git ~/.nvm && cd ~/.nvm && git checkout git describe --abbrev0 --tags2. 配置环境变量 vi ~/.bash_profileexport NVM_DIR"$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] &&…

【Vue2】一个数组按时间分割为【今年】和【往年】俩个数组

一. 需求 后端返回一个数组&#xff0c;前端按时间维度将该数组的分割为【今年】和【往年】俩个数组后端返回的数组格式如下 timeList:[{id:1,billTime:"2024-01-10",createTime:"2024-01-10 00:00:00",status:0},{id:2,billTime:"2022-05-25"…

【大数据】NiFi 中的处理器(二):PutDatabaseRecord

NiFi 中的处理器&#xff08;二&#xff09;&#xff1a;PutDatabaseRecord 1.基本介绍2.属性配置3.连接关系4.应用场景 1.基本介绍 PutDatabaseRecord 处理器使用指定的 RecordReader 从传入的流文件中读取&#xff08;可能是多个&#xff0c;说数组也成&#xff09;记录。这…

DHSP和DNS

一、服务程序 1.1DHCP定义 DHCP&#xff08;动态主机配置协议&#xff09;是一个局域网的网络协议。指的是由服务器控制一段IP地址范围&#xff0c;客户机登录服务器时就可以自动获得服务器分配的IP地址和子网掩码。默认情况下&#xff0c;DHCP作为Windows Server的一个服务组…

性格是如何形成的?能不能改变性格?

有一句话叫“性格决定命运”&#xff0c;广泛流传&#xff0c;也就是说 “命运”与“性格”是紧密相连的&#xff0c;可见“性格”对于一个人的重要性。 性格是怎么来的&#xff1f; 1、遗传基因 根据一些心理学家的最新研究&#xff0c;认为性格与人体内的基因有关系&#x…

不再恐惧指针,指针详解

什么是指针&#xff1f; 通俗来说指针就相当于地址&#xff0c;因为我们写入的代码每个变量的数据类型不同&#xff0c;字节大小不同&#xff0c;在计算机内存中所开辟存储的大小自然不同&#xff0c;且指针通常存储的是内存单元中最小单元的编号 比如&#xff1a;int*指针的…

【Scala】——面向对象

1 Scala 包 1.1 包风格 Scala 有两种包的管理风格。 第一种 Java 的包管理风格相同&#xff0c;每个源文件一个包&#xff08;包 名和源文件所在路径不要求必须一致&#xff09;&#xff0c;包名用“.”进行分隔以表示包的层级关系&#xff0c;如 com.atguigu.scala。另一种风…

遥感单通道图像保存为彩色图像

系列文章目录 第一章PIL单通道图像处理 文章目录 系列文章目录前言一、代码实现二、问题记录在这里插入图片描述 总结 前言 将单通道图像以彩色图像的形式进行保存主要使用了PIL库 一、代码实现 palette_data [***]&#xff1a;可以进行自定义设置 代码如下&#xff1a; fr…

UVa12304 2D Geometry 110 in 1!

题目链接 UVa12304 2D Geometry 110 in 1! 题意 这是一个拥有6&#xff08;二进制是110&#xff09;个子问题的2D几何问题集。 1 CircumscribedCircle x1 y1 x2 y2 x3 y3&#xff1a;求三角形(x1,y1)-(x2,y2)-(x3,y3)的外接圆。这3点保证不共线。答案应格式化成(x,y,r…

服务器 配置git

参考了下面这篇文章&#xff0c;不对的地方做了改正 在服务器上git clone github项目的过程-CSDN博客 1. 下载解压 wget https://www.kernel.org/pub/software/scm/git/git-2.34.1.tar.gz tar -zxvf git-2.34.1.tar.gz 2. 安装 cd git-2.34.1/ ./configure make confi…

Geotools-PG空间库(Crud,属性查询,空间查询)

建立连接 经过测试&#xff0c;这套连接逻辑除了支持纯PG以外&#xff0c;也支持人大金仓&#xff0c;凡是套壳PG的都可以尝试一下。我这里的测试环境是Geosence创建的pg SDE&#xff0c;数据库选用的是人大金仓。 /*** 获取数据库连接资源** param connectConfig* return* {…

springboot私人健身与教练预约管理系统源码和论文

随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&#xf…