点云学习1

# 实现PCA分析和法向量计算,并加载数据集中的文件进行验证

 

import open3d as o3d 

import os

import numpy as np

from pyntcloud import PyntCloud


 

def make_line_pcd(dv,meanData):

    '''

    定义三角形的点云

    :return:

    '''

    L = 400

    v0 = dv[:,0]

    v1 = dv[:,1]

    v2 = dv[:,2]

 

    triangle_points = np.array([[meanData[0],meanData[1],meanData[2]],  [v0[0]*L, v0[1]*L, v0[2]*L],

                                                                        [v1[0]*L/2, v1[1]*L/2, v1[2]*L/2],

                                                                        [v2[0]*L/3, v2[1]*L/3, v2[2]*L/3]], dtype=np.float32)

    lines = [[0, 1],[0,2],[0,3]]  # Right leg

    colors = [[0, 0, 1],[1, 0, 1],[0, 0, 0]]  # Default blue

    # 定义三角形的三个角点

    #point_pcd = open3d.geometry.PointCloud()  # 定义点云

    #point_pcd.points = o3d.utility.Vector3dVector(triangle_points)

 

    # 定义三角形三条连接线

    line_pcd = o3d.geometry.LineSet()

    line_pcd.lines = o3d.utility.Vector2iVector(lines)

    line_pcd.colors = o3d.utility.Vector3dVector(colors)

    line_pcd.points =o3d.utility.Vector3dVector(triangle_points)

 

    return line_pcd



 

# 功能:计算PCA的函数

# 输入:

#     data:点云,NX3的矩阵

#     correlation:区分np的cov和corrcoef,不输入时默认为False

#     sort: 特征值排序,排序是为了其他功能方便使用,不输入时默认为True

# 输出:

#     eigenvalues:特征值

#     eigenvectors:特征向量

 

def PCA(data, correlation=False, sort=True):

    # 作业1

    # 屏蔽开始

    meanData = np.mean(data,axis=0)

    #print("meanData : ",meanData)

    X = data - meanData

    N = X.shape[0]

    #print("N=",N)

    #covX = np.dot(X.T, X)/(N-1)

    covX = np.cov(X,rowvar=0)

    eigenvalues,eigenvectors = np.linalg.eig(covX)

    #print("eigenvalues = ",eigenvalues)

 

    # 屏蔽结束

 

    if sort:

        sort = eigenvalues.argsort()[::-1]

        eigenvalues = eigenvalues[sort]

        eigenvectors = eigenvectors[:, sort]

 

    return eigenvalues, eigenvectors,meanData


 

def main():

    # 指定点云路径

    cat_index = 10 # 物体编号,范围是0-39,即对应数据集中40个物体

    root_dir = r'../../ModelNet40/ply_data' # 数据集路径

    cat = os.listdir(root_dir)

    filename = os.path.join(root_dir, cat[cat_index],'train', cat[cat_index]+'_0001.ply') # 默认使用第一个点云

 

    # 加载原始点云

    point_cloud_pynt = PyntCloud.from_file(filename)

    point_cloud_o3d = point_cloud_pynt.to_instance("open3d", mesh=False)

    #o3d.visualization.draw_geometries([point_cloud_o3d]) # 显示原始点云

 

    # 从点云中获取点,只对点进行处理

    points = point_cloud_pynt.points

    print('total points number is:', points.shape[0])

 

    # 用PCA分析点云主方向

    _, v, meanData = PCA(points)

    point_cloud_vector = v[:, 2] #点云主方向对应的向量

    print('the main orientation of this pointcloud is: ', point_cloud_vector)

    # TODO: 此处只显示了点云,还没有显示PCA

 

    #print("v0*v1 = ",np.dot(v[:,1],v[:,0]))

    line_pcd = make_line_pcd(v,meanData)

    #o3d.visualization.draw_geometries([point_cloud_o3d,line_pcd])

    

    # 循环计算每个点的法向量

    pcd_tree = o3d.geometry.KDTreeFlann(point_cloud_o3d)

    normals = np.zeros((points.shape[0],3))

    # 作业2

    # 屏蔽开始

    for i in range(points.shape[0]):

        [_, idx, _] = pcd_tree.search_radius_vector_3d(point_cloud_o3d.points[i], 20)

        #print("idx.shape = ", np.asarray(idx).shape)

        #pts_nn=[]

        

        ids = np.asarray(idx)

        pts_nn = np.asarray(points)[ids]

        _, v,_1 = PCA(np.asarray(pts_nn))

 

        normals[i,:]=v[:,2]

 

    # 由于最近邻搜索是第二章的内容,所以此处允许直接调用open3d中的函数

    #print("normals : ",normals)

    # 屏蔽结束

    normals = np.array(normals, dtype=np.float64)

    # TODO: 此处把法向量存放在了normals中

    point_cloud_o3d.normals = o3d.utility.Vector3dVector(normals)

    o3d.visualization.draw_geometries([point_cloud_o3d])


 

if __name__ == '__main__':

    main()

################################################################################

################################################################################

# 实现voxel滤波,并加载数据集中的文件进行验证

 

