目前深度学习第一步encoder主要采用的是FPS。(PointNET++)
且FPS确实能在点云表面生成一组分布均匀的点。
import numpy as np
from plyfile import PlyData
import time
import matplotlib.pyplot as plt
def read_ply_points(ply_path):
ply = PlyData.read(ply_path)
data = ply.elements[0].data
points = np.stack([data['x'], data['y'], data['z']], axis=1)
return points
class FPS:
def __init__(self, points):
self.points = np.unique(points, axis=0)
def get_min_distance(self, a, b):
distance = []
for i in range(a.shape[0]):
dis = np.sum(np.square(a[i] - b), axis=-1)
distance.append(dis)
distance = np.stack(distance, axis=-1)
distance = np.min(distance, axis=-1)
return np.argmax(distance)
@staticmethod
def get_model_corners(model):
min_x, max_x = np.min(model[:, 0]), np.max(model[:, 0])
min_y, max_y = np.min(model[:, 1]), np.max(model[:, 1])
min_z, max_z = np.min(model[:, 2]), np.max(model[:, 2])
corners_3d = np.array([
[min_x, min_y, min_z],
[min_x, min_y, max_z],
[min_x, max_y, min_z],
[min_x, max_y, max_z],
[max_x, min_y, min_z],
[max_x, min_y, max_z],
[max_x, max_y, min_z],
[max_x, max_y, max_z],
])
return corners_3d
def compute_fps(self, K):
# 计算中心点位
corner_3d = self.get_model_corners(self.points)
center_3d = (np.max(corner_3d, 0) + np.min(corner_3d, 0)) / 2
A = np.array([center_3d])
B = np.array(self.points)
t = []
# 寻找K个节点
for i in range(K):
print(i)
max_id = self.get_min_distance(A, B)
A = np.append(A, np.array([B[max_id]]), 0)
B = np.delete(B, max_id, 0)
t.append(max_id)
file=open('fps_of.ply','w')
file.writelines("ply\n")
file.writelines("format ascii 1.0\n")
file.writelines("element vertex "+str(K+1)+"\n")
file.writelines("property float x\n")
file.writelines("property float y\n")
file.writelines("property float z\n")
file.writelines("element face 0\n")
file.writelines("property list uchar int vertex_indices\n")
file.writelines("end_header\n")
for i in A:
file.writelines(str(float(i[0]))+"\t"+str(float(i[1]))+"\t"+str(float(i[2]))+"\n")
print("开始计时")
time_start = time.time()
f = FPS(read_ply_points("fanDisk.ply"))
f.compute_fps(1500)#采样点个数
time_end = time.time()
time_c= time_end - time_start #运行所花时间
print('time cost', time_c, 's')
时间复杂度大,更新一下:输入指定路径,可以把该路径下所有文件做FPS(读入txt)
import os
# 遍历文件夹及其子文件夹中的文件,并存储在一个列表中
# 输入文件夹路径、空文件列表[]
# 返回 文件列表Filelist,包含文件名(完整路径)
def get_filelist(dir, Filelist):
newDir = dir
if os.path.isfile(dir):
Filelist.append(dir)
# # 若只是要返回文件文,使用这个
# Filelist.append(os.path.basename(dir))
elif os.path.isdir(dir):
for s in os.listdir(dir):
newDir = os.path.join(dir, s)
get_filelist(newDir, Filelist)
return Filelist
import numpy as np
olderr = np.seterr(all='ignore')
def farthest_point_sample(point, npoint):
N, D = point.shape
xyz = point[:,:3]
centroids = np.zeros((npoint,))
distance = np.ones((N,)) * 1e10
farthest = np.random.randint(0, N)
for i in range(npoint):
centroids[i] = farthest
centroid = xyz[farthest, :]
dist = np.sum((xyz - centroid) ** 2, -1)
mask = dist < distance
distance[mask] = dist[mask]
farthest = np.argmax(distance, -1)
point = point[centroids.astype(np.int32)]
return point
def run_fps(path):
point=np.loadtxt(path)
sample_point = 2048 # 输入想要采样的点的个数
pcd_point = farthest_point_sample(point, sample_point) # FPS采样
#保存路径
savepath="E:"+path.split(":")[1]
file = open(savepath, 'w')
for i in pcd_point:
file.write(str(i[0]) + " " + str(i[1]) + " " + str(i[2]) + " " + str(
i[3]) + " " + str(i[4]) + " " + str(i[5]) + " " + str((i[6])) + "\n")
file.close()
if __name__ == '__main__':
list = get_filelist('d:\\cvpr', [])
for e in list:
print(e)
run_fps(e)