当前位置: 首页 > news >正文

open3d教程 (三)点云的显示

官方文档位置: Visualization - Open3D 0.19.0 documentationhttps://www.open3d.org/docs/release/tutorial/visualization/visualization.html核心方法:

o3d.visualization.draw_geometries([几何对象列表])
import  open3d as o3d

print("Load a ply point cloud, print it, and render it")
sample_ply_data = o3d.data.PLYPointCloud()
pcd = o3d.io.read_point_cloud(sample_ply_data.path)
o3d.visualization.draw_geometries([pcd],
                                  zoom=0.3412,
                                  front=[0.4257, -0.2125, -0.8795],
                                  lookat=[2.6172, 2.0475, 1.532],
                                  up=[-0.0694, -0.9768, 0.2024])

visualization窗体功能:

点击到窗口  按键盘 h 键

(1) 视图控制

操作

方法
旋转视图按住鼠标左键拖动
平移视图按住鼠标滚轮拖动
缩放视图鼠标滚轮
重置视角按 R 键
切换全屏按 F 键
快捷键功能
L切换点云渲染(点/线框/面)
N显示/隐藏法线(需提前计算)
C显示/隐藏颜色(如果数据包含颜色)
S保存当前视角截图

添加几何元素 

下面的代码使用 、 和 生成一个长方体、一个球体和一个圆柱体。长方体涂成红色,球体涂成蓝色,圆柱体涂成绿色。为所有网格计算法线以支持 Phong 着色(请参见可视化 3D 网格和表面法线估计)。我们甚至可以使用 创建一个坐标轴,其原点设置为 (-2, -2, -2)。

import  open3d as o3d
print("Let's define some primitives")
#创建立方体
mesh_box = o3d.geometry.TriangleMesh.create_box(width=1.0,
                                                height=1.0,
                                                depth=1.0)
#设置颜色
mesh_box.paint_uniform_color([0.9, 0.1, 0.1]) 
#创建球体
mesh_sphere = o3d.geometry.TriangleMesh.create_sphere(radius=1.0)
#设置颜色
mesh_sphere.paint_uniform_color([0.1, 0.1, 0.7])
#创建圆柱体
mesh_cylinder = o3d.geometry.TriangleMesh.create_cylinder(radius=0.3,
                                                          height=4.0)
mesh_cylinder.paint_uniform_color([0.1, 0.9, 0.1])
#创建坐标轴
mesh_frame = o3d.geometry.TriangleMesh.create_coordinate_frame(
    size=0.6, origin=[-2, -2, -2])
print("We draw a few primitives using collection.")
o3d.visualization.draw_geometries(
    [mesh_box, mesh_sphere, mesh_cylinder, mesh_frame])

print("We draw a few primitives using + operator of mesh.")
o3d.visualization.draw_geometries(
    [mesh_box + mesh_sphere + mesh_cylinder + mesh_frame])

绘制线 

Visualization - Open3D 0.19.0 documentationhttps://www.open3d.org/docs/release/tutorial/visualization/visualization.html#Draw-line-set

import open3d as o3d
print("Let's draw a box using o3d.geometry.LineSet.")
# 点坐标
points = [
    [0, 0, 0],
    [1, 0, 0],
    [0, 1, 0],
    [1, 1, 0],
    [0, 0, 1],
    [1, 0, 1],
    [0, 1, 1],
    [1, 1, 1],
]
# 线段索引  [0, 1] 表示0号点到1号点的线段
lines = [
    [0, 1],
    [0, 2],
    [1, 3],
    [2, 3],
    [4, 5],
    [4, 6],
    [5, 7],
    [6, 7],
    [0, 4],
    [1, 5],
    [2, 6],
    [3, 7],
]
colors = [[1, 0, 0] for i in range(len(lines))]
line_set = o3d.geometry.LineSet(
    points=o3d.utility.Vector3dVector(points), # 点坐标 需要转换为Vector3dVector  Vector3dVector 是一个关键的数据转换工具,
    # 用于将常见的数值数组(如 NumPy 数组或 Python 列表)转换为 Open3D 内部高效处理的 3D 向量格式 N×3
    lines=o3d.utility.Vector2iVector(lines),
)
line_set.colors = o3d.utility.Vector3dVector(colors)
o3d.visualization.draw_geometries([line_set])

Vector2iVector 是一个用于处理 二维整数向量数据 的实用工具类,类似于 Vector3dVector,但专为 (N, 2) 形状的整数数据设计

