pclpy 拉格朗日乘子法拟合平面

news2025/2/27 23:03:56

pclpy 拉格朗日乘子法拟合平面

      • 一、算法原理
          • 1.算法步骤
      • 二、代码
      • 三、结果
          • 1.左边原点云数据,右边将点云拉格朗日乘子法拟合平面投影在该平面
      • 四、相关数据

一、算法原理

1.算法步骤

对k一近邻点拟合平面,最小二乘法(平面过重心),拟定公式为
a ( x − x ) + b ( y − y ) + c ( z − z ) = 0 a(x-\frac{}{x}) + b(y-\frac{}{y}) + c(z-\frac{}{z}) =0 a(xx)+b(yy)+c(zz)=0

  1. 求重心
    x = 1 N ∑ i = 1 N x i , y = 1 N ∑ i = 1 N y i , z = 1 N ∑ i = 1 N z i \frac{}{x}=\frac{1}{N}\sum_{i=1}^{N}{xi},\frac{}{y}=\frac{1}{N}\sum_{i=1}^{N}{yi},\frac{}{z}=\frac{1}{N}\sum_{i=1}^{N}{zi} x=N1i=1Nxi,y=N1i=1Nyi,z=N1i=1Nzi
  2. 去重心化
    x = x i − x , y = y i − y , x = z i − z x = xi -\frac{}{x}, y = yi -\frac{}{y}, x = zi -\frac{}{z} x=xix,y=yiy,x=ziz
  3. 拉格朗日乘子法求函数
    m i n ( ∑ i = 1 N i ∗ ∑ i = 1 N i ) = ∑ i = 1 N ( a x + b y + c z ) ∗ ( a x + b y + c z ) min(\sum_{i=1}^{N}{i}*\sum_{i=1}^{N}{i})= \sum_{i=1}^{N}{(ax + by + cz)*(ax + by + cz)} min(i=1Nii=1Ni)=i=1N(ax+by+cz)(ax+by+cz)
    4)求偏导

1.4.1 对a求偏导
2 x i ∑ i = 1 N a x i + b y i + c z i 2xi\sum_{i=1}^{N}{axi+byi+czi} 2xii=1Naxi+byi+czi
1.4.2 对b求偏导
2 y i ∑ i = 1 N a x i + b y i + c z i 2yi\sum_{i=1}^{N}{axi+byi+czi} 2yii=1Naxi+byi+czi
1.4.3 对c求偏导
2 z i ∑ i = 1 N a x i + b y i + c z i 2zi\sum_{i=1}^{N}{axi+byi+czi} 2zii=1Naxi+byi+czi
1.4.3 矩阵化

在这里插入图片描述

  1. 求出最小特征向量

二、代码

from pclpy import pcl
import numpy as np


def CloudShow(cloud1, cloud2):
    """
    Args:在一个窗口可视化多个点云
        cloud1: 点云数据1
        cloud2: 点云数据2
    """
    viewer = pcl.visualization.PCLVisualizer("viewer")  # 建立可刷窗口对象 窗口名 viewer
    v0 = 1  # 设置标签名(0, 1标记第一个窗口)
    viewer.createViewPort(0.0, 0.0, 0.5, 1.0, v0)  # 创建一个可视化的窗口
    viewer.setBackgroundColor(0.0, 0.0, 0.0, v0)  # 设置窗口背景为黑色
    single_color = pcl.visualization.PointCloudColorHandlerCustom.PointXYZ(cloud1, 255.0, 0, 0.0)  # 将点云设置为红色
    viewer.addPointCloud(cloud1,  # 要添加到窗口的点云数据。
                         single_color,  # 指定点云的颜色
                         "sample cloud1",  # 添加的点云命名
                         v0)  # 点云添加到的视图

    v1 = 2  # 设置标签名(2代表第二个窗口)
    viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v1)  # 创建一个可视化的窗口
    viewer.setBackgroundColor(255.0, 255.0, 255.0, v1)  # 设置窗口背景为白色
    single_color = pcl.visualization.PointCloudColorHandlerCustom.PointXYZ(cloud2, 0.0, 255.0, 0.0)  # 将点云设置为绿色
    viewer.addPointCloud(cloud2,  # 要添加到窗口的点云数据。
                         single_color,  # 指定点云的颜色
                         "sample cloud2",  # 添加的点云命名
                         v1)  # 点云添加到的视图

    # 设置点云窗口(可移除对点云可视化没有影响)
    viewer.setPointCloudRenderingProperties(0,  # 设置点云点的大小
                                            1,  # 点云像素
                                            "sample cloud1",  # 识别特定点云
                                            v0)  # 在那个窗口可视化
    viewer.setPointCloudRenderingProperties(0,  # 设置点云点的大小
                                            1,  # 点云像素
                                            "sample cloud2",  # 识别特定点云
                                            v1)  # 在那个窗口可视化
    # viewer.addCoordinateSystem(1.0)  # 设置坐标轴 坐标轴的长度为1.0
    # 窗口建立
    while not viewer.wasStopped():
        viewer.spinOnce(10)


