常用的点云预处理算法

news2024/11/15 21:26:38

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

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

离群点过滤

无效值剔除

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

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

Open3D实现

import open3d as o3d

def 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 np
 
 
if __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 deepcopy
 
 
if __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 np
 
 
if __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 np
 
def farthest_point_sample(point, npoint):
    """
    Input:
        xyz: pointcloud data, [N, D]
        npoint: number of samples
    Return:
        centroids: sampled pointcloud index, [npoint, D]
    """
    N, D = point.shape
    xyz = point[:,:3]
    centroids = np.zeros((npoint,))
    distance = np.ones((N,)) * 1e10
    farthest = np.random.randint(0, N)
    for i in range(npoint):
        centroids[i] = farthest
        centroid = xyz[farthest, :]
        dist = np.sum((xyz - centroid) ** 2, -1)
        mask = dist < distance
        distance[mask] = dist[mask]
        farthest = np.argmax(distance, -1)
    point = point[centroids.astype(np.int32)]
    return point

if __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 deepcopy

if __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 NearestNeighbors

def 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.coloradmin.cn/o/1932071.html

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

相关文章

实战打靶集锦-31-monitoring

文章目录 1. 主机发现2. 端口扫描3. 服务枚举4. 服务探查4.1 ssh服务4.2 smtp服务4.3 http/https服务 5. 系统提权5.1 枚举系统信息5.2 枚举passwd文件5.3 枚举定时任务5.4 linpeas提权 6. 获取flag 靶机地址&#xff1a;https://download.vulnhub.com/monitoring/Monitoring.o…

算法力扣刷题记录 四十九【112. 路径总和】和【113. 路径总和ii】

前言 二叉树篇继续。 记录 四十九【112. 路径总和】和【113. 路径总和ii】 一、【112. 路径总和】题目阅读 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 target…

VsCode远程ssh连接失败:Could not establish connection to XXX

一、问题描述 在VsCode中按下"F1"&#xff0c;选择Remote-SSH:Connect to Host 选择一个已经配置好的SSH主机&#xff0c;比如我选择的是192.168.0.104&#xff1a; 结果提示&#xff1a;Could not establish connection to XXX 二、解决方法 观察VsCode的输出信息…

走进NoSql

一、引入 1.1什么是NoSql NoSQL&#xff08;Not Only SQL&#xff09;是一组非关系型数据库&#xff08;或称为非SQL数据库&#xff09;的统称&#xff0c;它们提供了与传统的关系型数据库不同的数据存储和检索方式。NoSQL数据库通常用于处理大量的、分布式的、非结构化或半结…

STM32使用Wifi连接阿里云

目录 1 实现功能 2 器件 3 AT指令 4 阿里云配置 4.1 打开阿里云 4.2 创建产品 4.3 添加设备 5 STM32配置 5.1 基础参数 5.2 功能定义 6 STM32代码 本文主要是记述一下&#xff0c;如何使用阿里云物联网平台&#xff0c;创建一个简单的远程控制小灯示例。 完整工程&a…

BurpSuit的intruder模块结果进行筛选和导出

文章目录 一、搭建的测试网站第一步 先抓去数据包,查看数据包第二步 可以控制返回信息一条一条的显示第三步 使用intrude模块进行遍历,每次只显示一条用户信息第四步 配置过滤规则第五步 查看结果显示第六步 进行数据导出第七步 查看导出的表格二、实际项目中使用免责声明一、…

PCIe驱动开发(3)— 驱动设备文件的创建与操作

PCIe驱动开发&#xff08;3&#xff09;— 驱动设备文件的创建与操作 一、前言 在 Linux 中一切皆为文件&#xff0c;驱动加载成功以后会在“/dev”目录下生成一个相应的文件&#xff0c;应用程序通过对这个名为“/dev/xxx” (xxx 是具体的驱动文件名字)的文件进行相应的操作即…

Azure Repos 仓库管理

从远端仓库克隆到本地 前提:本地要安装git,并且登录了账户 1.在要放这个远程仓库的路径下,打git 然后 git clone https://.. 如果要登录验证,那就验证下,点 generate git credentials,复制password 克隆完后,cd 到克隆的路径, 可以用 git branch -a //查看分…

Spring Cloud环境搭建

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f525;个人专栏&#xff1a;Spring学习之路&#x1f4d5;格言&#xff1a;吾愚多不敏&#xff0c;而愿加学欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 1. 开发环境安装 1.1 安装JDK ​1.2 安装MySQL 2. 案列介绍 2.1 …

Linux 命令 —— top命令(查看进程资源占用)

