pointnet 实战

依赖库对 Python 版本的要求

依赖 支持的 Python 版本
PyTorch (最新稳定版) 3.9 ~ 3.12
tqdm 3.7+
plyfile 3.7+

推荐选择:Python 3.10

  • PyTorch 对 3.10 支持最成熟,预编译wheel包最完整
  • 3.11/3.12 较新,部分旧版第三方库可能有兼容问题
  • 3.9 已经偏老,未来支持会逐渐减少
  • 3.10 是目前深度学习项目事实上的"最稳定选择"

创建虚拟环境的命令

数据集 shapenetcore_partanno_segmentation_benchmark_v0/ 详解


shapenet 数据集来自 ShapeNet,斯坦福大学发布的大规模三维形状数据库。

core 指的是 ShapeNetCore ,是 ShapeNet 的核心子集,包含 55 个常见物体类别(飞机、椅子、桌子等),是 ShapeNet 中最常用的部分。


partanno = part annotation (零件标注) 表示这个数据集不只是三维模型,而是对每个模型的每个零件都做了标注

比如飞机被标注成:机身、机翼、发动机、尾翼四个部件。


segmentation 表示这个数据集是专门为分割任务准备的,即判断每个点属于哪个零件。


benchmark 表示这是一个基准数据集,专门用来评测和对比不同算法的性能。


v0 = version 0,第 0 个版本(初始版本)。


shapenetcore_partanno_segmentation_benchmark_v0/

├── synsetoffset2category.txt # 类别ID ↔ 名称映射
├── train_test_split/
│ ├── shuffled_train_file_list.json
│ ├── shuffled_val_file_list.json
│ └── shuffled_test_file_list.json
├── 02691156/ ← Airplane (2690 个模型)
├── 03001627/ ← Chair (3746 个模型)
├── 04379243/ ← Table (5266 个模型)
└── ...共 16 个类别文件夹

每个类别文件夹内结构一致:

02691156/

├── points/ ← 点云文件 (.pts)

├── points_label/ ← 语义标签文件 (.seg)

└── seg_img/ ← 预渲染可视化图片 (.png)

核心文件格式

.pts 文件 --- 纯文本,每行一个点的 XYZ 坐标:

0.25047 -0.06912 -0.02763
0.16421 -0.04005 -0.03361
...
每个模型约 2488 个点(均匀采样自原始 ShapeNetCore 网格)。

.seg 文件 --- 与 .pts 逐行对应,每行一个整数(part 标签,从 1 开始):

1 ← 第1个点属于 part 1(机身)

1

3 ← 第3个点属于 part 3(机翼)

3

...

Airplane 有 4 个 part(机身/机翼/机尾/发动机),16 个类别共 50 种 part。

.png 文件 --- 已经预先渲染好的彩色分割图(最直接的可视化方式)。


各类别模型数量

┌──────────┬──────────┬──────┐

│ 类别 │ ID │ 数量 │

├──────────┼──────────┼──────┤

│ Table │ 04379243 │ 5266 │

├──────────┼──────────┼──────┤

│ Chair │ 03001627 │ 3746 │

├──────────┼──────────┼──────┤

│ Airplane │ 02691156 │ 2690 │

├──────────┼──────────┼──────┤

│ Car │ 02958343 │ 1824 │

├──────────┼──────────┼──────┤

│ Lamp │ 03636649 │ 1546 │

├──────────┼──────────┼──────┤

│ Guitar │ 03467517 │ 787 │

├──────────┼──────────┼──────┤

│ ... │ ... │ ... │

├──────────┼──────────┼──────┤

│ Cap │ 02954340 │ 55 │

└──────────┴──────────┴──────┘


1.用的是 conda(推荐):

复制代码
conda create -n pointnet python=3.10
conda activate pointnet

2.pip install -e .

场景 A:在项目里训练

你在:

/root/pointnet.pytorch

运行:python train.py

一般不需要 setup.py 也可能能跑。


场景 B:在 notebook 里调这个项目

比如你在:

/root/notebooks

打开一个 notebook,想写:

from pointnet.model import PointNetCls

这就属于"在别的地方"。

如果没安装成包,通常导不进来。

如果执行过:pip install -e .

就能导入。

"在别的地方"就是:

你不在项目目录里运行代码,但还想 import 这个项目。

最典型例子:

  • 在另一个项目里 import 它

  • 在 Python 终端里 import 它

  • 在 Jupyter notebook 里 import 它

  • 在任何别的路径下运行脚本时 import 它

setup.py的作用

from setuptools import setup

setup(

name="pointnet",

version="0.0.1",

packages=["pointnet"],

install_requires=["torch", "numpy"]

)

  • name:项目名
  • version:版本号
  • packages:要安装哪些包
  • install_requires:依赖哪些第三方库

3.python train_classification.py --dataset ../shapenetcore_partanno_segmentation_benchmark_v0 --nepoch 25 --dataset_type shapenet --workers 0(windows带 workers 0)

