open3d 和numpy 交互

open3d和numpy

numpy转open3D需要借助Vector3dVector函数,这样可以直接赋值与open3d.PointCloud.points,具体操作如下,假设xyz、nxnynz、rgb分别是一个n*3numpy数组,则对于点数,法向量和颜色的转换都可以借助Vector3dVector函数,具体操作如下:

import numpy as np
import open3D as o3d
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(xyz)
pcd.normals = o3d.utility.Vector3dVector(nxnynz)
pcd.colors = o3d.utility.Vector3dVector(rgb)
import numpy as np
import open3d as o3d
# Load saved point cloud and visualize it
pcd_load = o3d.io.read_point_cloud("../../TestData/sync.ply")

# convert Open3D.o3d.geometry.PointCloud to numpy array
xyz_load = np.asarray(pcd_load.points)
o3d.visualization.draw_geometries([pcd_load])

从numpy中创建mesh

def show_mesh(verts,faces):
    mesh=o3d.geometry.TriangleMesh.create_coordinate_frame()
    mesh.clear()
    mesh.vertices=o3d.utility.Vector3dVector(verts)
    mesh.triangles=o3d.utility.Vector3iVector(faces)
    mesh.compute_vertex_normals()
    frame=o3d.geometry.TriangleMesh.create_coordinate_frame()
    frame.scale(2, center=(0,0,0))
    o3d.visualization.draw_geometries([mesh,frame])

显示mesh

def show_mesh(verts,faces):
    mesh=o3d.geometry.TriangleMesh.create_coordinate_frame()
    # mesh.clear()
    mesh.vertices=o3d.utility.Vector3dVector(verts)
    mesh.triangles=o3d.utility.Vector3iVector(faces)
    mesh.compute_vertex_normals()
    frame=o3d.geometry.TriangleMesh.create_coordinate_frame()
    frame.scale(0.5, center=(0,0,0))
    o3d.visualization.draw_geometries([mesh,frame],mesh_show_back_face=True)

mesh_show_back_face=True如果不设置的话模型中会有一些空洞

点云到mesh

laptop_points=mean_points[4]
pcd=o3d.geometry.PointCloud()
pcd.points=o3d.utility.Vector3dVector(laptop_points)

# visutil.show_3d(laptop_points,laptop_points,[0,0,0],[0,0,0])

# laptop_mesh,_=pcd.compute_convex_hull()
tetra_mesh,pt_map=o3d.geometry.TetraMesh.create_from_point_cloud(pcd)

# for alpha in np.logspace(np.log10(0.5), np.log10(0.01), num=4):
alpha=0.136
print(f"alpha={alpha:.3f}")
laptop_mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(
    pcd, alpha, tetra_mesh, pt_map)
laptop_mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([laptop_mesh], mesh_show_back_face=True)

点云处理

一、无穷值和非数点的剔除

该功能可筛选出点云中坐标值为以下两种类型的点:

坐标值为NaN(not a number,非数)的点,通常为未定义或不可表示的坐标值点。坐标值为Infinite(无穷大)的点,包含正向和负向的无穷大坐标值点。

import open3d as o3d

pcd = o3d.io.read_point_cloud(path)  # path为文件路径
pcd_new = o3d.geometry.PointCloud.remove_non_finite_points(
                        pcd, remove_nan = True, remove_infinite = False)
                        
  #remove_nan和remove_infinite参数均包含两个类型值,True和False分别为剔除非数点和无穷值点

二、孤点滤波

此处孤点滤波就是半径滤波,在点云数据中,指定每个的点一定范围内周围至少要有足够多的近邻。例如,如果指定至少要有1个邻居,只有黄色的点会被删除,如果指定至少要有2个邻居,黄色和绿色的点都将被删除。

pcd_new = o3d.geometry.PointCloud.remove_radius_outlier(pcd, knn, radius)

#knn参数为选择邻近点个数,radius参数为设置的半径

三、统计学滤波

统计学滤波用于去除明显离群点。离群点特征是在空间中分布稀疏,考虑到离群点的特征,则可以定义某处点云小于某个密度,既点云无效。对每个点的邻域进行一个统计分析,并修剪掉一些不符合标准的点。具体方法为在输入数据中对点到临近点的距离分布的计算,对每一个点,计算它到所有临近点的平均距离(假设得到的结果是一个高斯分布,其形状是由均值和标准差决定),那么平均距离在标准范围之外的点,可以被定义为离群点并从数据中去除。特点:主要是根据密度去除离群点,对密度差异较大的离群点去除效果较好。

pcd_new = o3d.geometry.PointCloud.remove_statistical_outlier(pcd, knn, std)


#knn参数为选择邻近点个数,std参数为设置的标准差阈值

四、RANSAC分割平面

RANSAC(Random Sample Consensus)是根据一组包含异常数据的样本数据集,计算出数据的数学模型参数,得到有效样本数据的算法。

RANSAC算法的基本假设是样本中包含正确数据(inliers,可以被模型描述的数据),也包含异常数据(outliers,偏离正常范围很远、无法适应数学模型的数据),即数据集中含有噪声。这些异常数据可能是由于错误的测量、错误的假设、错误的计算等产生的。同时RANSAC也假设,给定一组正确的数据,存在可以计算出符合这些数据的模型参数的方法。

在拟合平面(地面)这一需求上,平面的凹凸点(小的坑洼)是有效数据,但对所需平面来说有一定的偏移。而大的凹凸,比如地面上的障碍物、地面的深坑,这些都是偏移量过大的无效数据。最小二乘拟合,旨在照顾所有人的想法,对所有数据进行拟合,在无效数据多且偏移量大的情况下,拟合效果不好。而RANSAC拟合,旨在照顾多数人的意愿,对主体数据进行拟合,手动设置一个阈值,同拟合平面的距离超过阈值的点,就被判定为无效数据。随机拟合多个平面,选取平面内数据点最多的平面,或者说,无效数据最少的平面,作为拟合出的结果。根据如上思路,RANSAC在拟合平面这一需求上,可以得到更准确的结果。

plane_model, inliers = pcd.segment_plane(distance_threshold=dis, ransac_n=rnn, num_iterations=n)


# distance_threshold为距离阈值参数,ransac_n为RANSAC迭代的点数,num_iterations为最大迭代次数
pcd_in = pcd.select_by_index(inliers)  # RANSAC分割后的内部点云(拟合平面点)
pcd_out = pcd.select_by_index(inliers, invert=True)  # RANSAC分割后的外部点云(拟合平面之外的点

load obj save ply

for id,file in enumerate(nut_file_list+screw_file_list+hnm_file_list):
    id2file[id+1]=file
    file2id[file]=id+1
    out=os.path.join(out_path,'{}.ply'.format(id+1))
    ms=pymeshlab.MeshSet()
    ms.load_new_mesh(os.path.join(cat_path,file))
    m=ms.current_mesh()
    bbox=m.bounding_box()
    max=bbox.max()
    min=bbox.min()
    ms.save_current_mesh(out)

    mesh=trimesh.load(out)
    quad=mesh.faces
    bbox = mesh.bounding_box.bounds
    loc = (bbox[0] + bbox[1]) / 2
    mesh.apply_translation(-loc)
    result = trimesh.exchange.ply.export_ply(mesh, encoding='ascii')
    output_file = open(out, "wb+")
    output_file.write(result)
    output_file.close()
    # trimesh.exchange.export.exp

trimesh

在trimesh load 过程中会自动merge一些靠近的顶点,导致model 不watertight 解决方法是设置process=False

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值