常用的点云预处理算法

点云预处理是处理点云数据时的重要部分,其目的是提高点云数据的质量和处理效率。通过去除离群点、减少点云密度和增强特征,可以消除噪声、减少计算量、提高算法的准确性和鲁棒性,从而为后续的点云处理和分析步骤(如配准、分割和重建)提供更高质量的数据基础。

以下是常用的点云预处理算法介绍,内容包括离群点过滤、点云下采样、坐标上采样和特征上采样的数学原理以及Open3D实现代码。

离群点过滤

无效值剔除

无效值剔除是指移除点云中的值或无穷大的值。

数学原理: 假设点云数据集为,其中每个点。无效值剔除的规则可以表示为:

Open3D实现

import open3d as o3ddef remove_invalid_points(pcd):pcd = pcd.select_by_index(np.where(np.isfinite(np.asarray(pcd.points)).all(axis=1))[0])return pcd# 示例
pcd = o3d.io.read_point_cloud("example.ply")
pcd = remove_invalid_points(pcd)
o3d.visualization.draw_geometries([pcd])
统计方法剔除

统计方法剔除利用每个点的邻域统计信息来识别并移除离群点。

数学原理: 计算每个点到其个最近邻点的平均距离,并将该点的平均距离与全局平均距离进行比较。如果某点的平均距离超出某一阈值,则认为该点为离群点。

Open3D实现

def statistical_outlier_removal(pcd, nb_neighbors=20, std_ratio=2.0):cl, ind = pcd.remove_statistical_outlier(nb_neighbors=nb_neighbors, std_ratio=std_ratio)pcd = pcd.select_by_index(ind)return pcd# 示例
pcd = o3d.io.read_point_cloud("example.ply")
pcd = statistical_outlier_removal(pcd)
o3d.visualization.draw_geometries([pcd])
半径滤波方法剔除

半径滤波方法根据每个点在指定半径内的邻居数量来剔除离群点。

数学原理: 设定一个半径和最小点数阈值。对于每个点,如果其在半径内的邻居数量少于,则认为该点为离群点。

Open3D实现

def radius_outlier_removal(pcd, radius=0.05, min_points=5):cl, ind = pcd.remove_radius_outlier(nb_points=min_points, radius=radius)pcd = pcd.select_by_index(ind)return pcd# 示例
pcd = o3d.io.read_point_cloud("example.ply")
pcd = radius_outlier_removal(pcd)
o3d.visualization.draw_geometries([pcd])

离群点剔除代码示例:

import open3d as o3d
from copy import deepcopy
import numpy as npif __name__ == '__main__':file_path = 'rabbit.pcd'pcd = o3d.io.read_point_cloud(file_path)pcd = pcd.uniform_down_sample(50)#每50个点采样一次pcd.paint_uniform_color([0.5, 0.5, 0.5])#指定显示为灰色print(pcd)#剔除无效值pcd1 = deepcopy(pcd)pcd1.paint_uniform_color([0, 0, 1])#指定显示为蓝色pcd1.translate((20, 0, 0)) #整体进行x轴方向平移pcd1 = pcd1.remove_non_finite_points(True, True)#剔除无效值print(pcd1)#统计方法剔除pcd2 = deepcopy(pcd)pcd2.paint_uniform_color([0, 1, 0])#指定显示为蓝色pcd2.translate((-20, 0, 0)) #整体进行x轴方向平移res = pcd2.remove_statistical_outlier(20, 0.5)#统计方法剔除pcd2 = res[0]#返回点云,和点云索引print(pcd2)#半径方法剔除pcd3 = deepcopy(pcd)pcd3.paint_uniform_color([1, 0, 0])#指定显示为蓝色pcd3.translate((0, 20, 0)) #整体进行y轴方向平移res = pcd3.remove_radius_outlier(nb_points=20, radius=2)#半径方法剔除pcd3 = res[0]#返回点云,和点云索引print(pcd3)# # 点云显示o3d.visualization.draw_geometries([pcd, pcd1, pcd2, pcd3], #点云列表window_name="离群点剔除",point_show_normal=False,width=800,  # 窗口宽度height=600)  # 窗口高度

图片

点云下采样

