估计点云法向量最常用的方式是搜索某点领域的小范围点,利用最小二乘法估计平面,再求一个垂直的向量,就是法向量。原理有很多帖子,可以自行搜索。
下面是代码认真看里面的标注,其中法向量是固定的,一个平面法向量只有向上和向下的区别,里面有俩种设定的方式:
- orient_normals_to_align_with_direction,与某个轴的方向相同。
- orient_normals_towards_camera_location,法相量全部指向指定的相机位置。
里面还有三种不同的法向量给估计方式,混合搜索 KNN搜索 半径搜索,可以自行选择。
与z轴的方向相同
方向指向原点
# @Description: <Open3D估计法向量,可视化,存储为文件>
import open3d as o3d
import os
import numpy as np
pcd = o3d.io.read_point_cloud("..//chair_0002 - Cloud.pcd")
pcd.paint_uniform_color([0.5, 0.5, 0.5]) # 把所有点渲染为灰色
print(pcd)
mesh_frame = o3d.geometry.TriangleMesh.create_coordinate_frame(size=1, origin=[0, 0, 0]) #定义坐标轴
# print(o3d.np.asarray(pcd.points)) # 输出点的三维坐标
o3d.visualization.draw_geometries([pcd,mesh_frame], "Open3D origin points", width=800, height=600, left=50, top=50,
point_show_normal=False, mesh_show_wireframe=False,
mesh_show_back_face=False)
# 混合搜索 KNN搜索 半径搜索
# downpcd.estimate_normals(
# search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.01, max_nn=20)) # 计算法线,搜索半径1cm,只考虑邻域内的20个点
pcd.estimate_normals(
search_param=o3d.geometry.KDTreeSearchParamKNN(knn=20)) # 计算法线,只考虑邻域内的20个点
# downpcd.estimate_normals(
# search_param=o3d.geometry.KDTreeSearchParamRadius(radius=0.01)) # 计算法线,搜索半径1cm,只考虑邻域内的20个点
#o3d.geometry.PointCloud.orient_normals_to_align_with_direction(pcd, orientation_reference=np.array([0.0, 0.0, 1.0])) #设定法向量在z轴方向上,全部z轴正方向一致
#o3d.geometry.PointCloud.orient_normals_towards_camera_location(pcd, camera_location=np.array([0., 0., 0.])) #让法向量的方向都指向给定的相机位置
o3d.visualization.draw_geometries([pcd,mesh_frame], "Open3D normal estimation", width=800, height=600, left=50, top=50,
point_show_normal=True, mesh_show_wireframe=False,
mesh_show_back_face=False) # 可视化法线
原始显示