open3d-点云及其操作

news2024/11/16 21:42:47

open3d提供了一个专门用于点云的数据结构 PointCloud

class PointCloud(Geometry3D):
    color   # 颜色
    normals # 法向量
    points  # 点云
    def __init__(self, *args, **kwargs):
        """
        __init__(*args, **kwargs)
        Overloaded function.
        1. __init__(self: open3d.cpu.pybind.geometry.PointCloud) -> None
        Default constructor
        2. __init__(self: open3d.cpu.pybind.geometry.PointCloud, arg0: open3d.cpu.pybind.geometry.PointCloud) -> None
        Copy constructor
        3. __init__(self: open3d.cpu.pybind.geometry.PointCloud, points: open3d.cpu.pybind.utility.Vector3dVector) -> None
        Create a PointCloud from points
        """
    # dbscan聚类
    def cluster_dbscan(self, eps, min_points, print_progress=False):
    # 计算凸包
    def compute_convex_hull(self):
    # 计算马氏距离。 返回每个点的马氏距离
    def compute_mahalanobis_distance(self):
    # 计算均值与协方差矩阵
    def compute_mean_and_covariance(self): 
    # 计算点云每个点到其最近点的距离
    def compute_nearest_neighbor_distance(self):
    # 计算当前点云每个点到目标点云的最近距离
    def compute_point_cloud_distance(self, target):
    def create_from_depth_image(self, depth, intrinsic, extrinsic, *args, **kwargs):
    def create_from_rgbd_image(self, image, intrinsic, extrinsic, *args, **kwargs):
    # 裁剪。 输入一个aabb框或obb框
    def crop(self, *args, **kwargs):
    # 计算顶点法向量
    def estimate_normals(self, search_param=None, *args, **kwargs):
    # 是否有color
    def has_colors(self):
    # 是否有法向量
    def has_normals(self):
    # 是否有点云点
    def has_points(self):    
    # 隐藏点去除。 
    def hidden_point_removal(self, camera_location, radius):
    # 归一化法向量。 法向量长度为1
    def normalize_normals(self):
    # 法向量方向一致
    def orient_normals_consistent_tangent_plane(self, k):
    # 法向量方向一致。 指定相机位置
    def orient_normals_towards_camera_location(self, camera_location=None, *args, **kwargs):
    # 法向量方向一致。 指定参考方向
    def orient_normals_to_align_with_direction(self, orientation_reference=None, *args, **kwargs):
    # 上色。 颜色rgb,范围0~1
    def paint_uniform_color(self, color):
    # 随机下采样。 指定下采样率
    def random_down_sample(self, sampling_ratio):
    # 删除non 和 inf 值的点
    def remove_non_finite_points(self, remove_nan=True, remove_infinite=True):   
    # 删除指定半径内少于指定点数的点
    def remove_radius_outlier(self, nb_points, radius):
    # 删除相邻点中距离大于平均距离的点
    def remove_statistical_outlier(self, nb_neighbors, std_ratio):
    # 平面分割
    def segment_plane(self, distance_threshold, ransac_n, num_iterations):
    # 按照下标筛选点云
    def select_by_index(self, indices, invert=False):
    # 下采样。 每隔多少个点取一个
    def uniform_down_sample(self, every_k_points):
    # 体素下采样。 指定体素尺寸
    def voxel_down_sample(self, voxel_size):
    # 体素下采样并记录原数据。 指定体素尺寸
    def voxel_down_sample_and_trace(self, voxel_size, min_bound, max_bound, approximate_class=False): 
    
import numpy as np
import open3d as o3d
from open3d.web_visualizer import draw
from open3d.visualization import draw_geometries
pcd = o3d.io.read_point_cloud('datas/fragment.ply')
draw(pcd)

1.体素下采样

open3d.geometry.PointCloud 提供了 voxel_down_sample(self, voxel_size) 方法,来进行体素下采样操作。

    def voxel_down_sample(self, voxel_size):
        """
        voxel_down_sample(self, voxel_size)
        对输入点云进行体素下采样,如果法线和颜色存在,则法线和颜色取均值。

        Args:
            voxel_size (float): 体素尺寸

        Returns:
            open3d.geometry.PointCloud
        """