点云下采样的主要目的是减少点云数据的规模,从而降低计算复杂度和存储需求。在实际应用中,点云数据通常包含大量的点,这会占用大量的存储空间并增加处理时间。通过下采样,可以去除冗余点,只保留关键点,既能加速后续处理(如配准、分类、分割等),又能减少内存使用。此外,下采样还能提高算法的鲁棒性,减少噪声影响,使得处理结果更加稳定和可靠。

体素下采样

体素下采样通过将点云划分为固定大小的三维网格,并用每个网格中的点的质心来代表该网格中的所有点。

数学原理: 设定体素网格的大小为,将点云划分为体素网格,每个体素中的点用其质心替代。

其中,为体素的质心,为体素中的点数。

Open3D实现

import open3d as o3d
from copy import deepcopyif __name__ == '__main__':file_path = 'rabbit.pcd'pcd = o3d.io.read_point_cloud(file_path)pcd.paint_uniform_color([0.5, 0.5, 0.5])#指定显示为灰色print(pcd)pcd1 = deepcopy(pcd)pcd1.paint_uniform_color([0, 0, 1])#指定显示为蓝色pcd1.translate((20, 0, 0)) #整体进行x轴方向平移pcd1 = pcd1.voxel_down_sample(voxel_size=1)print(pcd1)pcd2 = deepcopy(pcd)pcd2.paint_uniform_color([0, 1, 0])#指定显示为绿色pcd2.translate((0, 20, 0)) #整体进行y轴方向平移res = pcd2.voxel_down_sample_and_trace(1, min_bound=pcd2.get_min_bound()-0.5, max_bound=pcd2.get_max_bound()+0.5, approximate_class=True)pcd2 = res[0]print(pcd2)# 点云显示o3d.visualization.draw_geometries([pcd, pcd1, pcd2], #点云列表window_name="体素下采样",point_show_normal=False,width=800,  # 窗口宽度height=600)  # 窗口高度

图片

随机下采样

随机下采样是从点云中随机选取一定比例的点,以减少点云的点数。

数学原理: 设点云数据集为,随机下采样从中选取个点。其中,是从中随机选取的索引。

Open3D实现

import open3d as o3d
from copy import deepcopy
import numpy as npif __name__ == '__main__':file_path = 'rabbit.pcd'pcd = o3d.io.read_point_cloud(file_path)pcd.paint_uniform_color([0.5, 0.5, 0.5])#指定显示为灰色print(pcd)pcd1 = deepcopy(pcd)pcd1.paint_uniform_color([0, 0, 1])#指定显示为蓝色pcd1.translate((20, 0, 0)) #整体进行x轴方向平移pcd1 = pcd1.uniform_down_sample(100)#每100个点采样一次print(pcd1)pcd2 = deepcopy(pcd)pcd2.paint_uniform_color([0, 1, 0])#指定显示为绿色pcd2.translate((0, 20, 0)) #整体进行y轴方向平移pcd2 = pcd2.random_down_sample(0.1)#采1/10的点云print(pcd2)#自定义随机采样pcd3 = deepcopy(pcd)pcd3.translate((-20, 0, 0)) #整体进行x轴方向平移points = np.array(pcd3.points)n = np.random.choice(len(points), 500, replace=False) #s随机采500个数据,这种随机方式也可以自己定义pcd3.points = o3d.utility.Vector3dVector(points[n])pcd3.paint_uniform_color([1, 0, 0])#指定显示为红色print(pcd3)# # 点云显示o3d.visualization.draw_geometries([pcd, pcd1, pcd2, pcd3], #点云列表

图片

均匀下采样

均匀下采样是等间距选择点云中的点。

数学原理: 设点云数据集为,均匀下采样每隔个点选择一个点。

Open3D实现

def uniform_downsample(pcd, every_k_points=10):pcd = pcd.uniform_down_sample(every_k_points)return pcd# 示例
pcd = o3d.io.read_point_cloud("example.ply")
pcd = uniform_downsample(pcd)
o3d.visualization.draw_geometries([pcd])
最远点采样

最远点采样是一种迭代方法,每次选择距离当前已选点集最远的点。