完整模型:

输入: [B, 3, N] B=32批次, 3=xyz坐标, N=2500个点


第一阶段:STN3d 输入对齐

class STN3d(nn.Module):

def forward(self, x): # x: [B, 3, N]

x = F.relu(self.bn1(self.conv1(x))) # [B, 3, N] → [B, 64, N]

x = F.relu(self.bn2(self.conv2(x))) # [B, 64, N] → [B, 128, N]

x = F.relu(self.bn3(self.conv3(x))) # [B, 128,N] → [B, 1024,N]

x = torch.max(x, 2, keepdim=True)[0] # [B, 1024,N] → [B, 1024,1] MaxPool

x = x.view(-1, 1024) # [B, 1024]

x = F.relu(self.bn4(self.fc1(x))) # [B, 1024] → [B, 512]

x = F.relu(self.bn5(self.fc2(x))) # [B, 512] → [B, 256]

x = self.fc3(x) # [B, 256] → [B, 9]

加上单位矩阵初始化,保证初始时不做变换

iden = torch.eye(3).flatten().repeat(B, 1) # [B, 9]

x = (x + iden).view(-1, 3, 3) # [B, 3, 3] ← 输出对齐矩阵

return x


第二阶段:PointNetfeat 特征提取

class PointNetfeat(nn.Module):

def forward(self, x): # x: [B, 3, N]

── 用STN3d预测变换矩阵,对点云做对齐 ──

trans = self.stn(x) # [B, 3, 3]

x = x.transpose(2, 1) # [B, N, 3]

x = torch.bmm(x, trans) # [B, N, 3] × [B, 3, 3] = [B, N, 3] 批量矩阵乘法

x = x.transpose(2, 1) # [B, 3, N]

── 第一层逐点特征提取 ──

x = F.relu(self.bn1(self.conv1(x))) # [B, 3, N] → [B, 64, N]

pointfeat = x # 保存64维逐点特征,分割任务要用

── 可选:STNkd 对64维特征空间再做一次对齐 ──

if self.feature_transform:

trans_feat = self.fstn(x) # [B, 64, 64]

x = x.transpose(2, 1) # [B, N, 64]

x = torch.bmm(x, trans_feat) # [B, N, 64]

x = x.transpose(2, 1) # [B, 64, N]

── 继续升维 ──

x = F.relu(self.bn2(self.conv2(x))) # [B, 64, N] → [B, 128, N]

x = self.bn3(self.conv3(x)) # [B, 128, N] → [B, 1024, N]

── 全局最大池化:N个点 → 1个全局向量 ──

x = torch.max(x, 2, keepdim=True)[0] # [B, 1024, N] → [B, 1024, 1]

x = x.view(-1, 1024) # [B, 1024]

if self.global_feat:

return x, trans, trans_feat # 分类任务:只返回全局特征

else:

分割任务:把全局特征广播回每个点,拼接逐点特征

x = x.view(-1, 1024, 1).repeat(1, 1, N) # [B, 1024, N]

return torch.cat([x, pointfeat], 1), ... # [B, 1088, N]


第三阶段:PointNetCls 分类头

class PointNetCls(nn.Module):

def forward(self, x): # x: [B, 3, N]

x, trans, trans_feat = self.feat(x) # x: [B, 1024]

x = F.relu(self.bn1(self.fc1(x))) # [B, 1024] → [B, 512]

x = F.relu(self.bn2(self.dropout(self.fc2(x)))) # [B, 512] → [B, 256]

x = self.fc3(x) # [B, 256] → [B, 16]

return F.log_softmax(x, dim=1), trans, trans_feat # [B, 16]

相关推荐
慕涯AI1 小时前
Agent 30 课程开发指南 - 第28课
人工智能·python
迷途酱2 小时前
RAG 从零到一:用 Python 给大模型接上你的私有知识库
python
我叫黑大帅2 小时前
受保护的海报图片读取方案 - 在不公开静态资源目录下如何获取静态资源
后端·python·面试
思绪无限2 小时前
YOLOv5至YOLOv12升级:农作物害虫检测系统的设计与实现(完整代码+界面+数据集项目)
人工智能·python·深度学习·目标检测·计算机视觉·yolov12·农作物害虫检测
码界筑梦坊2 小时前
94-基于Python的商品物流数据可视化分析系统
开发语言·python·mysql·信息可视化·数据分析·毕业设计·fastapi
元Y亨H2 小时前
Python 获取 Windows 设备信息笔记
windows·python
微刻时光2 小时前
影刀RPA:For循环与ForEach循环深度解析与实战指南
人工智能·python·低代码·自动化·rpa·影刀实战
KIHU快狐2 小时前
快狐KIHU|110寸壁挂触控一体机G+G电容屏安卓系统汽车展厅查询展示
android·python·汽车
斯维赤2 小时前
每天学习一个小算法:快速排序
java·python·学习·算法·排序算法