downsample = pcd.voxel_down_sample(voxel_size=0.05)
draw(downsample)

2. 顶点法向量估计

open3d.geometry.PointCloud 提供了 estimate_normals(self, voxel_size) 方法,来计算顶点法向量。

    def estimate_normals(self, search_param=None, *args, **kwargs): 
        """
        estimate_normals(self, search_param=KDTreeSearchParamKNN with knn = 30, fast_normal_computation=True)        
        Args:
            search_param (open3d.geometry.KDTreeSearchParam, optional): 用于领域搜索的KDTree搜索参数。 默认值为:KDTreeSearchParamKNN with knn = 30
            fast_normal_computation (bool, optional, default=True): 如果为true,通过协方差矩阵计算特征向量,速度更快,但数值不稳定。如果为False,则使用迭代方式。

        Returns:
            None   无返回值,法向量直接存储于 PointCloud.normals 
        """

search_param 参数有:

  • class KDTreeSearchParamHybrid(KDTreeSearchParam):
    def init(self, radius, max_nn): # 搜索半径、最大近邻点数
  • class KDTreeSearchParamKNN(KDTreeSearchParam):
    def init(self, knn=30): # 近邻点数
  • class KDTreeSearchParamRadius(KDTreeSearchParam):
    def init(self, radius): # 搜索半径
downsample.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.1, max_nn=30))

# 此处使用 draw_geometries绘制点云以及法线。
draw_geometries([downsample], point_show_normal=True)

3. 裁剪点云

裁剪点云,首先需要确定裁剪区域

通过o3d.visualization.read_selection_polygon_volume()函数,读取一个多边形区域。

然后通过多边形裁剪点云。

def read_selection_polygon_volume(filename): 
    """
    read_selection_polygon_volume(filename)
    Function to read SelectionPolygonVolume from file

    Args:
        filename (str): The file path.

    Returns:
        open3d.visualization.SelectionPolygonVolume
    """
    pass

open3d.visualization.SelectionPolygonVolume 含有两个方法:

  • crop_point_cloud(input)
  • crop_triangle_mesh(input)
# 读取多边形
vol = o3d.visualization.read_selection_polygon_volume('datas/cropped.json')
chair = vol.crop_point_cloud(pcd)
draw(chair)

4. 点云上色

open3d.geometry.PointCloud 提供了 paint_uniform_color(self, color)方法,来为点云进行上色。

def paint_uniform_color(self, color): 
    """
    paint_uniform_color(self, color)
    Assigns each point in the PointCloud the same color.

    Args:
        color (numpy.ndarray[float64[3, 1]]):RGB颜色,值在0~1范围内

    Returns:
        open3d.geometry.PointCloud
    """
    pass
chair.paint_uniform_color([1,0,0])  # 红色
draw(chair)

5. 点云距离与筛选

open3d.geometry.PointCloud 提供了 compute_point_cloud_distance(self, target)方法,计算当前点云中每个点到目标点云中点的最近距离。

def compute_point_cloud_distance(self, target):
    """        
    Args:
        target (open3d.geometry.PointCloud): 目标点云

    Returns:
        open3d.utility.DoubleVector
    """

open3d.geometry.PointCloud 提供了 select_by_index(self, indices, invert=False)方法,通过下标来筛选点云。

def select_by_index(self, indices, invert=False):
    """
    select_by_index(self, indices, invert=False)        
    Args:
        indices (List[int]): 下标
        invert (bool, optional, default=False): 反选

    Returns:
        open3d.geometry.PointCloud
    """
dists = pcd.compute_point_cloud_distance(chair)  # 计算整体点云中,每个点到椅子点云中最近点的距离。
dists = np.array(dists)
ind = np.where(dists > 0.01)[0]  # 获取距离大于0.01的点的下标
pcd_without_chair = pcd.select_by_index(ind)  # 通过下标筛选点云中点
draw(pcd_without_chair)

