基于python实现FPS(最远距离采样)

基于python实现FPS(最远距离采样)
FPS的原理:
基于python实现FPS(最远距离采样)_第1张图片

目前深度学习第一步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')

基于python实现FPS(最远距离采样)_第2张图片
时间复杂度大,更新一下:输入指定路径,可以把该路径下所有文件做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)

你可能感兴趣的:(python)