点云数据常用处理:python实现

目录

  • 数据集增强
    • 仿射变换
      • 平移变换
      • 旋转变换
      • 尺度变换
      • 仿射变换
    • 添加噪声
      • 高斯噪声
      • 随机噪声
    • 下采样
      • 指定体素
      • 指定点数
  • 数据归一化
    • 去中心化
    • 尺度归一化

数据集增强

仿射变换

平移变换

import numpy as np
import random

#文件名
old_file=r"rabbit.txt"
new_file=r"rabbit_change.txt"

#平移参数
x_offset=random.uniform(-10, 10)
y_offset=random.uniform(-10, 10)
z_offset=random.uniform(-10, 10)

#变换矩阵
transformation_matrix=np.array([
                            [1,0,0,x_offset],
                            [0,1,0,y_offset],
                            [0,0,1,z_offset],
                            [0,0,0,1]
                            ])

#加载文件
old_array=np.loadtxt(old_file)
old_xyz=old_array[:,:3]

#补充数据为齐次项
ones_data=np.ones(old_xyz.shape[0])
old_xyz=np.insert(old_xyz,3,values=ones_data,axis=1)

#变换数据
new_xyz = np.dot(transformation_matrix,old_xyz.T)
new_array=np.concatenate((new_xyz.T[:,:3],old_array[:,3:]),axis=1)
np.savetxt(new_file,new_array,fmt='%.06f')

旋转变换

import numpy as np
import random

#文件名
old_file=r"rabbit.txt"
new_file=r"rabbit_change.txt"

#旋转角度
roate_x=random.uniform(-np.pi/10, np.pi/10)
roate_y=random.uniform(-np.pi/10, np.pi/10)
roate_z=random.uniform(-np.pi/10, np.pi/10)

roate_x_matrix=np.array([
                    [1,0,0,0],
                    [0,np.cos(roate_x),-np.sin(roate_x),0],
                    [0,np.sin(roate_x),np.cos(roate_x),0],
                    [0,0,0,1]
                    ])
roate_y_matrix=np.array([
                    [np.cos(roate_y),0,np.sin(roate_y),0],
                    [0,1,0,0],
                    [-np.sin(roate_y),0,np.cos(roate_y),0],
                    [0,0,0,1]
                    ])
roate_z_matrix=np.array([
                    [np.cos(roate_z),-np.sin(roate_z),0,0],
                    [np.sin(roate_z),np.cos(roate_z),0,0],
                    [0,0,1,0],
                    [0,0,0,1]
                    ])

#变换矩阵
transformation_matrix=dot(roate_z_matrix).dot(roate_y_matrix).dot(roate_x_matrix)

#加载文件
old_array=np.loadtxt(old_file)
old_xyz=old_array[:,:3]

#补充数据为齐次项
ones_data=np.ones(old_xyz.shape[0])
old_xyz=np.insert(old_xyz,3,values=ones_data,axis=1)

#变换数据
new_xyz = np.dot(transformation_matrix,old_xyz.T)
new_array=np.concatenate((new_xyz.T[:,:3],old_array[:,3:]),axis=1)
np.savetxt(new_file,new_array,fmt='%.06f')

尺度变换

import numpy as np
import random

#文件名
old_file=r"rabbit.txt"
new_file=r"rabbit_change.txt"

#缩放参数
scale=0.1

#变换矩阵
transformation_matrix=np.array([
                            [scale,0,0,0],
                            [0,scale,0,0],
                            [0,0,scale,0],
                            [0,0,0,1]                            
                            ])

#加载文件
old_array=np.loadtxt(old_file)
old_xyz=old_array[:,:3]

#补充数据为齐次项
ones_data=np.ones(old_xyz.shape[0])
old_xyz=np.insert(old_xyz,3,values=ones_data,axis=1)

#变换数据
new_xyz = np.dot(transformation_matrix,old_xyz.T)
new_array=np.concatenate((new_xyz.T[:,:3],old_array[:,3:]),axis=1)
np.savetxt(new_file,new_array,fmt='%.06f')

仿射变换

上面三种变换综合可以写成:

import numpy as np
import random

#文件名
old_file=r"rabbit.txt"
new_file=r"rabbit_change.txt"

#平移参数
x_offset=random.uniform(-10, 10)
y_offset=random.uniform(-10, 10)
z_offset=random.uniform(-10, 10)

#缩放参数
scale=0.1

#旋转角度
roate_x=random.uniform(-np.pi/10, np.pi/10)
roate_y=random.uniform(-np.pi/10, np.pi/10)
roate_z=random.uniform(-np.pi/10, np.pi/10)

roate_x_matrix=np.array([
                    [1,0,0,0],
                    [0,np.cos(roate_x),-np.sin(roate_x),0],
                    [0,np.sin(roate_x),np.cos(roate_x),0],
                    [0,0,0,1]
                    ])
roate_y_matrix=np.array([
                    [np.cos(roate_y),0,np.sin(roate_y),0],
                    [0,1,0,0],
                    [-np.sin(roate_y),0,np.cos(roate_y),0],
                    [0,0,0,1]
                    ])
roate_z_matrix=np.array([
                    [np.cos(roate_z),-np.sin(roate_z),0,0],
                    [np.sin(roate_z),np.cos(roate_z),0,0],
                    [0,0,1,0],
                    [0,0,0,1]
                    ])

#变换矩阵
transformation_matrix=np.array([
                            [scale,0,0,x_offset],
                            [0,scale,0,y_offset],
                            [0,0,scale,z_offset],
                            [0,0,0,1]
                            ]).dot(roate_z_matrix).dot(roate_y_matrix).dot(roate_x_matrix)


#加载文件
old_array=np.loadtxt(old_file)
old_xyz=old_array[:,:3]