6. 边界框

o3d.geometry.Geometry3D 提供了 get_axis_aligned_bounding_box() 方法,来获取aabb包围盒(轴对齐包围盒)

def get_axis_aligned_bounding_box(self):
    """
    get_axis_aligned_bounding_box(self)        
    Returns:
        open3d.geometry.AxisAlignedBoundingBox
    """

o3d.geometry.Geometry3D 提供了 get_oriented_bounding_box() 方法,来获取obb包围盒(有向包围盒)

def get_oriented_bounding_box(self):
    """
    Returns:
        open3d.geometry.OrientedBoundingBox
    """
aabb = chair.get_axis_aligned_bounding_box()
print(aabb)
draw([chair, aabb])

obb = chair.get_oriented_bounding_box()
print(obb)
draw([chair, obb])

7.凸包

o3d.geometry.Geometry3D 提供了 compute_convex_hull() 方法,来获取点云的凸包。

def compute_convex_hull(self):
    """
    Returns:
        Tuple[open3d.geometry.TriangleMesh, List[int]] 返回两个值,第一个以三角形网格返回凸包,第二个返回凸包的顶点下标。
    """
hull, ind = chair.compute_convex_hull()

hull.paint_uniform_color([1,0,0])
draw([hull, chair])

chair.paint_uniform_color([0.5,0.5,0.5])
points = chair.select_by_index(ind)  # 红色点为凸包顶点
points.paint_uniform_color([1,0,0])
draw([chair, points])

8. dbscan聚类

open3d.geometry.PointCloud 提供了 cluster_dbscan(self, eps, min_points, print_progress=False) 方法,实现dbscan密度聚类。

def cluster_dbscan(self, eps, min_points, print_progress=False):
    """
    cluster_dbscan(self, eps, min_points, print_progress=False)        
    Args:
        eps (float):密度
        min_points (int): 形成簇的最小点数
        print_progress (bool, optional, default=False): 
    Returns:
        open3d.utility.IntVector label值,int
    """
from matplotlib import pyplot as plt
labels = pcd.cluster_dbscan(eps=0.02, min_points=10, print_progress=True)
labels = np.asarray(labels)
max_label = labels.max()
colors = plt.get_cmap("tab20")(labels / (max_label if max_label > 0 else 1))
colors[labels < 0] = 0
pcd.colors = o3d.utility.Vector3dVector(colors[:, :3])

draw(pcd)

9. 平面分割

open3d.geometry.PointCloud 提供了 **segment_plane(self, distance_threshold, ransac_n, num_iterations)** 方法,通过RANSAC从点云中分割平面。
def segment_plane(self, distance_threshold, ransac_n, num_iterations):
    """        
    Args:
        distance_threshold (float): 点到面的最大距离
        ransac_n (int): 随机采样估计平面的点数
        num_iterations (int): 迭代次数

    Returns:
        Tuple[numpy.ndarray[float64[4, 1]], List[int]]
        """
pcd = o3d.io.read_point_cloud('datas/fragment.ply')
plane_model, ind = pcd.segment_plane(distance_threshold=0.01, ransac_n=3, num_iterations=1000)

plane = pcd.select_by_index(ind)
plane.paint_uniform_color([1,0,0])
without_plane = pcd.select_by_index(ind, True)
draw([plane, without_plane])

10. 隐藏点去除

open3d.geometry.PointCloud 提供了 hidden_point_removal(self, camera_location, radius) 方法。

def hidden_point_removal(self, camera_location, radius):
    """        
    Args:
        camera_location (numpy.ndarray[float64[3, 1]]): All points not visible from that location will be reomved
        radius (float): The radius of the sperical projection

    Returns:
        Tuple[open3d.geometry.TriangleMesh, List[int]]
    """
diameter = np.linalg.norm(np.asarray(pcd.get_max_bound()) - np.asarray(pcd.get_min_bound()))
camera = [0, 0, diameter]
radius = diameter * 100
_, pt_map = pcd.hidden_point_removal(camera, radius)

pcd = pcd.select_by_index(pt_map)
draw(pcd)

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

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