Vector3dVector 是一个关键的数据转换工具,用于将常见的数值数组(如 NumPy 数组或 Python 列表)转换为 Open3D 内部高效处理的 3D 向量格式,主要功能:将 N×3 的数值数据(如点云坐标、法线、颜色)转换为 Open3D 几何体(如 PointCloudTriangleMesh)可识别的内部数据结构

自定义可视化  自定义创建功能

 

Customized visualization - Open3D 0.19.0 documentationhttps://www.open3d.org/docs/release/tutorial/visualization/customized_visualization.html#customized-visualization使点云旋转

import  open3d as o3d
def custom_draw_geometry_with_rotation(pcd):

    def rotate_view(vis):
        ctr = vis.get_view_control()
        ctr.rotate(10.0, 0.0)
        return False

    o3d.visualization.draw_geometries_with_animation_callback([pcd],
                                                              rotate_view)

sample_pcd_data = o3d.data.PCDPointCloud()
pcd = o3d.io.read_point_cloud(sample_pcd_data.path)
custom_draw_geometry_with_rotation(pcd)

https://www.open3d.org/docs/release/_images/rotate_small.gif

交互式可视化

Interactive visualization - Open3D 0.19.0 documentation

  

# examples/python/visualization/interactive_visualization.py

import numpy as np
import copy
import open3d as o3d


def demo_crop_geometry():
    print("Demo for manual geometry cropping")
    print(
        "1) Press 'Y' twice to align geometry with negative direction of y-axis"
    )
    print("2) Press 'K' to lock screen and to switch to selection mode")
    print("3) Drag for rectangle selection,")
    print("   or use ctrl + left click for polygon selection")
    print("4) Press 'C' to get a selected geometry")
    print("5) Press 'S' to save the selected geometry")
    print("6) Press 'F' to switch to freeview mode")
    pcd_data = o3d.data.DemoICPPointClouds()
    pcd = o3d.io.read_point_cloud(pcd_data.paths[0])
    o3d.visualization.draw_geometries_with_editing([pcd])


def draw_registration_result(source, target, transformation):
    source_temp = copy.deepcopy(source)
    target_temp = copy.deepcopy(target)
    source_temp.paint_uniform_color([1, 0.706, 0])
    target_temp.paint_uniform_color([0, 0.651, 0.929])
    source_temp.transform(transformation)
    o3d.visualization.draw_geometries([source_temp, target_temp])


def prepare_data():
    pcd_data = o3d.data.DemoICPPointClouds()
    source = o3d.io.read_point_cloud(pcd_data.paths[0])
    target = o3d.io.read_point_cloud(pcd_data.paths[2])
    print("Visualization of two point clouds before manual alignment")
    draw_registration_result(source, target, np.identity(4))
    return source, target


def pick_points(pcd):
    print("")
    print(
        "1) Please pick at least three correspondences using [shift + left click]"
    )
    print("   Press [shift + right click] to undo point picking")
    print("2) After picking points, press 'Q' to close the window")
    vis = o3d.visualization.VisualizerWithEditing()
    vis.create_window()
    vis.add_geometry(pcd)
    vis.run()  # user picks points
    vis.destroy_window()
    print("")
    return vis.get_picked_points()


def register_via_correspondences(source, target, source_points, target_points):
    corr = np.zeros((len(source_points), 2))
    corr[:, 0] = source_points
    corr[:, 1] = target_points
    # estimate rough transformation using correspondences
    print("Compute a rough transform using the correspondences given by user")
    p2p = o3d.pipelines.registration.TransformationEstimationPointToPoint()
    trans_init = p2p.compute_transformation(source, target,
                                            o3d.utility.Vector2iVector(corr))
    # point-to-point ICP for refinement
    print("Perform point-to-point ICP refinement")
    threshold = 0.03  # 3cm distance threshold
    reg_p2p = o3d.pipelines.registration.registration_icp(
        source, target, threshold, trans_init,
        o3d.pipelines.registration.TransformationEstimationPointToPoint())
    draw_registration_result(source, target, reg_p2p.transformation)


def demo_manual_registration():
    print("Demo for manual ICP")
    source, target = prepare_data()

    # pick points from two point clouds and builds correspondences
    source_points = pick_points(source)
    target_points = pick_points(target)
    assert (len(source_points) >= 3 and len(target_points) >= 3)
    assert (len(source_points) == len(target_points))
    register_via_correspondences(source, target, source_points, target_points)
    print("")


if __name__ == "__main__":
    demo_crop_geometry()
    demo_manual_registration()

draw_geometries_with_editing 默认绑定的功能 可以实现点云的剪切

以下是打印信息中提到的按键及其作用:

按键