数学原理: 初始化点集为随机选择的一个点,每次迭代选择距离当前已选点集最远的点:

Open3D实现

import open3d as o3d
from copy import deepcopy
import numpy as npdef farthest_point_sample(point, npoint):"""Input:xyz: pointcloud data, [N, D]npoint: number of samplesReturn:centroids: sampled pointcloud index, [npoint, D]"""N, D = point.shapexyz = point[:,:3]centroids = np.zeros((npoint,))distance = np.ones((N,)) * 1e10farthest = np.random.randint(0, N)for i in range(npoint):centroids[i] = farthestcentroid = xyz[farthest, :]dist = np.sum((xyz - centroid) ** 2, -1)mask = dist < distancedistance[mask] = dist[mask]farthest = np.argmax(distance, -1)point = point[centroids.astype(np.int32)]return pointif __name__ == '__main__':file_path = 'rabbit.pcd'pcd = o3d.io.read_point_cloud(file_path)pcd.paint_uniform_color([0.5, 0.5, 0.5])#指定显示为灰色print(pcd)pcd1 = deepcopy(pcd)pcd1.translate((20, 0, 0)) #整体进行x轴方向平移points = np.array(pcd1.points)points = farthest_point_sample(points, 500)pcd1 = o3d.geometry.PointCloud()pcd1.points = o3d.utility.Vector3dVector(points)pcd1.paint_uniform_color([0, 0, 1])#指定显示为蓝色print(pcd1)# # 点云显示o3d.visualization.draw_geometries([pcd, pcd1], #点云列表window_name="最远点采样",point_show_normal=False,width=800,  # 窗口宽度height=600)  # 窗口高度

图片

坐标上采样

点云上采样的目的是增加点云的密度,以提高其分辨率和细节表现。在许多应用中,特别是三维重建和表面细化时,原始点云的分辨率可能不足,导致重建结果不够精细或存在明显的缺陷。通过上采样,可以插值生成更多的点,使得点云更密集,从而更好地捕捉物体的几何细节,提升最终的三维模型质量。这对于需要高精度、高分辨率数据的任务(如精细的表面重建、细节检测等)尤为重要。

插值法

插值法是通过插值计算新增点的坐标。

数学原理: 常用的插值方法包括线性插值、双线性插值、三次样条插值等。以线性插值为例,两个点和之间新增点:

其中,为插值系数,取值范围为[0, 1]。

Open3D实现

import open3d as o3d
from copy import deepcopyif __name__ == '__main__':file_path = 'rabbit.pcd'pcd = o3d.io.read_point_cloud(file_path)pcd.paint_uniform_color([0.5, 0.5, 0.5])  # 指定显示为灰色print(pcd)pcd1 = deepcopy(pcd)pcd1.paint_uniform_color([0, 0, 1])  # 指定显示为蓝色pcd1.translate((20, 0, 0))  # 整体进行x轴方向平移pcd1 = pcd1.voxel_down_sample(voxel_size=1)print(pcd1)mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(pcd1, alpha=2)pcd2 = mesh.sample_points_poisson_disk(number_of_points=3000, init_factor=5)pcd2.paint_uniform_color([0, 1, 0])  # 指定显示为绿色pcd2.translate((-40, 0, 0))  # 整体进行x轴方向平移print(pcd2)o3d.visualization.draw_geometries([pcd, pcd1, pcd2],  # 点云列表window_name="点云上采样",point_show_normal=False,width=800,  # 窗口宽度height=600)  # 窗口高度

图片

特征上采样

最近邻插值

最近邻插值是通过选择最近邻的特征值作为新增点的特征值。

数学原理: 设已知点云的特征为,新增点的特征值通过最近邻点的特征值确定:,其中,为距离最近的点。

Open3D实现

