美团面试—手撕numpy之fps点云最远点采样实现

FPS

没有想到不按套路出牌的美团今早就撕了这个。

点云最远点采样,从一堆点集中选出一些点,使得他们尽可能地远离。这样采样出来的点能比较好的表征整个轮廓。在pointnet++中就用到过。

整体思路是:分别维护一个已选取和待选取的点云集合。先从点云集合中选出一个点,然后计算其余所有点到该点的距离,距离最大的那个点是下次要加入的点。当pick集合中有多个点时,距离的定义为到集合每个点距离中的最小距离。
关于距离的计算:维护一个distance列表,对于每次pick出来的点,去更新distance。可以利用前缀性质,不需要重新计算点到集合中所有点的距离了,而是选取原值和到新point的距离中的较小值,即dis = min(dis, newdis)。
关于第一个点的选取:一般用离点云重心最远的点作为初始点

import numpy as np
import matplotlib.pyplot as plt

# def compute_dis(points):
#     ## points: N*3
#     ## return -- distances: N*N
#     points_dis = np.sum(np.power(points, 2), axis=1) # N
#     distances = np.expand_dims(points_dis, axis=1).repeat(points.shape[0], axis=1) # N*N
#     distances = distances + distances.T + 2 * np.dot(points, points.T)
#     return distances

def plot(points, sample_points):
    ax = plt.axes(projection='3d')
    ax.scatter3D(points[:,0], points[:,1], points[:,2])
    ax.scatter3D(sample_points[:,0], sample_points[:,1], sample_points[:,2], c='r', s=60, marker = '^')
    plt.show()
    

def fps(points, k):
    sample_points = np.zeros((k, 3))
    
    ## 用离重心最远的初始化
    barycenter = np.sum(points, axis=0)/points.shape[0]
    print(barycenter)
    distance = np.full((points.shape[0]), np.nan)
    point = barycenter
    
    
#     # 随机初始化
#     point = points[0]
#     points = points[:-1,:]
#     sample_points[0,:] = point
#     distance = np.sum((points - point)**2, axis=1)
    for i in range(k):
        distance = np.minimum(distance, np.sum((points - point)**2, axis=1)) ## 前缀思想更新最小值
        index = np.argmax(distance)
        point = points[index]
        sample_points[i,:] = point
        mask = np.ones((points.shape[0]), dtype=bool)
        mask[index] = False
        points = points[mask]
        distance = distance[mask]
    return sample_points
        
np.random.seed(42)
points = np.random.randint(0, 5, size=(50, 3))
sample_points = fps(points, 10)
plot(points, sample_points)
print(points)
print(sample_points)        
    

在这里插入图片描述
————————————————————————————————————————————
最远点采样(FPS)
三维点云处理05-FPS代码实现

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值