功能触发条件
Y (按两次)将几何体对齐到 Y 轴负方向必须在非锁定模式下
K锁定屏幕并进入选择模式任意时刻
Ctrl + 左键多边形选择模式必须在选择模式下
拖动鼠标矩形框选必须在选择模式下
C提取选中区域的几何体必须在选择模式下有选中区域
S保存当前几何体到 edited_model.ply任意时刻
F退出选择模式,返回自由视角必须在选择模式下

自定义按键绑定(高级用法)
如果需要覆盖默认行为或添加新功能,可以通过 注册回调函数 实现:


def custom_key_callback(vis):
    print("Custom key pressed!")
    return False

vis = o3d.visualization.VisualizerWithEditing()
vis.create_window()
vis.register_key_callback(ord("Q"), custom_key_callback)  # 绑定Q键
vis.add_geometry(pcd)
vis.run()

Interactive visualization - Open3D 0.19.0 documentation

实现手动选点 

核心代码
def pick_points(pcd):
    print("")
    print(
        "1) Please pick at least three correspondences using [shift + left click]"
    )
    print("   Press [shift + right click] to undo point picking")
    print("2) After picking points, press 'Q' to close the window")
    vis = o3d.visualization.VisualizerWithEditing()
    vis.create_window()
    vis.add_geometry(pcd)
    vis.run()  # user picks points
    vis.destroy_window()
    print("")
    return vis.get_picked_points()

进行点云配准

def register_via_correspondences(source, target, source_points, target_points):
    """
    通过用户提供的对应点对进行点云粗配准 + ICP精配准
    
    参数:
        source (open3d.geometry.PointCloud): 待配准的源点云
        target (open3d.geometry.PointCloud): 目标点云
        source_points (list/np.array): 源点云中选取的对应点索引数组
        target_points (list/np.array): 目标点云中对应的点索引数组
    """
    # 1. 构建对应点对矩阵 (N x 2)
    corr = np.zeros((len(source_points), 2))  # 初始化对应点对容器
    corr[:, 0] = source_points  # 第一列填充源点云索引
    corr[:, 1] = target_points  # 第二列填充目标点云索引
    
    # 2. 基于对应点对计算初始变换矩阵
    print("Compute a rough transform using the correspondences given by user")
    # 创建点对点变换估计器
    p2p = o3d.pipelines.registration.TransformationEstimationPointToPoint()
    # 计算初始变换矩阵(将source_points对齐到target_points)
    trans_init = p2p.compute_transformation(
        source, 
        target,
        o3d.utility.Vector2iVector(corr)  # 将对应点对转换为Open3D格式
    )
    
    # 3. 使用ICP进行精细配准
    print("Perform point-to-point ICP refinement")
    threshold = 0.03  # 3cm距离阈值,超过此距离的点对不参与计算
    reg_p2p = o3d.pipelines.registration.registration_icp(
        source,               # 源点云
        target,               # 目标点云
        threshold,            # 最大对应点距离阈值
        trans_init,           # 上一步计算的初始变换
        o3d.pipelines.registration.TransformationEstimationPointToPoint(),  # 使用点对点ICP
        # 可选参数(未显式设置时使用默认值):
        # criteria = ICP迭代停止条件(默认最大迭代30次,相对变化1e-6)
        # estimation_method = 变换估计方法
    )
    
    # 4. 可视化配准结果
    draw_registration_result(source, target, reg_p2p.transformation)
    
    # 返回配准结果(包含变换矩阵、拟合度等信息)
    return reg_p2p

典型使用场景:

# 示例:手动选取5对对应点进行配准
source_idx = [10, 20, 30, 40, 50]  # 源点云中选取的点索引
target_idx = [15, 25, 35, 45, 55]  # 目标点云中对应的点索引
result = register_via_correspondences(source_pcd, target_pcd, source_idx, target_idx)
print("Final transformation matrix:\n", result.transformation)

非阻塞窗口  不停止窗口  并更新窗口显示


import open3d as o3d
import numpy as np

def prepare_data():
    # 加载Open3D提供的示例点云数据(两帧扫描数据)
    pcd_data = o3d.data.DemoICPPointClouds()
    source_raw = o3d.io.read_point_cloud(pcd_data.paths[0])  # 源点云
    target_raw = o3d.io.read_point_cloud(pcd_data.paths[1])  # 目标点云
    
    # 体素下采样(降低计算量)
    source = source_raw.voxel_down_sample(voxel_size=0.02)
    target = target_raw.voxel_down_sample(voxel_size=0.02)

    # 对源点云施加初始变换(模拟初始位姿偏差)
    trans = [[0.862, 0.011, -0.507, 0.0], 
             [-0.139, 0.967, -0.215, 0.7],
             [0.487, 0.255, 0.835, -1.4], 
             [0.0, 0.0, 0.0, 1.0]]  # 4x4变换矩阵
    source.transform(trans)
    
    # 对两个点云施加镜像翻转(使可视化效果更直观)
    flip_transform = [[1, 0, 0, 0], 
                      [0, -1, 0, 0], 
                      [0, 0, -1, 0], 
                      [0, 0, 0, 1]]
    source.transform(flip_transform)
    target.transform(flip_transform)
    return source, target