from sklearn.neighbors import NearestNeighborsdef nearest_neighbor_interpolation(pcd, features, num_points):points = np.asarray(pcd.points)new_points = np.array([]).reshape(0, 3)new_features = np.array([]).reshape(0, features.shape[1])for i in range(len(points) - 1):for t in np.linspace(0, 1, num_points):new_point = points[i] + t * (points[i + 1] - points[i])new_points = np.vstack((new_points, new_point))nn = NearestNeighbors(n_neighbors=1).fit(points)distances, indices = nn.kneighbors(new_points)new_features = features[indices.flatten()]pcd_interpolated = o3d.geometry.PointCloud()pcd_interpolated.points = o3d.utility.Vector3dVector(new_points)return pcd_interpolated, new_features# 示例
pcd = o3d.io.read_point_cloud("example.ply")
features = np.random.rand(len(pcd.points), 3)  # 假设特征是随机生成的
pcd, new_features = nearest_neighbor_interpolation(pcd, features, num_points=10)
o3d.visualization.draw_geometries([pcd])

以上内容总结自网络,如有帮助欢迎关注与转发,我们下次再见!

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

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

相关文章

三大知名向量化模型比较分析——m3e,bge,bce

先聊聊出处。 M3E 是 Moka Massive Mixed Embedding 的缩写&#xff0c; Moka&#xff0c;此模型由 MokaAI 训练&#xff0c;开源和评测&#xff0c;训练脚本使用 uniem &#xff0c;评测 BenchMark 使用 MTEB-zhMassive&#xff0c;此模型通过千万级 (2200w) 的中文句对数据…

智慧电子班牌系统,智慧班牌源码,为校园提供了便捷、高效、智能的信息管理和服务方式

智慧班牌在实现智慧校园的数字化建设中扮演着重要角色&#xff0c;它通过集成多种技术和功能&#xff0c;为校园提供了便捷、高效、智能的信息管理和服务方式。以下是智慧班牌如何实现智慧校园的数字化建设的具体方式&#xff1a; 一、信息集成与展示 基础信息展示&#xff1a…

海外媒体发稿:葡萄牙-实现高效媒体软文发稿计划-大舍传媒

一、葡萄牙媒体环境概述 葡萄牙&#xff0c;位于欧洲大陆西南端的国家&#xff0c;拥有丰富的文化和历史。在这个国家&#xff0c;媒体行业也有着相当大的影响力。葡萄牙的媒体环境多元化&#xff0c;包括电视、广播、报纸、杂志和互联网等各个领域。 二、葡萄牙媒体发稿的重…

如何恢复电脑上删除的文件?快速恢复被删除文件的技巧【5个实用方法】

如何恢复电脑上删除的文件&#xff1f;电脑误删文件的情况很经常发生&#xff0c;删除文件后第一时间可以按下组合键CtrlZ撤销&#xff0c;这样能挽回99%以上的文件。当然&#xff0c;如果已经彻底删除&#xff0c;那么可以了解下本文整理的方法找回。 &#xff08;一&#xff…

【计算机网络】学习指南及导论

个人主页&#xff1a;【&#x1f60a;个人主页】 系列专栏&#xff1a;【❤️计算机网络】 文章目录 前言我们为什么要学计算机网络&#xff1f;计算机网络概述计算机网络的分类按交换技术分类按使用者分类按传输介质分类按覆盖网络分类按覆盖网络分类 局域网的连接方式有线连接…

【HarmonyOS学习】动画

页面分类动画 显示动画 function animateTo(value: AnimateParam, event: () > void): void;代码如下&#xff1a;&#xff08;实现属性变化引发的动画&#xff09; Entry Component struct Animate_Page1 {State boxWidth: number 100;State boxHeight: number 100;Sta…

第一节Linux常见指令

目录 1.Linux下基本指令 ls指令 pwd 命令 cd 指令 知识点:理解树形结构 touch 指令 mkdir指令(重要) rmdir指令 && rm指令(重要) 知识点:ls file* 可以找到当前目录下任何以file开头的文件​编辑 知识点:热键 man指令()重要 补充知识点:nano cp…

前端程序员应该往全栈方向发展吗?还是坚守前端?

作者&#xff1a;寒蝉&#xff08;知乎&#xff09; 顺便吆喝一声&#xff0c;技术大厂&#xff0c;内推捞人&#xff0c;前/后端or测试←感兴趣 要求学历&#xff1a;全日制统招本科&#xff08;非学院派即可&#xff09;&#xff1a; --加班偶尔较多&#xff0c;但周末加班两…

Android NDK开发之震动服务客户端编写程序(C++)