def plane(cloud, normal_vector):
    coeffs = pcl.ModelCoefficients()  # 创建了一个模型系数对象
    coeffs.values.append(normal_vector[0])  # a = 0.0
    coeffs.values.append(normal_vector[1])  # b = 0.0
    coeffs.values.append(normal_vector[2])  # c = 1.0
    coeffs.values.append(normal_vector[3])  # d = 0.0

    # 创建滤波器
    proj = pcl.filters.ProjectInliers.PointXYZ()  # 过滤器对象 proj,用于将点云投影到一个模型上。
    proj.setModelType(0)  # 模型类型被设为 0,代表使用平面模型。
    proj.setInputCloud(cloud)  # 将cloud点云数据进行处理
    proj.setModelCoefficients(coeffs)  # 处理参数coeffs
    cloud_projected = pcl.PointCloud.PointXYZ()  # 建立保存点云
    proj.filter(cloud_projected)  # 将投影结果保存

    return cloud_projected

if __name__ == '__main__':
    cloud1 = pcl.PointCloud.PointXYZ()
    reader = pcl.io.PCDReader()  # 设置读取对象
    reader.read('res/bunny.pcd', cloud1)  # 读取点云保存在cloud中

    # 调用函数,生成离散点
    x, y, z = cloud1.x, cloud1.y, cloud1.z
    # 求重心
    x0 = np.mean(x)   # 计算平均值
    y0 = np.mean(y)   # 计算平均值
    z0 = np.mean(z)   # 计算平均值
    # 去重心
    x = x - x0
    y = y - y0
    z = z - z0
    # ------------------------构建系数矩阵-----------------------------
    A = np.array([[np.sum(x * x), np.sum(x * y), np.sum(x * z)],
                  [np.sum(x * y), np.sum(y * y), np.sum(y * z)],
                  [np.sum(x * z), np.sum(y * z), np.sum(z * z)]])
    [D, X] = np.linalg.eig(A)  # 计算矩阵的特征值和特征向量的函数

    # 找到最小特征值的索引
    min_eigenvalue_index = np.argmin(D)

    # 获取对应的特征向量
    min_eigenvector = X[:, min_eigenvalue_index]
    print('平面拟合结果为:z = %.3f * x + %.3f * y + %.3f' % (min_eigenvector[0], min_eigenvector[1], min_eigenvector[2]))

    # 平面参数
    a, b, c, d = min_eigenvector[0], min_eigenvector[1], min_eigenvector[2], -min_eigenvector[0]*x0 - min_eigenvector[1]*y0 - min_eigenvector[2]*z0
    plane_cloud = plane(cloud1, [a, b, c, d])  # 获得投影后的点云数据
    # ------------------ 可视化点云 -----------------

    CloudShow(cloud1, plane_cloud)  # 可视化点云

三、结果

1.左边原点云数据,右边将点云拉格朗日乘子法拟合平面投影在该平面

在这里插入图片描述

四、相关数据

