【点云处理教程】05-Python 中的点云分割
一、说明
这是我的“点云处理”教程的第 5 篇文章。“点云处理”教程对初学者友好,我们将在其中简单地介绍从数据准备到数据分割和分类的点云处理管道。
在上一教程中,我们看到了如何过滤点云以减少噪声或其密度。在本教程中,我们将应用一些聚类算法进行点云分割,即:K-means和DBSCAN。
【点云处理教程】00计算机视觉的Open3D简介
【点云处理教程】01如何创建和可视化点云
【点云处理教程】02从 Python 中的深度图像估计点云
【点云处理教程】03使用 Python 实现地面检测
【点云处理教程】04 Python 中的点云过滤
【点云处理教程】05-Python 中的点云分割
二、 简介
通常,数据分割旨在将数据重新分组为非重叠组。在点云分割中,这些组可能对应于区域:对象或其一部分、表面、平面等。点云分割方法可分为 3 大类:基于区域增长的方法、基于模型拟合的方法和基于聚类的方法。在本教程中,我们对基于聚类的方法感兴趣。聚类算法在许多机器学习API中实现,包括我们将在本教程中使用的Scikit-learn。
在引入一些聚类分析算法之前,请务必记住一些模型属性:
- 可扩展性。算法的可扩展性是它能够很好地处理大规模数据。关于聚类算法,它们的可扩展性取决于样本的数量(点云的点数)和聚类的数量。例如,K 均值和 DBSCAN 不能在大量集群中保持可伸缩性。
- 指标。为了创建样本组,聚类分析算法需要计算定义的指标,以查找同一组的点之间的相似性以及其他组的点之间的相似性。例如,K 均值计算点之间的距离,而 DBSCAN 计算最近点之间的距离。
- 运行。运行时间很重要,尤其是在实时应用程序中。它不仅取决于样本数量和组的数量,还取决于算法和计算指标。
- 超参数。该算法的超参数是一个需要考虑的非常重要的属性,尤其是组的数量。在许多应用程序中,集群的数量事先并不知道,因此固定组的数量可能会导致以后过程中的冲突。
- 行为。我认为重要的另一个重要因素是模型是确定性的还是随机的。确定性行为意味着算法每次执行都提供相同的输出,不涉及随机性。在这种情况下,聚类分析算法每次都会针对具有相同配置的相同点云返回具有相同点的相同聚类。相反,随机行为为具有相同配置的相同输入生成不同的输出;它具有一定的随机性。选择确定性模型还是随机模型取决于其应用。
这些是一些重要的属性,有关更多详细信息,您可以访问此链接。说够了,让我们开始练习吧!我们首先导入所需的库和我们的点云:
import numpy as np
import open3d as o3d
from sklearn.cluster import KMeans, DBSCAN, OPTICS
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler# Read point cloud:
pcd = o3d.io.read_point_cloud("../data/depth_2_pcd_downsampled.ply")
# Get points and transform it to a numpy array:
points = np.asarray(pcd.points).copy() 为了可视化计算的群集,在调用该方法后添加了以下行:fit()
# Get labels:
labels = model.labels_
# Get the number of colors:
n_clusters = len(set(labels))# Mapping the labels classes to a color map:
colors = plt.get_cmap("tab20")(labels / (n_clusters if n_clusters > 0 else 1))
# Attribute to noise the black color:
colors[labels < 0] = 0
# Update points colors:
pcd.colors = o3d.utility.Vector3dVector(colors[:, :3])# Display:
o3d.visualization.draw_geometries([pcd]) 三、K均值
K-means是一种基于质心的算法。它将输入样本分成 K 个具有相等方差的独立组,同时最小化点之间的距离。
K 均值需要聚类数作为输入参数。可以将其他超参数设置为质心初始化的参数。修复此参数可使算法具有确定性。您可以在此处找到有关参数的更多信息。n_clustersrandom_state
为了分割点云,我们首先对点进行归一化,然后拟合。这里我们设置为 4。n_clusters
# Normalisation:
scaled_points = StandardScaler().fit_transform(points)
# Clustering:
model = KMeans(n_clusters=4)
model.fit(scaled_points) K 均值将输入点云分割为 4 个聚类:将墙分割成 3 组,其余点重新分组为单个聚类。

