点云处理: 基于飞桨复现PointNet++
本文介绍PointNet++在PaddlePaddle的复现项目。PointNet++通过分层结构提取点云局部特征,解决点集分布不均问题。复现基于ModelNet40数据集,top-1 Acc达92.0,超原论文。说明环境依赖、快速开始步骤,分析代码结构及复现中PaddlePaddle多维索引支持不足的问题与解决方法。

pointnet_plus_plus_paddlepaddle
Paper: PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space
免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
一、项目简介
PointNet++与PointNet相比网络可以更好的提取局部特征。网络使用空间距离(metric space distances),使用PointNet对点集局部区域进行特征迭代提取,使其能够学到局部尺度越来越大的特征。基于自适应密度的特征提取方法,解决了点集分布不均匀的问题。
论文地址:
PointNet++
论文背景:
论文主要解决的是点云分割与点云分类的问题。该方法对PointNet进行了改进。针对PointNet存在的无法获得局部特征,难以对复杂场景进行分析的缺点。PointNet++,通过两个主要的方法进行了改进:
利用空间距离(metric space distances),使用PointNet对点集局部区域进行特征迭代提取,使其能够学到局部尺度越来越大的特征。由于点集分布很多时候是不均匀的,如果默认是均匀的,会使得网络性能变差,所以作者提出了一种自适应密度的特征提取方法。通过以上两种方法,能够更高效的学习特征,也更有鲁棒性。论文方案介绍
在PointNet++中,作者利用所在空间的距离度量将点集划分(partition)为有重叠的局部区域(可以理解为patch)。在此基础上,在小范围中从几何结构中提取局部特征(浅层特征),然后扩大范围,在这些局部特征的基础上提取更高层次的特征,从而提取到整个点集的全局特征。
PointNet++解决了两个关键的问题:第一,将点集划分为不同的区域;第二,利用特征提取器获取不同区域的局部特征。
在本文中,作者使用了PointNet作为特征提取器,使用邻域球来定义分区,每个区域可以通过中心坐标和半径来确定。中心坐标的选取,作者使用了快速采样算法来完成(farthest point sampling (FPS) algorithm)。区域半径的选择使用了Multi-scale grouping (MSG) and Multi-resolution grouping (MRG)来实现。
论文模型介绍
PointNet++是PointNet的延伸,在PointNet的基础上加入了多层次结构(hierarchical structure),使得网络能够在越来越大的区域上提供更高级别的特征。
网络的每一组set abstraction layers主要包括3个部分:Sampling layer, Grouping layer and PointNet layer。
· Sample layer:主要是对输入点进行采样,在这些点中选出若干个中心点; · Grouping layer:是利用上一步得到的中心点将点集划分成若干个区域; · PointNet layer:是对上述得到的每个区域进行编码,变成特征向量。 每一组提取层的输入是N * (d + C),其中N是输入点的数量,d是坐标维度,C是特征维度。输出是N'* (d + C'),其中N'是输出点的数量,d是坐标维度不变,C'是新的特征维度。
二、复现精度
三、数据集
使用的数据集为:ModelNet40。
ModelNet包含了来自662类的127915个三维形状,其子集Model10包含了来自10类的4899个三维形状,ModelNet40包含了来自40类的12311个三维形状。ModelNet40是常用的三维点云分割数据集,现在是一个用来评判三维点云分割性能的常规benchmark。
四、环境依赖
硬件:GPU、CPU
框架:
PaddlePaddle >= 2.0.0tqdm五、快速开始
Data Preparation
Download alignment ModelNet and put it in ./dataset/modelnet40_normal_resampled/
Train
python train_modelnet.py --process_data登录后复制
Test
python test_modelnet.py --log_dir path_to_model登录后复制
六、代码结构与详细说明
6.1 代码结构
|—— README.md|—— provider.py # 点云数据增强|—— ModelNetDataset.py # 数据集定义及加载|── train_modelnet.py # 训练网络|── test_modelnet.py # 测试网络|—— models # 模型文件定义登录后复制
6.2 参数说明
可以在 train_modelnet.py 中设置训练与评估相关参数,具体如下:
Reference Implementation:
TensorFlow (Official)PyTorch七、复现总结与心得
问题
复现主要参考的是PyTorch的pytorch实现,pytorch的大部分api可以在paddlepaddle中找到对应,最困难的地方在于,paddlepaddle没法办法进行二维的索引,对应原实现中的多个部分
def index_points(points, idx): """ Input: points: input points data, [B, N, C] idx: sample index data, [B, S] Return: new_points:, indexed points data, [B, S, C] """ device = points.device B = points.shape[0] view_shape = list(idx.shape) view_shape[1:] = [1] * (len(view_shape) - 1) repeat_shape = list(idx.shape) repeat_shape[0] = 1 batch_indices = torch.arange(B, dtype=torch.long).to(device).view(view_shape).repeat(repeat_shape) new_points = points[batch_indices, idx, :] return new_points登录后复制
def farthest_point_sample(xyz, npoint): """ Input: xyz: pointcloud data, [B, N, 3] npoint: number of samples Return: centroids: sampled pointcloud index, [B, npoint] """ device = xyz.device B, N, C = xyz.shape centroids = torch.zeros(B, npoint, dtype=torch.long).to(device) distance = torch.ones(B, N).to(device) * 1e10 farthest = torch.randint(0, N, (B,), dtype=torch.long).to(device) batch_indices = torch.arange(B, dtype=torch.long).to(device) for i in range(npoint): centroids[:, i] = farthest centroid = xyz[batch_indices, farthest, :].view(B, 1, 3) dist = torch.sum((xyz - centroid) ** 2, -1) mask = dist < distance distance[mask] = dist[mask] farthest = torch.max(distance, -1)[1] return centroids登录后复制
def query_ball_point(radius, nsample, xyz, new_xyz): """ Input: radius: local region radius nsample: max sample number in local region xyz: all points, [B, N, 3] new_xyz: query points, [B, S, 3] Return: group_idx: grouped points index, [B, S, nsample] """ device = xyz.device B, N, C = xyz.shape _, S, _ = new_xyz.shape group_idx = torch.arange(N, dtype=torch.long).to(device).view(1, 1, N).repeat([B, S, 1]) sqrdists = square_distance(new_xyz, xyz) group_idx[sqrdists > radius ** 2] = N group_idx = group_idx.sort(dim=-1)[0][:, :, :nsample] group_first = group_idx[:, :, 0].view(B, S, 1).repeat([1, 1, nsample]) mask = group_idx == N group_idx[mask] = group_first[mask] return group_idx登录后复制
def sample_and_group(npoint, radius, nsample, xyz, points, returnfps=False): """ Input: npoint: radius: nsample: xyz: input points position data, [B, N, 3] points: input points data, [B, N, D] Return: new_xyz: sampled points position data, [B, npoint, nsample, 3] new_points: sampled points data, [B, npoint, nsample, 3+D] """ B, N, C = xyz.shape S = npoint fps_idx = farthest_point_sample(xyz, npoint) # [B, npoint, C] new_xyz = index_points(xyz, fps_idx) idx = query_ball_point(radius, nsample, xyz, new_xyz) grouped_xyz = index_points(xyz, idx) # [B, npoint, nsample, C] grouped_xyz_norm = grouped_xyz - new_xyz.view(B, S, 1, C) if points is not None: grouped_points = index_points(points, idx) new_points = torch.cat([grouped_xyz_norm, grouped_points], dim=-1) # [B, npoint, nsample, C+D] else: new_points = grouped_xyz_norm if returnfps: return new_xyz, new_points, grouped_xyz, fps_idx else: return new_xyz, new_points登录后复制
这里所有的二维索引都没有办法使用,包括经常使用的mask方法
这里进行了一些妥协,将需要二维索引的地方进行拉直,从而可以将二维索引变为n个一维索引,但是这里肯定对速度有所损失,暂时没有想到好的办法
farthest = torch.randint(0, N, (B,), dtype=torch.long).to(device)batch_indices = torch.arange(B, dtype=torch.long).to(device)for i in range(npoint): centroids[:, i] = farthest centroid = xyz[batch_indices, farthest, :].view(B, 1, 3)登录后复制
farthest = paddle.randint(0, N, (B, ), dtype="int64")for i in range(npoint): centroids[:, i] = farthest # centroid = xyz[batch_indices, farthest, :].reshape((B, 1, 3)) centroid = paddle.zeros((B, 1, 3), dtype="float32") for j in range(3): centroid[:,:,j] = xyz[:,:,j].index_sample(farthest.reshape((-1, 1))).reshape((B, 1))登录后复制
对于mask的地方,可以直接使用数值运算的方法达到mask的目的
mask = dist < distancedistance[mask] = dist[mask]farthest = torch.max(distance, -1)[1]登录后复制
mask = dist < distancemask = mask.astype("int64")mask_index = paddle.nonzero(mask)if mask_index.size > 0: distance = distance * (1 - mask.astype("float32")) + dist * mask.astype("float32")登录后复制
总结
目前的paddlepaddle可以支持大多数pytorch的API,但是其对于多维索引的支持不足,非常影响使用体验,而多维索引又是一个在日常的研究以及工程中,非常常规的功能,这里需要改进。
安装依赖
In [ ]!python3 -m pip install tqdm登录后复制
解压缩数据集
In [ ]%cd /home/aistudio/data/data50045/!unzip modelnet40_normal_resampled.zip登录后复制
解压缩代码并链接数据集
In [ ]%cd /home/aistudio/!unzip pointnet_plus_plus_paddlepaddle-main.zip%cd pointnet_plus_plus_paddlepaddle-main/登录后复制 In [ ]
%mkdir /home/aistudio/pointnet_plus_plus_paddlepaddle-main/dataset%cp -r /home/aistudio/data/data50045/modelnet40_normal_resampled /home/aistudio/pointnet_plus_plus_paddlepaddle-main/dataset登录后复制
训练模型
In [2]%cd /home/aistudio/pointnet_plus_plus_paddlepaddle-main/!python3 train_modelnet.py --process_data登录后复制
测试
In [ ]%cd /home/aistudio/pointnet_plus_plus_paddlepaddle-main/!python3 test_modelnet.py --log_dir path_to_log登录后复制
相关攻略
常见报错解析:“Access Not Configured”故障排除指南 许多开发者和团队成员在使用OpenClaw集成飞书时,都曾遭遇过一个典型的中断提示:“access not configured”(访问未配置)。该提示会明确显示您的飞书账户ID及一组唯一的配对验证码,并指出需要联系机器人所有
OpenClaw 常用指令大全与使用详解 openclaw status:此命令是查看OpenClaw系统整体健康状态的核心指令,执行后即获取服务运行状况的全面报告,是日常运维的首要诊断工具。 openclaw gateway restart:在修改网关配置后,必须运行此指令以重启网关服务,使配置文
如何通过 OpenClaw 实现 Chrome 浏览器自动化操控 在软件开发与自动化测试领域,持续学习是常态。本文旨在详细介绍如何利用 OpenClaw 连接并控制一个已开启的 Chrome 浏览器实例,实现点击、文本输入、文件上传、页面滚动、屏幕截图以及执行 JavaScript 等自动化操作。整
项目概述 你是否希望将强大的 AI 助手带入日常聊天?本教程将指导你完成搭建流程,让你能在 QQ 上直接调用 OpenClaw 智能助手,实现无门槛的 AI 对话体验。 架构说明 ┌─────────────┐ ┌──────────────┐ ┌─────────────┐ │ QQ 用户 │ ─
一 下载并安装Node js,全程保持默认设置 首先,请前往Node js官方网站的下载中心:https: nodejs org zh-cn download。根据您的操作系统(Windows Mac Linux)下载对应的安装程序。运行安装向导时,整个过程非常简单,您只需连续点击“下一步”按钮
热门专题
热门推荐
比特币强制平仓热图:揭秘市场流动性猎场的终极指南 2025年11月下旬,比特币价格剧烈波动,一度跌破91,000美元关键支撑。在短短24小时内,全网超过3 01亿美元的资金被强制清算,十余万交易者遭遇爆仓。这些清算事件并非随机分布,而是高度集中在特定的价格水平,形成了一场残酷的“流动性踩踏”。这一切
红色沙漠跃升之塔详细启动攻略 如何启动跃升之塔?当主线推进到第八章“面对内心的自我”时,这已成为推动剧情的关键挑战。整个过程更像是一次集平台跳跃与精密电路解谜于一体的沉浸式体验。本文将为你详尽解析这座神秘装置的完整启动流程与核心技巧。 一、启动前置条件 在启程探索之前,务必确认以下几项准备工作已完成
作为全球领先的数字资产交易平台之一,欧易(OKX)为用户提供了高效、安全的交易体验。然而,当你尝试登录欧易OKX(OKX)交易所时,系统会弹出提示:“请求超时,请稍后重试。”这类问题常让人困惑:网络明明正常、账号也没问题,为什么就是登录不了?这并不是账户故障,而是“访问路径”出现了问题。 简单来说,
珊瑚的化学成分究竟是什么?神奇海洋今日答案为你解析 欢迎来到每日海洋知识科普!今日我们一同探索海洋中的瑰丽建筑师——珊瑚。你是否好奇珊瑚的主要化学成分是什么?正确答案现已公布:碳酸钙。 事实上,珊瑚的本质是珊瑚虫分泌形成的坚硬骨骼,其核心化学构成正是碳酸钙。掌握这一知识点,不仅是答对题目的关键,更是
在数字化办公成为主流的今天,腾讯文档作为一款优秀的在线协作文档工具,极大地提升了团队效率。而将腾讯文档在线文档生成独立网页,能够进一步扩大文档的传播范围,实现无需登录即可公开访问,便于在各种场景下分享与展示。 将腾讯文档内容转化为网页的操作流程其实非常简单。首先,您需要在腾讯文档中打开您希望发布成网