open3d 将点云投影到平面-CSDN博客:open3d 将点云投影到平面-CSDN博客

pclpy 参数模型投影:pclpy 参数模型投影-CSDN博客

拉格朗日乘子法理论参考:最小二乘拟合平面(python/C++版) - 知乎 (zhihu.com)

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

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

相关文章

金三银四面试必问:Redis真的是单线程吗?

文章目录 01 Redis中的多线程1)redis-server:2)jemalloc_bg_thd3)bio_xxx: 02 I/O多线程03 Redis中的多进程04 结论▼延伸阅读 由面试题“Redis是否为单线程”引发的思考 作者:李乐 来源:IT阅读…

【MySQL】数据管理——DML操作数据

目录 DML(数据操作语言)添加数据插入单行语法插入多行语法SQL示例将查询结果插入到新表中语法1:语法2: 修改数据语法示例关于SQL的运算符算术运算符比较运算符逻辑运算符 案例 删除数据DELETE命令语法 TRUNCATE TABLE 命令语法代码…

数据卷(Data Volumes)自定义镜像(Dockerfile)

目录 一.数据卷(Data Volumes) 二.自定义镜像(Dockerfile) 自定义centos 一.数据卷(Data Volumes) 数据卷(Data Volumes)是一个可供一个或多个容器使用的特殊目录,它将主机操作系统目录直接映射进容器,它可以提供很多有用的特性: 1.数据卷…

[DEBUG] spring boot-如何处理链接中的空格等特殊字符

问题&#xff1a; get或者post中提交的内容可能有空格、#等特殊字符&#xff0c;不做处理的话可能解析错误。 解决&#xff1a; html中&#xff1a; <a th:href"{/listSgrna(id${item.getGeneId()},geneName${item.getGeneName()},genome${genome},sgrnaNum${sgrnaN…

Java开发的核心模式 - MVC

文章目录 1、MVC设计模式2、Web开发本质3、服务器的性能瓶颈 1、MVC设计模式 MVC设计模式示意图 在整个Java学习之旅中&#xff0c;MVC&#xff08;Model-View-Controller&#xff09;设计模式无疑占据着极其重要的地位&#xff0c;堪称理解和掌握Java项目开发精髓的钥匙。如…

2024最新Android面试题目,【设计思想解读开源框架】

前言 从18年毕业至今&#xff0c;就职过两家公司&#xff0c;大大小小项目做了几个&#xff0c;非常感谢我的两位老大&#xff0c;在我的android成长路上给予我很多指导&#xff0c;亦师亦友的关系。 从年前至今参加面试了很多公司&#xff0c;也收到了几家巨头的offer&#…

【React架构 - Scheduler中的MessageChannel】

前序 我们都知道JS代码是在浏览器5个进程(下面有介绍)中渲染进程中的Js引擎线程执行的&#xff0c;其他还有GUI渲染线程、定时器线程等&#xff0c;而页面的布局和绘制是在GUI线程中完成的&#xff0c;这些线程之间是互斥的&#xff0c;所以在执行Js的同时会阻塞页面的渲染绘制…