文章目录 top 命令显示信息介绍top 命令使用 top 命令显示信息介绍 top 命令是 Linux/Unix 系统中常用的进程监控工具&#xff0c;可以实时动态显示系统中各个进程的资源占用情况&#xff0c;包括CPU、内存等。 进入 linux 系统&#xff0c;直接输入 top&#xff0c;回车&…

全网超详细Redis主从部署(附出现bug原因)

主从部署 整体架构图 需要再建两个CentOs7,过程重复单机部署 http://t.csdnimg.cn/zkpBE http://t.csdnimg.cn/lUU5gLinux环境下配置redis 查看自己ip地址命令 ifconfig 192.168.187.137 进入redis所在目录 cd /opt/software/redis cd redis-stable 进入配置文件 vim redi…

书生大模型第三关-Git基础

1.任务1: 破冰活动&#xff1a;自我介绍 目标&#xff1a; 每位参与者提交一份自我介绍。 提交地址&#xff1a;https://github.com/InternLM/Tutorial 的 camp3 分支&#xff5e; 行动&#xff1a; 首先Fork项目到自己Repo中&#xff0c;然后git clone在本地上 然后创建一个…

liunx面试题目

如何看当前Linux系统有几颗物理CPU和每颗CPU的核数&#xff1f; 查看物理cup&#xff1a; cat /proc/cpuinfo|grep -c ‘physical id’ 查看每颗cup核数 cat /proc/cpuinfo|grep -c ‘processor’ 若希望自动实现软件包的更新&#xff0c;可以使用yum-cron并启动该服务 yum -y …

【java计算机毕设】农产品仓库管理系统系统MySQL ssm JSP maven项目代码+文档 前后端一体 暑假作业

目录 1项目功能 2项目介绍 3项目地址 1项目功能 【java计算机毕设】农产品仓库管理系统系统MySQL ssm vue maven项目代码文档 前后端一体 暑假作业 2项目介绍 系统功能&#xff1a; 农产品仓库管理包括管理员、用户俩种角色。 管理员功能包括个人中心模块用于修改个人信息和…

60K起?“软件安全岗”比“网络安全岗”薪资高在哪里?

在网络世界的江湖中&#xff0c;“软件安全”与“网络安全”这两大“武林高手”都肩负着守护数字领域和平的重任。不过&#xff0c;眼尖的小伙伴们可能发现了&#xff0c;软件安全岗位的薪资待遇往往比网络安全岗位要丰厚那么一些&#xff0c;这到底是为啥呢&#xff1f;今天&a…

【AI绘画教程】Stable Diffusion 1.5 vs 2

在本文中,我们将总结稳定扩散 1 与稳定扩散 2 辩论中的所有要点。我们将在第一部分中查看这些差异存在的实际原因,但如果您想直接了解实际差异,您可以跳下否定提示部分。让我们开始吧! Stable Diffusion 2.1 发布与1.5相比,2.1旨在解决2.0的许多相对缺点。本文的内容与理解…

数字化转型“破局”:低代码开发平台如何缩短开发交付周期,提升效率

日新月异的数字时代&#xff0c;各行业正经历着前所未有的变革与转型。随着大数据、云计算、人工智能等技术的不断成熟与融合&#xff0c;数字化转型的步伐愈发坚定而迅速&#xff0c;成为企业转型升级、实现可持续发展的必由之路。然而&#xff0c;传统的软件开发模式受限于高…

35.UART(通用异步收发传输器)-RS232(2)

&#xff08;1&#xff09;RS232接收模块visio框图&#xff1a; &#xff08;2&#xff09;接收模块Verilog代码编写: /* 常见波特率&#xff1a; 4800、9600、14400、115200 在系统时钟为50MHz时&#xff0c;对应计数为&#xff1a; (1/4800) * 10^9 /20 -1 10416 …

如何防止漏洞攻击

随着信息技术的日新月异&#xff0c;企业在日常运营中对网络和数字化系统的依赖日益加深。然而&#xff0c;这种高度依赖也伴随着网络安全威胁的急剧增长&#xff0c;对企业的核心资产与数据构成了严峻挑战。为了有效捍卫企业利益&#xff0c;确保运营无忧&#xff0c;积极构建…

Monaco 使用 DocumentHighlightProvider

Monaco 中有一个文字高亮的功能&#xff0c;就是选中一个单词&#xff0c;会高亮文字文档中所有出现该单词的位置&#xff0c;效果如下&#xff1a; Monaco 默认就有这个功能&#xff0c;可以根据具体需求进行定制。通过 registerDocumentHighlightProvider 进行注册 实现 pro…