一、背景 最近有个小伙伴问我可不可以写一个可执行程序(C/C) 来实现Android设备的震动的功能。 作为一个多年的Android开发者&#xff0c;我觉得这是可以实现的。 但是由于过去我一直做App开发&#xff0c;也就把这个实现过程想简单了。 经过了几天的折腾&#xff0c;终于算是…

港股指数实时行情API接口

港股 指数 实时 行情 API接口 # Restful API https://tsanghi.com/api/fin/index/HKG/realtime?token{token}&ticker{ticker}指定指数代码&#xff0c;获取该指数的实时行情&#xff08;开、高、低、收、量&#xff09;。 更新周期&#xff1a;实时。 请求方式&#xff1a…

vue router 切换路由的时候,页面的动画效果,使页面切换好看,以及控制有的页面使用切换路由特效,有的页面不用

一、使用切换效果 在router文件中 useTransition: true代表需要动画 meta: { title: “新开卡预填表单”, keepAlive: true, useTransition: true }, [{path: "/",name: "Home",meta: {title: "首页",keepAlive: true,useTransition: false},c…

给你的博客添加数据统计功能

20.数据统计 我们可以给博客添加统计功能&#xff0c;这里以百度统计和谷歌统计为例。 ‍ 百度统计 ‍ 添加网站 登陆百度统计后台&#xff1a;百度统计——一站式智能数据分析与应用平台&#xff0c;并登录&#xff0c;然后进入产品&#xff1a; ‍ 在使用设置–网站列…

图解KMP算法,带你彻底吃透KMP

模式串匹配——KMP算法 KMP算法一直是一个比较难以理解的算法&#xff0c;本篇文章主要根据《大话数据结构》中关于KMP算法的讲解&#xff0c;结合自己的思考&#xff0c;对于KMP算法进行一个比较详细的解释。 由于博主本人水平有限&#xff0c;难免会出现一些错误。如果发现…

C语言课程回顾:十、C语言之 指针

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 C语言之 指针 10 指针10.1 地址指针的基本概念10.2 变量的指针和指向变量的指针变量10.2.1 定义一个指针变量10.2.2 指针变量的引用10.2.3 指针变量作为函数参数10.2.4 指针变…

电脑远程开关机

1. 远程开机 参考&#xff1a;https://post.smzdm.com/p/664774/ 1.1 Wake On LAN - 局域网唤醒&#xff08;需要主板支持&#xff0c;一般都支持&#xff09; 要使用远程唤醒&#xff0c;有几种方式&#xff1a;使用类似向日葵开机棒&#xff08;很贵&#xff09;、公网ip&…

MongoDB教程(六):mongoDB复制副本集

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、MongoD…

使用Bind提供的域名解析服务

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 目录 一、DNS域名解析服务 二、安装Bind服务程序 1、正向解析 2、反向解析 三、部署从服务器 四、安全的加密传输 五、部署缓存服务器 六、分…

浅析班组建设在企业发展中的重要作用

众所周知&#xff0c;企业的成功与否往往取决于其内部管理的精细化和团队的高效协作。而班组作为企业最基层的管理单元&#xff0c;其建设质量直接关系到企业的整体运营效率和竞争力。今天&#xff0c;深圳天行健企业管理咨询公司将从多个维度分析班组建设在企业发展中的重要作…

【Python】深入了解 defaultdict:轻松处理默认值与复杂数据结构

文章目录 1. 深入理解 Python 中的 defaultdict&#xff1a;简化数据结构处理的利器2. defaultdict 基础概念3. 创建 defaultdict 实例3.1 基本用法3.2 使用其他工厂函数 4. defaultdict 的应用场景4.1 计数器4.2 分组数据 5. defaultdict 的高级用法5.1 嵌套 defaultdict5.2 自…

为什么流程图在项目管理中如此重要?

在我们的日常学习生活中&#xff0c;是不是感觉工作复杂繁琐&#xff0c;知识杂乱无章呢&#xff1f;那么流程图能够完美的解决这个问题&#xff0c;本文将会用一篇文章告诉你什么是流程图&#xff0c;流程图简单来说就是一种以图形方式表示算法、工作流程或过程的图表&#xf…