Python实现向量自回归模型(VAR算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 向量自回归模型&#xff08;Vector Autoregression&#xff0c;简称VAR&#xff09;是一种多元时间序列…

国内 永远不会倒闭的四个行业

据教育部公布的数据&#xff0c;2024届高校毕业生人数预计将达到1187万人&#xff0c;较2023年增加29万&#xff0c;再创历史新高。 同时&#xff0c;受全球经济形势的影响&#xff0c;一些行业和领域的就业形势并不乐观&#xff0c;比如房地产、传统零售业、传统金融业、低技能…

Python 从文件中读取JSON 数据并解析转存

文章目录 文章开篇Json简介Json数据类型Json硬性规则Json数据转化网站Json和Dict类型转换json模块的使用Python数据和Json数据的类型映射json.dumps1.字典数据中含有**存在中文**2.json数据通过缩进符**美观输出**3.对Python数据类型中键进行**排序输出**4.json数据**分隔符的控…

Rocky Linux 运维工具 tar

一、tar的简介 tar​命令是Linux操作系统中用于打包和解压文件的工具。通过 ​tar​可以将多个文件或目录打包成一个归档文件&#xff0c;也可以解压这些归档文件。 二、tar的参数说明 -c 用于将指定的文件或目录打包成一个归档文件&#xff0c;即压缩归档文件 -f 用于指定归档…

Kubernetes activemq系列| k8s 部署activemq artemis

一、ActiveMQ Artemis介绍 Apache ActiveMQ Artemis 是一个高性能的开源消息代理,它完全符合 Java Message Service (JMS) 2.0 规范,并支持多种通信协议,包括 AMQP、MQTT、STOMP 和 OpenWire 等。ActiveMQ Artemis 由 Apache Software Foundation 开发和维护,旨在提供可靠…

select * from 表 c=‘1‘ and b=‘2‘ and a=‘3‘; abc是联合索引,这样查询会命中索引吗?

倒叙也会命中索引 但是要注意&#xff0c;倒叙的时候必须要有a存在&#xff0c;否则就会索引失效 因为mysql底层会有优化器去进行优化&#xff0c;但是如果没有a的话&#xff0c;那么优化器就不知道要优化那个索引了&#xff0c;所以他走了全表&#xff0c;导致索引失效

小程序实现定位城市切换且城市根据首字母A-Z排序后端数据实现逻辑

场景&#xff1a; 话不多说后端提供数据实现步骤&#xff1a; 1.controller层 Api(tags {"[地区]-城市相关接口"}) RestController RequestMapping("region") Slf4j public class RegionController extends BaseController {Resourceprivate RegionServ…

车载电子电器架构 —— 基础技术开发概述

车载电子电器架构 —— 基础技术开发概述 我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消耗…

【数据结构】单链表解析+完整代码(插入、删除、尾插法、头插法、按值和按位查找、前插和后插)带头结点和不带两种实现

文章目录 3.1 单链表3.1.1 单链表的定义3.1.2 单链表的插入A.按位序插入&#xff08;带头结点&#xff09;B.按位序插入&#xff08;不带头结点&#xff09;C.指定结点的后插操作D.指定结点的前插操作 3.1.3 单链表的删除A.按位序删除B.删除指定结点 3.1.4 单链表的查找A.按位查…

jetson nano——编译安装opencv-python==4.3.0.38

目录 1.下载源码&#xff0c;我提供的链接如下&#xff1a;2.解压文件3.安装依赖scikit4.安装opencv-python5.查看opencv-python版本 系统&#xff1a;jetson-nano-jp451-sd-card-image ubuntu 18.04 1.下载源码&#xff0c;我提供的链接如下&#xff1a; 链接&#xff1a;http…

使用 OpenCV 通过 SIFT 算法进行对象跟踪

本文介绍如何使用 SIFT 算法跟踪对象 在当今世界&#xff0c;当涉及到对象检测和跟踪时&#xff0c;深度学习模型是最常用的&#xff0c;但有时传统的计算机视觉技术也可能有效。在本文中&#xff0c;我将尝试使用 SIFT 算法创建一个对象跟踪器。 为什么人们会选择使用传统的计…

如何对比 MySQL 主备数据的一致性?

随着业务范围的扩大&#xff0c;很多企业为了保障核心业务的高可用性&#xff0c;选择了 MySQL 主从架构&#xff0c;这一套方案通常具备主备数据同步、数据备份与恢复、读写分离、高可用切换等特性&#xff0c;是一种相当成熟可靠的数据库架构方案。然而这套方案在特定情况下可…

数电学习笔记——逻辑代数的基本定理

目录 一、带入定理 二、反演定理 三、对偶定理 一、带入定理 在任何一个包含变量A的逻辑等式中&#xff0c;若以另外一个逻辑式代入式中所有A的位置&#xff0c;则等式仍然成立。 例1&#xff1a;&#xff08;AB&#xff09;AB 将&#xff08;BC&#xff09;带入等式中所…