三维点云处理02-surface_normal代码实现

三维点云处理02-surface_normal代码实现

基础知识点
surface_normal是PCA的应用,基础知识点与PCA相同,可以查看PCA
代码实现
#!/usr/bin/python3

import os
import numpy as np
from pyntcloud import PyntCloud
import open3d as o3d

def PCA(data,sort=True):
	'''
	PCA函数实现:
	输入:
	data:点云数据
	sort:是否排序
	输出:
	w:特征值
	v:特征向量
	'''
	
	#获取点云总数
	N = data.shape[0]
	#将点云数据转为numpy
	X = data.to_numpy()
	
	#PCA-01:将点云进行归一化处理
	mu = np.mean(X,axis=0)
	X_normalized = X - mu
	
	#PCA-02:对归一化后的点云求协方差矩阵(因为数据为Nx3,即列为属性,行为观测,所以rowvar=False, bias=True表示有偏估计)
	func = np.cov
	H = func(X_normalized, rowvar=False, bias=True)
	
	#PCA-03:对协方差矩阵进行SVD分解,获得特征值和特征向量
	eigenvalues, eigenvectors = np.linalg.eig(H)
	
	#PCA-04:获得特征值从大到小排序的索引,然后根据特征值排序索引,对特征值和特征向量进行排序
	if sort:
		sort = eigenvalues.argsort()[::-1]
		eigenvalues = eigenvalues[sort]
		eigenvectors = eigenvectors[:,sort] #列对应的是特征向量
	
	return eigenvalues,eigenvectors
	
def get_surface_normals(pcd,points,knn=5):
	'''
	获得点云的法向量
	'''
	#SN-01:使用输入点云建立KDTree,通过调用open3d中的KDTree函数实现
	pcd_tree = o3d.geometry.KDTreeFlann(pcd)
	
	#获得输入点云总数
	N = len(pcd.points)
	#存放点云法向量的list
	normals = []
	
	#SN-02:通过KDTree获得每个点knn个最近邻,对该邻域内所有点进行主成分分析,获得最不重要的特征向量即为法向量
	for i in range(N):
		#idx:当前点的5个最近邻的idx
		[k,idx,_] = pcd.tree.search_knn_vector_3d(pcd.points[i],knn)
		#调用PCA函数获得当前邻域内点云的特征值和特征向量
		w,v = PCA(points.iloc[idx])
		#最小的特征值对应的特征向量即为法向量
		normals.append(v[:,3])
	
	return np.array(normals,dtype=np.float64)
	
def main(point_cloud_filename):
	'''
	主函数:
	输入:点云文件名
	'''
	#从文件中加载点云
	point_cloud_pynt = PyntCloud.from_file(point_cloud_filename)
	point_cloud_o3d = point_cloud_pynt.to_instance("open3d",mesh=False)
	#从点云中获取点
	points = point_cloud_pynt.points
	
	#调用子函数获得点云的法向量
	normals = get_surface_normals(point_cloud_o3d,points)
	
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值