这可能对某些应用程序有好处,但对其他应用程序则不然。在我们的例子中,我们想要墙作为一个整体,椅子,等等。换句话说,我们希望将它们分组到一个由非密集区域隔开的密集区域中。
四、数据库扫描
DBSCAN算法旨在将样本分离为具有低密度区域的高密度簇。不必事先定义聚类数。DBSCAN对噪声具有鲁棒性:在聚类过程中,异常值被检测并忽略,因此聚类过程不受它们的影响。
DBSCAN 需要两个超参数:分别表示形成聚类的最小点数和用于定位相邻要素的距离测量值。您可以在此处找到有关DBSCAN的更多信息。min_sampleseps
为了分割点云,我们首先对点进行归一化,然后拟合。在这里,我们设置为 10 点和 0.15。min_sampleseps
# Normalisation:
scaled_points = StandardScaler().fit_transform(points)
# Clustering:
model = DBSCAN(eps=0.15, min_samples=10)
model.fit(scaled_points) 对于固定参数,DBSCAN将输入点云分成8个簇:墙被分割成4组,椅子被分成2组,桌子被分割成一组。这是由于传感器的性质:噪声产生了一些间隙。

五、投影点云
正如我们从前面的例子中看到的,墙和椅子上的一些部分是分开重新组合的。这没关系,但是,如果我们只对地面上占用的空间感兴趣怎么办?例如,找到自由行走的空间。
在这种情况下,我们不关心高度,就像我们关心地面上的被占领区域一样。因此,我们可以将所有点投影到地平面上。这样,所有点将具有相同的高度(y 坐标),这不会影响聚类。在地平面上投影点云需要估计地平面方程,然后找到投影矩阵。我知道,这有很多工作要做!但是,如果我们只忽略 y 坐标呢?后者甚至会减少运行时间,因为在聚类过程中只考虑两个属性!
让我们尝试一下,从可视化投影点云开始。这里所有点都投影在平面 OXZ (y=0) 上:
# Project points on OXZ plane:
points[:, 1] = 0
pcd_projected = o3d.geometry.PointCloud() # create point cloud object
pcd_projected.points = o3d.utility.Vector3dVector(points) # set pcd_np as the point cloud points
o3d.visualization.draw_geometries([pcd_projected]) 
在平面 OXZ 上投影点云。
现在,我们可以分割投影点云。请注意,为此,我们只考虑 x 和 z 坐标:
# projection: caonsider the x and z coordinates (y=0)
points_xz = points[:, [0, 2]]# Normalisation:
scaled_points = StandardScaler().fit_transform(points_xz)# Clustering:
model = DBSCAN(eps=0.15, min_samples=10)
model.fit(scaled_points) 投影点云上的分割如下图所示:

或者在原始点云上:

通过投影,我们可以看到点云根据占用的空间进行分割,这对于许多应用程序来说更好。但是,对于其他应用程序,这可能不像精细分割那样工作,或者当有物体最初不在地面上时,例如投射路过的鸟!
六、结论
在本教程中,我们学习了如何使用 K 均值和 DBSCAN 分割点云。聚类算法的挑战是设置良好的超参数,这对于实际应用程序并不明显。作为练习,您可以针对不同的超参数值测试这些算法,也可以测试Scikit-learn提供的其他聚类算法。
谢谢,我希望你喜欢阅读这篇文章。您可以在我的 GitHub 存储库中找到示例。如果您有任何问题或建议,请随时在下面给我留言。
相关文章:
【点云处理教程】05-Python 中的点云分割
一、说明 这是我的“点云处理”教程的第 5 篇文章。“点云处理”教程对初学者友好,我们将在其中简单地介绍从数据准备到数据分割和分类的点云处理管道。 在上一教程中,我们看到了如何过滤点云以减少噪声或其密度。在本教程中,我们将应用一些聚…...
代码随想录算法训练营之JAVA|第十七天| 654. 最大二叉树
今天是第17天刷leetcode,立个flag,打卡60天。 算法挑战链接 654. 最大二叉树https://leetcode.cn/problems/maximum-binary-tree/description/ 第一想法 错误的想法,就不说了。 看完代码随想录之后的想法 用递归模拟真实的过程 如果我…...
C++重写函数、隐藏函数、重载函数的区别对比
目录 1.函数重载 1.1定义 1.2函数重载的规则: 1.3函数重载的作用: 2.函数重写: 2.1定义 2.2例子: 3.函数隐藏 3.1定义 3.2举个例子: 1.函数重载 1.1定义 我们在学类和对象的封装特性时学过一个词叫重载,…...
15.python设计模式【函数工厂模式】
1.知识讲解 内容:定义一个字典,在python中一切皆对象,将所有的函数进行封装,然后定一个分发函数进行分发,将原来if…else全部干掉。角色: 函数(function)函数工厂(funct…...
Redis主从复制、哨兵、cluster集群原理+实验
目录 一、Redis 主从复制 1、主从复制的作用 2、主从复制流程 3、搭建Redis 主从复制 安装Redis(所有主机) 修改Master节点Redis配置文件 修改Slave节点Redis配置文件 验证主从效果 一、Redis 主从复制 主从复制,是指将一台Redis服务器的数据&am…...
微信小程序如何实现页面传参?
前言 只要你的小程序超过一个页面那么可能会需要涉及到页面参数的传递,下面我总结了 4 种页面方法。 路径传递 通过在url后面拼接参数,参数与路径之间使用 ? 分隔,参数键与参数值用 相连,不同参数用 & 分隔;如…...
OPC DA 客户端与服务器的那点事
C#开发OPC客户端,使用OPCDAAuto.dll。在开发过程中偶遇小坎坷,主要记录一下问题解决办法。 1、建立客户端,参考链接。建立WinFrom工程,将博客中代码全部复制即可运行: https://www.cnblogs.com/kjgagaga/p/17011730.…...
Java 错误异常介绍(Exceptions)
1、异常介绍 异常是程序执行期间发生的意外事件。它影响程序指令流,从而导致程序异常终止。 发生异常的原因有很多。其中包括: 无效的用户输入 设备故障 网络连接丢失 物理限制(磁盘内存不足) 代码错误 打开一个不可用的文…...
每日一题——旋转数组的最小数字
题目 有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这…...
SpringBoot Jackson 日期格式化统一配置
目录 1.在全局配置文件配置 2.通过JavaBean方式配置 1.在全局配置文件配置 spring:jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT8 该配置方式仅支持 Date 类型的日期格式化,不支持LocalDate 及 LocalDateTime 的格式化。 2.通过JavaBean方式配置 …...
剑指 Offer 38. 字符串的排列 / LeetCode 47. 全排列 II(回溯法)
题目: 链接:剑指 Offer 38. 字符串的排列 难度:中等 输入一个字符串,打印出该字符串中字符的所有排列。 你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。 示例: 输入:s “abc” 输出&…...
【前端知识】React 基础巩固(四十三)——Effect Hook
React 基础巩固(四十三)——Effect Hook 一、Effect Hook的基本使用 Effect Hook 用来完成一些类似class中生命周期的功能。 在使用类组件时,不管是渲染、网路请求还是操作DOM,其逻辑和代码是杂糅在一起的。例如我们希望把计数器结果显示在标签上&…...
一百三十八、ClickHouse——使用clickhouse-backup备份ClickHouse库表
一、目标 使用clickhouse-backup在本地全库备份ClickHouse的数据库 二、前提 已经安装好clickhouse-backup 注意:由于之前同事已经按照好clickhouse-backup,所以我就没有安装 如有需要请参考其他人的博客安装一下,下面是我认为比较好的一…...
【无标题】使用Debate Dynamics在知识图谱上进行推理(2020)7.31
使用Debate Dynamics在知识图谱上进行推理 摘要介绍背景与相关工作我们的方法 摘要 我们提出了一种新的基于 Debate Dynamics 的知识图谱自动推理方法。 其主要思想是将三重分类任务定义为两个强化学习主体之间的辩论游戏,这两个主体提取论点(知识图中…...
windows下若依vue项目部署
下载若依项目,前端后端项目本地启动前端打包,后端打包配置nginx.conf 需要注意的是:路径别用中文,要不然报错 #前台访问地址及端口80,在vue.config.js中可查看server {listen 80;server_name localhost; #后台…...
【目标检测】基于yolov5的水下垃圾检测(附代码和数据集,7684张图片)
写在前面: 首先感谢兄弟们的订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 路虽远,行则将至;事虽难,做则必成。只要有愚公移山的志气、滴水穿石的毅力,脚踏实地,埋头苦干,积跬步以至千里,就…...
P1734 最大约数和
题目描述 选取和不超过 S 的若干个不同的正整数,使得所有数的约数(不含它本身)之和最大。 输入格式 输入一个正整数 S。 输出格式 输出最大的约数之和。 输入输出样例 输入 11 输出 9 说明/提示 【样例说明】 取数字 4 和 6&a…...
Excel将单元格中的json本文格式化
打开Excel文件并按下ALT F11打开Visual Basic for Applications(VBA)编辑器。 输入下面的代码 Sub FormatJSONCells()Dim cell As RangeDim jsonString As StringDim json As ObjectDim formattedJSON As String 循环遍历选定的单元格范围For Each ce…...
Baumer工业相机堡盟工业相机如何通过BGAPI SDK获取相机当前实时帧率(C#)
Baumer工业相机堡盟工业相机如何通过BGAPISDK里函数来计算相机的实时帧率(C#) Baumer工业相机Baumer工业相机的帧率的技术背景Baumer工业相机的帧率获取方式CameraExplorer如何查看相机帧率信息在BGAPI SDK里通过函数获取相机帧率 Baumer工业相机通过BGA…...
XGBoost的基础思想与实现
目录 1. XGBoost VS 梯度提升树 1.1 XGBoost实现精确性与复杂度之间的平衡 1.2 XGBoost极大程度地降低模型复杂度、提升模型运行效率 1.3 保留了部分与梯度提升树类似的属性 2. XGBoost回归的sklearnAPI实现 2.1 sklearn API 实现回归 2.2 sklearn API 实现分类 3. XGBo…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
