Open3d是一个支持解决3D数据快速处理软件开发的一个开源库。Open3D 前端在 C++ 和 Python 中公开了一组精心挑选的数据结构和算法。后端被高度优化,以及采用并行化处理运行。我们欢迎来自开源社区的贡献。
Open3d包含的核心特点:
构建Pip 或conda,需支持Ubuntu 18.04+, macOS 10.15+ and Windows 10 (64-bit)平台上的Python 3.6-3.9。
# Install
pip install open3d
# Verify installation
python -c "import open3d as o3d; print(o3d.__version__)"
# Python API
python -c "import open3d as o3d; \
mesh = o3d.geometry.TriangleMesh.create_sphere(); \
mesh.compute_vertex_normals(); \
o3d.visualization.draw(mesh, raw_mode=True)"
# Open3D CLI
open3d example visualization/draw
GitHub Issue: bug reports, feature requests, etc.
Forum: 关于Open3D使用的讨论。
Discord Chat: 在线聊天, 讨论,以及和他使用者或开发者合作。
@article{Zhou2018,
author = {Qian-Yi Zhou and Jaesik Park and Vladlen Koltun},
title = {{Open3D}: {A} Modern Library for {3D} Data Processing},
journal = {arXiv:1801.09847},
year = {2018},
}
Open3D的python包是通过PyPI发布的。
支持的Python版本:3.7、3.8、3.9、3.10
支持的操作系统:Ubuntu 18.04+、macOS 10.15+、Windows 10 (64-bit)
install: 一般来说,我们建议使用虚拟环境或conda环境。否则,根据配置的不同,Python 3可能需要使用pip3,或者需要使用–user选项来避免权限问题。比如说。
pip3 install open3d
# or
pip install --user open3d
# or
python3 -m pip install --user open3d
将复制一套完整的Python教程和数据集合,以演示Open3D Python接口的使用。
https://github.com/isl-org
https://github.com/isl-org/Open3D
python教程在上述链接的/examples/python中, 里面有一些ply格式的数据)(不是Master版本,其他版本),(搞不懂,我就想下载一个ply数据就找不到,外过网站的那个兔子一直下不下来,国内的都是要钱的,很无语)
系统要求:
C++14 compiler:
Ubuntu 18.04+: GCC 5+, Clang 7+
macOS 10.15+: XCode 8.0+
Windows 10 (64-bit): Visual Studio 2019+
CMake: 3.19+
Ubuntu (18.04 / 20.04):
Install with apt-get: see official APT repository
Install with snap: sudo snap install cmake --classic
Install with pip (run inside a Python virtualenv): pip install cmake
macOS: Install with Homebrew: brew install cmake
Windows: Download from: [CMake download page](https://cmake.org/download/)、
CUDA 10.1+ :可选择的,Open3D 通过 Linux 上的 CUDA 支持对越来越多的操作进行 GPU 加速。我们建议使用CUDA11.0, 以便与最近的GPU和可选的外部依赖(如Tensorflow或PyTorch)保持最佳兼容性。
如果有需要请查询官方文档安装CUDA toolkit 【https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html】
git clone https://github.com/isl-org/Open3D
# Only needed for Ubuntu
util/install_deps_ubuntu.sh
激活python的虚拟环境(virtualenv)或Conda环境。
…
Open3D-ML是Open3D为3D机器学习任务所实现的的扩展。他是在Open3D核心库上建立的,并且扩展她成为3D数据处理的机器学习工具。
本教程演示了点云的基本用法。
import open3d as o3d
import numpy as np
print("Load a ply point cloud, print it, and render it")
# 从文件中读取点云
# 下载地址为
# https://github.com/isl-org/open3d_downloads/releases/download/20220201-data/fragment.ply
# 链接:https://pan.baidu.com/s/1V3anL9caeDe6bWgHsrEpTg
# 提取码:5u7b
pcd = o3d.io.read_point_cloud('./fragment.ply')
print(pcd)
print(np.asarray(pcd.points))
# 可视化点云。使用鼠标/触控板从不同的视点查看几何图形。
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])
==read_point_cloud:==从一个文件中读取点云。它尝试根据扩展名解码文件。对于列表的文件类型,请参考File IO.
==draw_geometries:==可视化点云,使用鼠标或触摸板从不同的角度查看不同的点云。
It looks like a dense surface, 上图看起来像一个深度表面图(这半句翻译不准确,dense surface),但是,但它实际上是点云渲染成的表面。GUI支持各种键盘功能。例如,"-"键减少了点的大小(surfels)。
eg:
在可视化的图上按键“h”按键,在控制台会出现帮助(关于快捷键的技巧)更多可视化和自定义可视化的技巧参考 Visualization and Customized visualization., 此外macOS中的快捷键可能不能用,此时试试将python替换成pythonw。
[Open3D INFO] -- 鼠标控制 --
[Open3D INFO] 鼠标左键 + 拖 = 旋转
[Open3D INFO] Ctrl + 鼠标左键 + 拖拽 = 平移.
[Open3D INFO] 鼠标滑轮 = 放大/缩小.
[Open3D INFO] Shift + 鼠标左键 + 拖拽 : 滚动
[Open3D INFO] -- 键盘控制 --
[Open3D INFO] [,] 方括号 : 增加/减少视野。
[Open3D INFO] R : 重置视角。
[Open3D INFO] Ctrl/Cmd + C : 将当前视图状态复制到剪贴板。
[Open3D INFO] Ctrl/Cmd + V : 将当前视图状态粘贴。
[Open3D INFO] -- 普通控制 --
[Open3D INFO] Q, Esc : 退出窗口
[Open3D INFO] H : 打印帮助信息
[Open3D INFO] P, PrtScn : 捕获当前图像并以png和json保存信息
[Open3D INFO] D : 同P
[Open3D INFO] O : 对当前的渲染设置进行捕捉,以json的形式存储。
[Open3D INFO] Alt + Enter : 在全屏和窗口模式之间进行切换。
[Open3D INFO] -- 渲染模式控制--
[Open3D INFO] L : Turn on/off lighting(曝光??).
[Open3D INFO] +/- : 增加/减少 点的大小.
[Open3D INFO] Ctrl + +/- :增加/减少几何体的宽度::LineSet.(没有用)
[Open3D INFO] N : 打开和关闭点云正常的渲染
[Open3D INFO] S : 在网格平坦阴影和平滑阴影之间切换。
[Open3D INFO] W : 打开/关闭网状线框。(没什么用)
[Open3D INFO] B : Turn on/off back face rendering.
[Open3D INFO] I : Turn on/off image zoom in interpolation.
[Open3D INFO] T : Toggle among image render:
[Open3D INFO] no stretch / keep ratio / freely stretch.
[Open3D INFO] -- 颜色控制 --
[Open3D INFO] 0 - 默认渲染的点云
[Open3D INFO] 1 - Render point color.
[Open3D INFO] 2 - x coordinate as color.
[Open3D INFO] 3 - y coordinate as color.
[Open3D INFO] 4 - z coordinate as color.
[Open3D INFO] 9 - normal as color.
[Open3D INFO] Ctrl + 0..4,9: Set mesh color option.
[Open3D INFO] 0 - Default behavior, render uniform gray color.
[Open3D INFO] 1 - Render point color.
[Open3D INFO] 2 - x coordinate as color.
[Open3D INFO] 3 - y coordinate as color.
[Open3D INFO] 4 - z coordinate as color.
[Open3D INFO] 9 - normal as color.
[Open3D INFO] Shift + 0..4 : Color map options.
[Open3D INFO] 0 - Gray scale color.
[Open3D INFO] 1 - JET color map.
[Open3D INFO] 2 - SUMMER color map.
[Open3D INFO] 3 - WINTER color map.
[Open3D INFO] 4 - HOT color map.
[Open3D INFO]
Process finished with exit code 0
import open3d as o3d
import numpy as np
print("Load a ply point cloud, print it, and render it")
# 从文件中读取点云
pcd = o3d.io.read_point_cloud(r'D:\ros\data\open3D_test\data\fragment.ply')
print(pcd)
print(np.asarray(pcd.points))
print("Downsample the point cloud with a voxel of 0.05")
downpcd = pcd.voxel_down_sample(voxel_size=0.05)
# 可视化点云。使用鼠标/触控板从不同的视点查看几何图形。
o3d.visualization.draw_geometries([downpcd],
zoom=0.3412,
front=[0.4257, -0.2125, -0.8795],
lookat=[2.6172, 2.0475, 1.532],
up=[-0.0694, -0.9768, 0.2024])
import open3d as o3d
import numpy as np
print("Load a ply point cloud, print it, and render it")
# 从文件中读取点云
pcd = o3d.io.read_point_cloud(r'D:\ros\data\open3D_test\data\fragment.ply')
print(pcd)
print(np.asarray(pcd.points))
print("Downsample the point cloud with a voxel of 0.05")
downpcd = pcd.voxel_down_sample(voxel_size=0.05)
print("Recompute the normal of the downsampled point cloud")
downpcd.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.1, max_nn=30))
o3d.visualization.draw_geometries([downpcd],
zoom=0.3412,
front=[0.4257, -0.2125, -0.8795],
lookat=[2.6172, 2.0475, 1.532],
up=[-0.0694, -0.9768, 0.2024],
point_show_normal=True)
estimate_normals: 计算每个点的法线。该函数找到相邻的点,并利用协方差分析计算相邻点的主轴。
该函数将KDTreeSearchParamHybrid类的一个实例作为参数。两个关键参数radius = 0.1和max_nn = 30指定了搜索半径和最大近邻。它有10cm的搜索半径,并且只考虑最多30个邻居以节省计算时间。
Note:
协方差分析算法产生了两个相反的方向作为候选法线。在不知道几何体的全局结构的情况下,两个方向都可能是正确的。这就是所谓的法线方向问题。如果原法线存在,Open3D会尝试将法线的方向与原法线对齐。否则,Open3D会做一个随机猜测。如果方向是一个问题,就需要进一步调用orient_normals_to_align_with_direction和orient_normals_towards_camera_location等方向函数。
print("Print a normal vector of the 0th point")
print(downpcd.normals[0])
# 法线向量转化为array
print("Print the normal vectors of the first 10 points")
print(np.asarray(downpcd.normals)[:10, :])
import open3d as o3d
import numpy as np
# 从文件中读取点云
print("Load a polygon volume and use it to crop the original point cloud")
pcd = o3d.io.read_point_cloud("./data/fragment.ply")
###################################################
vol = o3d.visualization.read_selection_polygon_volume("./data/cropped.json")
chair = vol.crop_point_cloud(pcd)
###################################################
o3d.visualization.draw_geometries([chair],
zoom=0.7,
front=[0.5439, -0.2333, -0.8060],
lookat=[2.4615, 2.1331, 1.338],
up=[-0.1781, -0.9708, 0.1608])
read_selection_polygon_volume:读取指定多边形选择区域的json文件
vol.crop_point_cloud(pcd):过滤出点云
import open3d as o3d
import numpy as np
# 从文件中读取点云
print("Load a polygon volume and use it to crop the original point cloud")
pcd = o3d.io.read_point_cloud("./data/fragment.ply")
vol = o3d.visualization.read_selection_polygon_volume("./data/cropped.json")
chair = vol.crop_point_cloud(pcd)
###################################################
chair.paint_uniform_color([1, 0.706, 0])
###################################################
o3d.visualization.draw_geometries([chair],
zoom=0.7,
front=[0.5439, -0.2333, -0.8060],
lookat=[2.4615, 2.1331, 1.338],
up=[-0.1781, -0.9708, 0.1608])
paint_uniform_color: 将所有点云绘制成一个标准颜色。RGB颜色的范围是【0. 1】
12. 点云距离(Point cloud distance)
compute_point_cloud_distance方法计算源点云到目标点云之间的距离等。它为源点云中的每个点计算到目标点云中最近点的距离。
在下面的例子中,我们使用这个函数来计算两个点云之间的差异。请注意,这种方法也可以用来计算两个点云之间的Chamfer距离。
import open3d as o3d
import numpy as np
# 从文件中读取点云
print("Load a polygon volume and use it to crop the original point cloud")
pcd = o3d.io.read_point_cloud("./data/fragment.ply")
vol = o3d.visualization.read_selection_polygon_volume("./data/cropped.json")
chair = vol.crop_point_cloud(pcd)
chair.paint_uniform_color([1, 0.706, 0])
###################################################
dists = pcd.compute_point_cloud_distance(chair)
dists = np.asarray(dists)
ind = np.where(dists > 0.01)[0]
pcd_without_chair = pcd.select_by_index(ind)
###################################################
o3d.visualization.draw_geometries([pcd_without_chair],
zoom=0.7,
front=[0.5439, -0.2333, -0.8060],
lookat=[2.4615, 2.1331, 1.338],
up=[-0.1781, -0.9708, 0.1608])
14. 边界体积 (Bounding volumes)
PointCloud 几何类型与 Open3D 中的所有其他几何类型一样具有边界体积。目前,Open3D 实现了一个 AxisAlignedBoundingBox 和一个 OrientedBoundingBox,它们也可用于裁剪几何图形。
import open3d as o3d
import numpy as np
# 从文件中读取点云
print("Load a polygon volume and use it to crop the original point cloud")
pcd = o3d.io.read_point_cloud("./data/fragment.ply")
vol = o3d.visualization.read_selection_polygon_volume("./data/cropped.json")
chair = vol.crop_point_cloud(pcd)
chair.paint_uniform_color([1, 0.706, 0])
# 求解距离,根据距离索引点云
dists = pcd.compute_point_cloud_distance(chair)
dists = np.asarray(dists)
ind = np.where(dists > 0.01)[0]
pcd_without_chair = pcd.select_by_index(ind)
###################################################
# 体积
aabb = chair.get_axis_aligned_bounding_box()
aabb.color = (1, 0, 0)
obb = chair.get_oriented_bounding_box()
obb.color = (0, 1, 0)
###################################################
o3d.visualization.draw_geometries([chair, aabb, obb],
zoom=0.7,
front=[0.5439, -0.2333, -0.8060],
lookat=[2.4615, 2.1331, 1.338],
up=[-0.1781, -0.9708, 0.1608])
16. 凸包(Convex hull)
点云的凸包是包含所有点的最小凸集。Open3D 包含计算点云凸包的方法 compute_convex_hull。该实现基于 Qhull。
在下面的示例代码中,我们首先从一个网格中对点云进行采样,并计算出凸壳,然后以三角形网格的形式返回。然后,我们将凸体可视化为一个红色的LineSet。
import open3d as o3d
import numpy as np
# 从文件中读取点云
print("Load a polygon volume and use it to crop the original point cloud")
pcd = o3d.io.read_point_cloud("./data/fragment.ply")
mesh = o3d.io.read_triangle_mesh("./data/BunnyMesh.ply")
mesh.compute_vertex_normals()
vol = o3d.visualization.read_selection_polygon_volume("./data/cropped.json")
chair = vol.crop_point_cloud(pcd)
chair.paint_uniform_color([1, 0.706, 0])
# 求解距离,根据距离索引点云
dists = pcd.compute_point_cloud_distance(chair)
dists = np.asarray(dists)
ind = np.where(dists > 0.01)[0]
pcd_without_chair = pcd.select_by_index(ind)
# 体积
aabb = chair.get_axis_aligned_bounding_box()
aabb.color = (1, 0, 0)
obb = chair.get_oriented_bounding_box()
obb.color = (0, 1, 0)
###################################################
# 凸包
pcl = mesh.sample_points_poisson_disk(number_of_points=2000)
hull, _ = pcl.compute_convex_hull()
hull_ls = o3d.geometry.LineSet.create_from_triangle_mesh(hull)
hull_ls.paint_uniform_color((1, 0, 0))
o3d.visualization.draw_geometries([pcl, hull_ls])
###################################################
17. DBSCAN 聚类(DBSCAN clustering)
给定一个来自例如深度传感器的点云,我们想把局部的点云聚类在一起。为了这个目的,我们可以使用聚类算法。Open3D实现了DBSCAN[Ester1996],这是一种基于密度的聚类算法。该算法在cluster_dbscan中实现,需要两个参数:eps定义了集群中与邻居的距离,min_points定义了形成一个集群所需的最小点数。该函数返回标签,其中标签-1表示噪声.
import open3d as o3d
import numpy as np
import matplotlib as plt
# 从文件中读取点云
print("Load a polygon volume and use it to crop the original point cloud")
pcd = o3d.io.read_point_cloud("./data/fragment.ply")
with o3d.utility.VerbosityContextManager(
o3d.utility.VerbosityLevel.Debug) as cm:
labels = np.array(
pcd.cluster_dbscan(eps=0.02, min_points=10, print_progress=True))
max_label = labels.max()
print(f"point cloud has {max_label + 1} clusters")
colors = plt.cm.get_cmap("tab20")(labels / (max_label if max_label > 0 else 1))
colors[labels < 0] = 0
pcd.colors = o3d.utility.Vector3dVector(colors[:, :3])
o3d.visualization.draw_geometries([pcd],
zoom=0.455,
front=[-0.4999, -0.1659, -0.8499],
lookat=[2.1813, 2.0619, 2.0999],
up=[0.1204, -0.9852, 0.1215])
18. 平面分割(plane segmentation)
Open3D也支持使用RANSAC对点云中的几何基元进行分割。为了找到点云中支持度最大的平面,我们可以使用 segment_plane。
该方法有三个参数:
distance_threshold定义了一个点与一个估计的平面的最大距离,以便被认为是一个离群点;r
ansac_n定义了为估计一个平面而随机采样的点的数量;
num_iterations定义了一个随机平面被采样和验证的频率。
然后,该函数返回平面为(a,b,c,d),这样对于平面上的每个点(x,y,z),我们有ax+by+cz+d=0。
import open3d as o3d
import numpy as np
import matplotlib as plt
# 从文件中读取点云
print("Load a polygon volume and use it to crop the original point cloud")
pcd = o3d.io.read_point_cloud("./data/fragment.ply")
plane_model, inliers = pcd.segment_plane(distance_threshold=0.01,
ransac_n=3,
num_iterations=1000)
[a, b, c, d] = plane_model
print(f"Plane equation: {a:.2f}x + {b:.2f}y + {c:.2f}z + {d:.2f} = 0")
inlier_cloud = pcd.select_by_index(inliers)
inlier_cloud.paint_uniform_color([1.0, 0, 0])
outlier_cloud = pcd.select_by_index(inliers, invert=True)
o3d.visualization.draw_geometries([inlier_cloud, outlier_cloud],
zoom=0.8,
front=[-0.4999, -0.1659, -0.8499],
lookat=[2.1813, 2.0619, 2.0999],
up=[0.1204, -0.9852, 0.1215])
19. 隐藏点移除(Hidden point removal)
想象一下,你想从一个给定的视点渲染一个点云,但是背景中的点因为没有被其他点遮挡而漏到了前景中。为了这个目的,我们可以应用一个隐藏点去除算法。在Open3D中,实现了[Katz2007]的方法,在没有表面重建或法线估计的情况下,从一个给定的视图中接近点云的可见性。
import open3d as o3d
import numpy as np
import matplotlib as plt
print("Convert mesh to a point cloud and estimate dimensions")
mesh = o3d.io.read_triangle_mesh("./data/ArmadilloMesh.ply")
mesh.compute_vertex_normals()
pcd = mesh.sample_points_poisson_disk(5000)
diameter = np.linalg.norm(
np.asarray(pcd.get_max_bound()) - np.asarray(pcd.get_min_bound()))
o3d.visualization.draw_geometries([pcd])
#################################################################
print("Define parameters used for hidden_point_removal")
camera = [0, 0, diameter]
radius = diameter * 100
print("Get all points that are visible from given view point")
_, pt_map = pcd.hidden_point_removal(camera, radius)
print("Visualize result")
pcd = pcd.select_by_index(pt_map)
o3d.visualization.draw_geometries([pcd])
#################################################################