来源:
Docs version 0.15.1
Point cloud — Open3D 0.15.1 documentation
点云的基础使用教程
读取点云文件并可视化:
import open3d as o3d
import numpy as np
#读取点云文件(.ply、.pcd、.xzy等格式)
pcd = o3d.io.read_point_cloud(filepath)
#可视化点云,用鼠标可以选择视图,+-(小键盘区可能不行,用主键盘区的+-)可以修改点大小
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 从文件读取点云。支持的文件类型有.ply, .pcd, .xyz等。
draw_geometries 可视化点云。可以在可视化窗口中用鼠标切换视角。也可以用键盘进行一些操作,如-可以减小点的大小。按H获取按键说明。
open3D 自带了一些点云数据,用下面的方法可以从github下载点云文件:
print("Load a ply point cloud, print it, and render it")
ply_point_cloud = o3d.data.PLYPointCloud()
pcd = o3d.io.read_point_cloud(ply_point_cloud.path)
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])
由于github直接连不上去(网络经常抽风),这里手动复制下载地址通过代理下载(fragment.ply)。
import open3d as o3d
import numpy as np
print("Load a ply point cloud, print it, and render it")
ply_point_cloud_path = r'fragment.ply'
#读取ply文件
pcd = o3d.io.read_point_cloud(ply_point_cloud_path)
print(pcd)
print(np.asarray(pcd.points))
#可视化ply文件
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])

体素下采样使用规格体素网格进行标准下采样。通常作为点云任务的预处理。算法有两步:
1.将点放入体素
2.每个被占用的体素通过平均内部的所有点来生成一个点。
import open3d as o3d
import numpy as np
print("Load a ply point cloud, print it, and render it")
ply_point_cloud_path = r'fragment.ply'
#读取ply文件
pcd = o3d.io.read_point_cloud(ply_point_cloud_path)
print(pcd)
print("Downsample the point cloud with a voxel of 0.05")
downpcd = pcd.voxel_down_sample(voxel_size=0.05)
print(downpcd)
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])

点的法线估计。按N查看法线。- +可以控制法线显示的长度。
estimate_normals 计算每个点的法线,该函数使用协方差分析查找相邻点并计算相邻点的主轴。
该函数将类KDTreeSearchParamHybrid的实例作为参数。两个关键参数radius = 0.1 max_nn = 30,指定搜索半径和最大最近邻数。示例的搜索半径为10cm,最大考虑30个邻居,以节省计算时间。
import open3d as o3d
import numpy as np
print("Load a ply point cloud, print it, and render it")
ply_point_cloud_path = r'fragment.ply'
#读取ply文件
pcd = o3d.io.read_point_cloud(ply_point_cloud_path)
print(pcd)
print("Downsample the point cloud with a voxel of 0.05")
downpcd = pcd.voxel_down_sample(voxel_size=0.05)
print(downpcd)
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)
通过downpcd.normals[idx] 访问法线
print("Print a normal vector of the 0th point")
print(downpcd.normals[0])
要查看其他变量,请使用help(downpcd) 。法线数组可以使用 np.asarray转换为 numpy 数组。
print("Print the normal vectors of the first 10 points")
print(np.asarray(downpcd.normals)[:10,:])
import open3d as o3d
print("Load a polygon volume and use it to crop the original point cloud")
demo_crop_data_point_cloud_path = r'fragment.ply'
demo_crop_data_cropped_json_path = r'cropped.json'
pcd = o3d.io.read_point_cloud(demo_crop_data_point_cloud_path)
vol = o3d.visualization.read_selection_polygon_volume(demo_crop_data_cropped_json_path)
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) 过滤点,只保留椅子。

paint_uniform_color 将所有点颜色变为统一颜色。 颜色形式是RGB , 值在[0, 1]范围 。
#Paint 涂色
print("Paint chair")
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])

Open3D 提供了计算从源点云到目标点云的距离的方法compute_point_cloud_distance,它为源点云中的每个点计算到目标点云中最近点的距离。
在下面的示例中,我们使用该函数来计算两个点云之间的差异。请注意,此方法还可用于计算两个点云之间的倒角(Chamfer)距离。
import open3d as o3d
import numpy as np
# Load data
demo_crop_data_point_cloud_path = r'fragment.ply'
demo_crop_data_cropped_json_path = r'cropped.json'
pcd = o3d.io.read_point_cloud(demo_crop_data_point_cloud_path)
vol = o3d.visualization.read_selection_polygon_volume(demo_crop_data_cropped_json_path)
chair = vol.crop_point_cloud(pcd)
#计算距离,去除椅子
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.3412,
front=[0.4257, -0.2125, -0.8795],
lookat=[2.6172, 2.0475, 1.532],
up=[-0.0694, -0.9768, 0.2024])

PointCloud几何类型与 Open3D 中的所有其他几何体类型一样具有边界体积块(Bounding volumes)。目前,Open3D 实现了AxisAlignedBoundingBox和OrientedBoundingBox,也可用于裁剪几何图形。
#轴对齐边框
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])

点云的凸壳是包含所有点的最小凸集。Open3D 包含计算点云的凸壳的方法compute_convex_hull。该实现基于 Qhull。
在下面的示例代码中,我们首先从网格中对点云进行采样,并计算作为三角形网格返回的凸壳。然后,我们将凸壳可视化为红色。
import open3d as o3d
bunny_path = r'BunnyMesh.ply'
mesh = o3d.io.read_triangle_mesh(bunny_path)
mesh.compute_vertex_normals()
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])