#补充数据为齐次项
ones_data=np.ones(old_xyz.shape[0])
old_xyz=np.insert(old_xyz,3,values=ones_data,axis=1)

#变换数据
new_xyz = np.dot(transformation_matrix,old_xyz.T)
new_array=np.concatenate((new_xyz.T[:,:3],old_array[:,3:]),axis=1)
np.savetxt(new_file,new_array,fmt='%.06f')

仿射变换:
PCL 仿射变换,实现点云平移旋转

添加噪声

高斯噪声

import numpy as np

#文件名
old_file=r"rabbit.txt"
new_file=r"rabbit_change.txt"

def add_noise(point, sigma=0.1, clip=0.1):
    point = point.reshape(-1,3)
    Row, Col = point.shape
    noisy_point = np.clip(sigma * np.random.randn(Row, Col), -1*clip, clip)
    noisy_point += point
    return noisy_point
  
  
#加载文件
old_array=np.loadtxt(old_file)
old_xyz=old_array[:,:3]

new_xyz=add_noise(old_xyz)
new_array=np.concatenate((new_xyz,old_array[:,3:]),axis=1)
np.savetxt(new_file,new_array,fmt='%.06f')

随机噪声

import numpy as np

#文件名
old_file=r"rabbit.txt"
new_file=r"rabbit_change.txt"

def guass_noise(point, sigma=1, clip=1):
    point = point.reshape(-1,3)
    Row, Col = point.shape
    noisy_point = np.clip(sigma * np.random.rand(Row, Col), -1*clip, clip)
    noisy_point += point
    return noisy_point
  
  
#加载文件
old_array=np.loadtxt(old_file)
old_xyz=old_array[:,:3]

new_xyz=guass_noise(old_xyz)
new_array=np.concatenate((new_xyz,old_array[:,3:]),axis=1)
np.savetxt(new_file,new_array,fmt='%.06f')

下采样

指定体素

import numpy as np

#文件名
old_file=r"rabbit.txt"
new_file=r"rabbit_change.txt"

#体素滤波
def voxel_filter(point_cloud, leaf_size):
    filtered_points = []
    # 计算边界点
    x_min, y_min, z_min = np.amin(point_cloud, axis=0)  #计算x y z 三个维度的最值
    x_max, y_max, z_max = np.amax(point_cloud, axis=0)
    
    # 计算 voxel grid维度
    Dx = (x_max - x_min) // leaf_size + 1
    Dy = (y_max - y_min) // leaf_size + 1
    Dz = (z_max - z_min) // leaf_size + 1

    # 计算每个点的voxel索引
    h = list()  # h为保存索引的列表
    for i in range(len(point_cloud)):
        hx = (point_cloud[i][0] - x_min) // leaf_size
        hy = (point_cloud[i][1] - y_min) // leaf_size
        hz = (point_cloud[i][2] - z_min) // leaf_size
        h.append(hx + hy * Dx + hz * Dx * Dy)
    h = np.array(h)
    
    #筛选点
    h_indice = np.argsort(h)  #返回h里面的元素按从小到大排序的索引
    h_sorted = h[h_indice]
    begin = 0
    for i in range(len(h_sorted) - 1):  # 0~9999
        if h_sorted[i] != h_sorted[i + 1]:
            point_idx = h_indice[begin: i + 1]
            filtered_points.append(np.mean(point_cloud[point_idx], axis=0))
            begin = i+1
    #把点云格式改成array,并对外返回
    filtered_points = np.array(filtered_points, dtype=np.float64)
    return filtered_points


#加载文件
old_array=np.loadtxt(old_file)
old_xyz=old_array[:,:3]

#保存文件
new_xyz=voxel_filter(old_xyz, 1)
np.savetxt(new_file,new_xyz,fmt='%.06f')

调用open3d的api:

import open3d as o3d
import numpy as np

old_file=r"rabbit.txt"
new_file=r"rabbit_change.txt"

cloud=o3d.io.read_point_cloud(old_file,format='xyzrgb')
cloud_downsampled=cloud.voxel_down_sample(1)
cloud_downsampled = np.array(cloud_downsampled.points)
np.savetxt(new_file,cloud_downsampled,fmt='%.06f')

调用pcl的api:

import pcl 
import numpy as np

old_file=r"rabbit.txt"
new_file=r"rabbit_change.txt"

cloud = pcl.PointCloud()
pcd = np.genfromtxt(old_file, delimiter=" ")
pcd = np.array(pcd, dtype = np.float32)
pcd=pcd[:,:3]
cloud.from_array(pcd)

cloud_down=pcl.ApproximateVoxelGrid()
pcl.ApproximateVoxelGrid.set_InputCloud(cloud_down, cloud)
pcl.ApproximateVoxelGrid.set_leaf_size(cloud_down, 1, 1, 1)
cloud_downsampled=pcl.ApproximateVoxelGrid.filter(cloud_down)
cloud_downsampled = np.array(cloud_downsampled.to_array())
np.savetxt(new_file,cloud_downsampled,fmt='%.06f')

指定点数

import numpy as np

#文件名
old_file=r"rabbit.txt"
new_file=r"rabbit_change.txt"

#加载文件
old_array = np.loadtxt(old_file).astype(np.float32)
points_num =2048
choice = np.random.choice(old_array.shape[0], points_num, replace=True)

#保存文件
new_array = old_array[choice, :]
np.savetxt(new_file,new_array,fmt='%.06f')

数据归一化

去中心化

    centroid = np.mean(pc, axis=0)
    pc = pc - centroid

尺度归一化

    m = np.max(np.sqrt(np.sum(pc**2, axis=1)))
    pc = pc / m

你可能感兴趣的:(3D,deep,learning,python,计算机视觉,3d)