def demo_non_blocking_visualization():
    # 设置日志级别为Debug(显示详细运行信息)
    o3d.utility.set_verbosity_level(o3d.utility.VerbosityLevel.Debug)

    # 加载数据
    source, target = prepare_data()
    
    # 创建可视化窗口并添加几何体
    vis = o3d.visualization.Visualizer()
    vis.create_window()
    vis.add_geometry(source)  # 添加源点云(红色)
    vis.add_geometry(target)  # 添加目标点云(蓝色)

    # ICP参数设置
    threshold = 0.05  # 距离阈值(5cm内视为对应点)
    icp_iteration = 100  # 总迭代次数
    save_image = False  # 是否保存每帧截图

    # 迭代执行ICP
    for i in range(icp_iteration):
        # 执行单次ICP迭代(max_iteration=1表示每步只迭代一次)
        reg_p2l = o3d.pipelines.registration.registration_icp(
            source, target, threshold, np.identity(4),
            o3d.pipelines.registration.TransformationEstimationPointToPlane(),
            o3d.pipelines.registration.ICPConvergenceCriteria(max_iteration=1))
        
        # 更新源点云位置
        source.transform(reg_p2l.transformation)
        
        # 刷新可视化
        vis.update_geometry(source)  # 通知可视化器几何体已更新
        vis.poll_events()  # 处理UI事件(如窗口缩放)
        vis.update_renderer()  # 重绘场景
        
        # 可选:保存当前帧截图
        if save_image:
            vis.capture_screen_image("temp_%04d.jpg" % i)
    
    # 关闭窗口
    vis.destroy_window()
    o3d.utility.set_verbosity_level(o3d.utility.VerbosityLevel.Info)  # 恢复日志级别




if __name__ == '__main__':
    demo_non_blocking_visualization()

关键点

  • 非阻塞可视化三要素

    • update_geometry():标记需要更新的几何体

    • poll_events():处理用户交互事件

    • update_renderer():触发画面重绘

  • ICP配置

    • TransformationEstimationPointToPlane:使用点到面ICP(比点到点更鲁棒)

    • max_iteration=1:每次外部循环只做一次ICP迭代,实现逐步可视化

此脚本调用每次迭代。请注意,它通过 .这是从单个 ICP 迭代中检索轻微姿势更新的技巧。在 ICP 之后,源几何体会相应地变换。registration_icpICPConvergenceCriteria(max_iteration = 1)

相关文章:

  • 【蓝桥杯每日一题】4.1
  • SQLyog一款被遗忘的MySQL管理利器深度解析
  • 强化终端安全防线防范屏幕共享诈骗
  • SAP SCC安装配置
  • 【蓝桥杯速成】| 18.完全背包(练习室)
  • Excel去掉单元格里面的换行的方法
  • 优艾智合-西安交大具身智能机器人研究院公布人形机器人矩阵
  • Tiktok矩阵运营中使用云手机的好处
  • ChatBI产品形态深度解析:嵌入式BI与大模型的场景化融合实践
  • Mysql之Redo log(Red log of MySQL)
  • 黑白彩色相机成像原理
  • 嘿嘿,好久不见
  • Maven核心配置文件深度解析:pom.xml完全指南
  • 解码 @property - 属性管理的艺术
  • 搜索算法-------DFS练习1
  • C 语 言 --- 指 针 1
  • Vue2(12) 表单输入绑定学习笔记
  • 数据库——MySQL连接表
  • 从零构建大语言模型全栈开发指南:第四部分:工程实践与部署-4.2.3行业案例:智能客服中的图文交互系统
  • 谈谈快速排序算法,其时间复杂度和空间复杂度是多少?
  • 可以做网站的域名后缀/360搜索引擎入口
  • 遂溪手机网站建设公司/代理公司注册
  • 做网站哪些/网络信息发布平台
  • 六安网站制作/制作app平台需要多少钱
  • 提供网站制作公司电话/教育培训机构十大排名
  • 做玩网站怎么上传图片/seo01网站