给定点云,我们希望将局部点云聚集在一起。为此,我们可以使用聚类算法。Open3D实现了DBSCAN [Ester1996],这是一种基于密度的聚类算法。该算法在 cluster_dbscan中实现,需要两个参数:eps定义到聚类中相邻元素的距离,min_points定义形成聚类所需的最小点数。该函数返回lebels ,其中标签-1指噪声。
import open3d as o3d
import numpy as np
from matplotlib import pyplot as plt
ply_point_cloud_path = 'fragment.ply'
pcd = o3d.io.read_point_cloud(ply_point_cloud_path)
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.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])
此算法预计算所有点的 epsilon 半径内的所有邻居。如果所选的 epsilon 太大,则可能需要大量内存。

Open3D 还支持使用 RANSAC 对点云中的几何基元进行分割。要查找点云中支撑最大的平面,我们可以使用segment_plane。该方法有三个参数:distance_threshold定义点到估计平面的最大距离才能被视为入值(inlier),ransac_n定义随机采样点数,以及num_iterations定义随机平面采样和验证的频率。然后,该函数返回平面(a,b,c,d),以便对于平面上的每个点(x,y,z),我们都有ax+by+cz+d=0 。该函数进一步返回inlier点的索引列表。
import open3d as o3d
pcd_point_cloud_path = r'fragment.pcd'
pcd = o3d.io.read_point_cloud(pcd_point_cloud_path)
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])

假设您想从给定的视点渲染点云,但背景中的点泄漏到前景中,因为它们没有被其他点遮挡。为此,我们可以应用隐藏点删除算法。在 Open3D 中,[实现了 Katz2007] 的方法,该方法从给定视图近似点云的可见性,而无需表面重建或法向估计。
import open3d as o3d
import numpy as np
print("Convert mesh to a point cloud and estimate dimensions")
armadillo_path = r'ArmadilloMesh.ply'
mesh = o3d.io.read_triangle_mesh(armadillo_path)
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])


无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u
之前说过10之后的版本没有3dScan了,所以还是9.8的版本或者之前更早的版本。 3d物体扫描需要先下载扫描的APK进行扫面。首先要在手机上装一个扫描程序,扫描现实中的三维物体,然后上传高通官网,在下载成UnityPackage类型让Unity能够使用这个扫描程序可以从高通官网上进行下载,是一个安卓程序。点到Tools往下滑,找到VuforiaObjectScanner下载后解压数据线连接手机,将apk文件拷入手机安装然后刚才解压文件中的Media文件夹打开,两个PDF图打印第一张A4-ObjectScanningTarget.pdf,主要是用来辅助扫描的。好了,接下来就是扫描三维物体。将瓶
一段时间以来,我一直在使用open_uri下拉ftp路径作为数据源,但突然发现我几乎连续不断地收到“530抱歉,允许的最大客户端数(95)已经连接。”我不确定我的代码是否有问题,或者是否是其他人在访问服务器,不幸的是,我无法真正确定谁有问题。本质上,我正在读取FTPURI:defself.read_uri(uri)beginuri=open(uri).readuri=="Error"?nil:urirescueOpenURI::HTTPErrornilendend我猜我需要在这里添加一些额外的错误处理代码...我想确保我采取一切预防措施来关闭所有连接,这样我的连接就不是问题所在,但是我
标题本身就说明了......read_timeout和open_timeout之间有什么区别? 最佳答案 open_timeout是您愿意等待“打开连接”的时间。在TCP上下文中,在放弃尝试并引发超时错误之前等待握手完成的时间量。read_timeout您可能会猜到,是您愿意等待从连接方接收到某些数据的时间。一个例子可能会清楚地说明这一点:在SOAPoverHTTPoverTCP上下文中(简化):您尝试与服务器建立TCP连接。如果建立连接的时间比open_timeout长,则放弃连接尝试并引发/发出/返回超时错误。如果连接成功,您发
我是Ruby的新手,我正在尝试以如下方式打开文件:#!/usr/bin/envrubydata_file='~/path/to/file.txt'file=File.open(data_file,'r')但是我得到“没有这样的文件或目录”(该文件确实存在于该目录中)。如果我将该文件路径作为命令行参数,它会起作用,例如:#!/usr/bin/envrubyfile=File.open(ARGV[0],'r')然后从命令行运行,如:rubyscript.cgi~/path/to/file.txt关于如何让它以第一种方式工作的任何想法? 最佳答案
关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭9年前。Improvethisquestion是否有适用于这些的3d游戏引擎?
如何获取外部命令的输出并从中提取值?我有这样的东西:stdin,stdout,stderr,wait_thr=Open3.popen3("#{path}/foobar",configfile)if/exit0/=~wait_thr.value.to_srunlog.puts("Foobarexitednormally.\n")puts"Testcompleted."someoutputvalue=stdout.read("TX.*\s+(\d+)\s+")puts"Outputvalue:"+someoutputvalueend我没有在标准输出上使用正确的方法,因为Ruby告诉我它不能
关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。关于您编写的代码问题的问题必须在问题本身中描述具体问题—并且包括有效代码以重现它。参见SSCCE.org寻求指导。关闭8年前。Improvethisquestion我是Rails的新手。我正在制作一个网络应用程序,我在其中使用nokogiri搜索不同的网站以从中提取文本。所以在Gemfile中,我写了require'nokogiri'和'open-uri',但是当我捆绑安装时我得到这个错误:Couldnotfindgem'open-uri(>=0)ruby'inthegemsavailableon