相关文章

对某登录站点的JS前端逆向思路

前言 js逆向一直没有相关了解&#xff0c;虽然目前渗透遇见的不是很多&#xff0c;大多数遇见的要么不加密&#xff0c;要么无法实现其加密流程&#xff0c;不过最近看到了一个较为简单的站点正好能够逆向出来&#xff0c;就做了简单记录。本文旨在介绍js逆向的一些基础思路&a…

Antd可编辑表格初始数据为空,单元格不能编辑的解决办法

黑科技超简单: 给table表格增加行className rowClassName{() > editable-row} 然后设置可编辑表格的行样式 .editable-row:hover .editable-cell-value-wrap {border: 1px solid #d9d9d9;border-radius: 4px;padding: 4px 11px;}.editable-cell-value-wrap {padding: 5px…

网络调试助手 连接Onenet 多协议接入平台 TCP透传协议

onenet文档链接 多协议接入地址 打开Onenet平台&#xff0c;多协议接入 选择TCP透传协议&#xff0c;点击添加产品&#xff0c;输入信息&#xff0c;点击确认 点击设备列表&#xff0c;添加设备 下面需要上传一个解析脚本文件该文件的下载地址lua文件下载地址 建立连接 设备…

Vmware虚拟化引擎开启

VMware虚拟化引擎开启可以优化虚拟机性能和安全性&#xff0c;但总会出现打开后报错的情况&#xff0c;需要按以下步骤设置处理。 通过任务管理器查看CPU是否已经启用虚拟化 在启用或关闭windows功能中去掉和虚拟化配置相关的功能项后重启 在VMware中选择需要的虚拟化引擎&…

上海震坤行:水泥行业数字化采购的趋势、策略与实践

上海震坤行&#xff1a;水泥行业数字化采购的趋势、策略与实践 在中国水泥协会发布的《2023年上半年水泥行业经济运行及下半年展望》中提到了水泥行业的发展现状——2023年上半年&#xff0c;在全球经济增长放缓、国内经济延续恢复态势、但市场需求不足的宏观环境下&#xff0…

Leetcode394. 字符串解码

Every day a Leetcode 题目来源&#xff1a;394. 字符串解码 解法1&#xff1a;栈 本题中可能出现括号嵌套的情况&#xff0c;比如 2[a2[bc]]&#xff0c;这种情况下我们可以先转化成 2[abcbc]&#xff0c;在转化成 abcbcabcbc。我们可以把字母、数字和括号看成是独立的 TO…

leetcode LCR 179. 查找总价格为目标值的两个商品(优质解法)

代码&#xff1a; class Solution {public int[] twoSum(int[] price, int target) {int lengthprice.length;int left0;int rightlength-1;while (left<right){if(price[left]price[right]>target){right--;}else if(price[left]price[right]<target){left;}else {b…

express+mySql实现用户注册、登录和身份认证

expressmySql实现用户注册、登录和身份认证 注册 注册时需要对用户密码进行加密入库&#xff0c;提高账户的安全性。用户登录时再将密码以相同的方式进行加密&#xff0c;再与数据库中存储的密码进行比对&#xff0c;相同则表示登录成功。 安装加密依赖包bcryptjs cnpm insta…

毫无基础的人如何入门 Python ?--找对学习入口是关键!

1.行百里者半三十 不少学生或职场人士总面临这样一种窘境&#xff1a;数字化转型大背景、大趋势下&#xff0c;感觉非常有必要学习Python等分析工具&#xff0c;但在真正学习Python的各种语言规则时&#xff0c;往往体验不到知识的乐趣&#xff0c;翻看个别章节后即束之高阁。…

循环神经网络RNN

1. 背景 RNN(Recurrent Neural Networks) CNN利用输入中的空间几何结构信息&#xff1b;RNN利用输入数据的序列化特性。 2. SimpleRNN单元 传统多层感知机网络假设所有的输入数据之间相互独立&#xff0c;但这对于序列化数据是不成立的。RNN单元用隐藏状态或记忆引入这种依赖…

力扣 --- 三数之和

目录 题目描述&#xff1a; 思路描述&#xff1a; 代码&#xff1a; 提交结果&#xff1a; 官方代码&#xff1a; 官方提交结果&#xff1a; 题目描述&#xff1a; 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k…

【虚拟机】Docker基础 【二】

2.2.数据卷 容器是隔离环境&#xff0c;容器内程序的文件、配置、运行时产生的容器都在容器内部&#xff0c;我们要读写容器内的文件非常不方便。大家思考几个问题&#xff1a; 如果要升级MySQL版本&#xff0c;需要销毁旧容器&#xff0c;那么数据岂不是跟着被销毁了&#x…

vue要做权限管理该怎么做?如果控制到按钮级别的权限怎么做?

面试官&#xff1a;vue要做权限管理该怎么做&#xff1f;如果控制到按钮级别的权限怎么做&#xff1f; 一、是什么 权限是对特定资源的访问许可&#xff0c;所谓权限控制&#xff0c;也就是确保用户只能访问到被分配的资源 而前端权限归根结底是请求的发起权&#xff0c;请求…

上海震坤行被评为虹桥生产线互联网服务高质量发展平台

上海震坤行被评为虹桥生产线互联网服务高质量发展平台 10月12日&#xff0c;新一期“潮涌浦江投资虹桥”活动暨“战略赋能新机遇&#xff0c;开放引领新高地”——2023虹桥国际中央商务区投资促进大会在上海虹桥举行。 本次活动旨在释放关于推动虹桥国际开放枢纽进一步提升能级…

Attention机制(笔记)

参考&#xff1a;2.3.2注意力机制-part1_哔哩哔哩_bilibili 什么是attention&#xff1f; 答&#xff1a;注意力放在事物最有辨识度的部分 attention计算机制&#xff1a; 为什么用这个公式可以得到attention&#xff1f; 补充说明&#xff08;chatGPT给出的解释&#xff09;&…

Vue中 实现自定义指令(directive)及应用场景

一、Vue2 1. 指令钩子函数 一个指令定义对象可以提供如下几个钩子函数 (均为可选)&#xff1a; bind 只调用一次&#xff0c;指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted 被绑定元素插入父节点时调用 (仅保证父节点存在&#xff0c;但不一定已…

高等数学中微分方程的种类及其解法

1 微分方程的基本概念 1.1 微分方程 含导数或微分的方程,称为微分方程 1.2 微分方程的阶 微分方程中所含的导数或微分的最高阶数,称为该微分方程的阶数 1.3 微分方程的解 使得微分方程成立的函数,称为微分方程的解,微分方程的解可分为通解和特解 不含任意常数的微分方程的…

正式确定,奥特曼重回 OpenAI 担任 CEO

今天&#xff0c;OpenAI 正式宣布山姆奥特曼回归 OpenAI&#xff0c;重新担任 CEO&#xff1a; 米拉将回归首席技术官职位&#xff08;CTO&#xff09;而新的初步董事会成员包括布雷特泰勒&#xff08;主席&#xff09;、拉里萨默斯和亚当D’安杰洛。经此一役&#xff0c;可以…

Java核心知识点整理大全23-笔记

目录 21. JAVA 算法 21.1.1. 二分查找 21.1.2.冒泡排序算法 21.1.3. 插入排序算法 21.1.4. 快速排序算法 21.1.1. 希尔排序算法 21.1.2. 归并排序算法 21.1.3. 桶排序算法 21.1.4. 基数排序算法 21.1.5. 剪枝算法 21.1.6. 回溯算法 21.1.7. 最短路径算法 21.1.8. 最…

用java实现拼图小游戏

1、了解拼图游戏基本功能&#xff1a; 拼图游戏内容由若干小图像块组成的&#xff0c;通过鼠标点击图像块上下左右移动&#xff0c;完成图像的拼凑。 2、拼图游戏交互界面设计与开发&#xff1a; 通过创建窗体类、菜单、中间面板和左右面板完成设计拼图的交互界面 &#xff…