import open3d as o3d 

import os

import numpy as np

from pyntcloud import PyntCloud



 

def PCA(data, correlation=False, sort=True):

    # 作业1

    # 屏蔽开始

    meanData = np.mean(data,axis=0)

    #print("meanData : ",meanData)

    X = data - meanData

    N = X.shape[0]

    #print("N=",N)

    #covX = np.dot(X.T, X)/(N-1)

    covX = np.cov(X,rowvar=0)

    eigenvalues,eigenvectors = np.linalg.eig(covX)

    #print("eigenvalues = ",eigenvalues)

 

    # 屏蔽结束

 

    if sort:

        sort = eigenvalues.argsort()[::-1]

        eigenvalues = eigenvalues[sort]

        eigenvectors = eigenvectors[:, sort]

 

    return eigenvalues, eigenvectors,meanData

#

def get_all_index(lst, item):

     return [i for i in range(len(lst)) if lst[i] == item]

 

# 功能:对点云进行voxel滤波

# 输入:

#     point_cloud:输入点云

#     leaf_size: voxel尺寸

def voxel_filter(point_cloud, leaf_size):

    filtered_points = []

    filtered_idx=[]

    # 作业3

    # 屏蔽开始

    minPC = np.min(point_cloud,axis=0)

    maxPC = np.max(point_cloud,axis=0)

    Dx = (maxPC[0] - minPC[0])/leaf_size

    Dy = (maxPC[1] - minPC[1])/leaf_size

    #Dz = (maxPC[2] - minPC[2])/leaf_size

    N = point_cloud.shape[0]

    #print("pc len = ",N)

    for i in range(N):

        idx = (np.asarray(point_cloud)[i][0] -  minPC[0] )//leaf_size + (np.asarray(point_cloud)[i][1] -  minPC[1] ) //leaf_size *Dx + (np.asarray(point_cloud)[i][2] -  minPC[2] )//leaf_size*Dx*Dy

        filtered_idx.append(idx)

    

    sort_idx = np.array(filtered_idx).argsort()[::-1]

 

    filtered_idx_ok = np.array(filtered_idx)[sort_idx]

    point_cloud_ok = np.asarray(point_cloud)[sort_idx]

 

    idx_set = set(filtered_idx_ok)

    for i in idx_set:

        all_idx = get_all_index(filtered_idx_ok,i)

        xm = np.mean(np.asarray(point_cloud_ok)[all_idx],axis=0)

        #print(xm)

        filtered_points.append(xm)

    # 屏蔽结束

 

    # 把点云格式改成array,并对外返回

    filtered_points = np.array(filtered_points, dtype=np.float64)

    return filtered_points

 

def main():

    # # 从ModelNet数据集文件夹中自动索引路径,加载点云

    cat_index = 10 # 物体编号,范围是0-39,即对应数据集中40个物体

    root_dir = r'../../ModelNet40/ply_data' # 数据集路径

    cat = os.listdir(root_dir)

    filename = os.path.join(root_dir, cat[cat_index],'train', cat[cat_index]+'_0001.ply') # 默认使用第一个点云

    point_cloud_pynt = PyntCloud.from_file(filename)

 

    # 加载自己的点云文件

    #file_name = "/Users/renqian/Downloads/program/cloud_data/11.ply"

    #point_cloud_pynt = PyntCloud.from_file(file_name)

 

    # 转成open3d能识别的格式

    point_cloud_o3d = point_cloud_pynt.to_instance("open3d", mesh=False)

    #o3d.visualization.draw_geometries([point_cloud_o3d]) # 显示原始点云

 

    # 调用voxel滤波函数,实现滤波

    filtered_cloud = voxel_filter(point_cloud_pynt.points, 5)

    point_cloud_o3d.points = o3d.utility.Vector3dVector(filtered_cloud)

    # 显示滤波后的点云

    #o3d.visualization.draw_geometries([point_cloud_o3d])


 

     # 循环计算每个点的法向量

    points = point_cloud_o3d.points

 

    pcd_tree = o3d.geometry.KDTreeFlann(point_cloud_o3d)

    N_pcd = np.asarray(points).shape[0]

    normals = np.zeros((N_pcd,3))

    # 作业2

    # 屏蔽开始

    for i in range(N_pcd):

        [_, idx, _] = pcd_tree.search_radius_vector_3d(point_cloud_o3d.points[i], 30)

        #print("idx.shape = ", np.asarray(idx).shape)

        #pts_nn=[]

        

        ids = np.asarray(idx)

        pts_nn = np.asarray(points)[ids]

        _, v,_1 = PCA(np.asarray(pts_nn))

 

        normals[i,:]=v[:,2]

 

    # 由于最近邻搜索是第二章的内容,所以此处允许直接调用open3d中的函数

    #print("normals : ",normals)

    # 屏蔽结束

    normals = np.array(normals, dtype=np.float64)

    # TODO: 此处把法向量存放在了normals中

    point_cloud_o3d.normals = o3d.utility.Vector3dVector(normals)

    o3d.visualization.draw_geometries([point_cloud_o3d])

 

if __name__ == '__main__':

    main()

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值