3D点云目标检测(PointPillars)部署pipeline

面向 KITTI 3D 目标检测的 PointPillars 部署工程,支持从 PyTorch checkpoint 拆分导出 ONNX、ONNXRuntime/MNN 推理、结果诊断、BEV/相机图可视化与输出对齐。

CSDN 资源下载链接:https://download.csdn.net/download/m0_60827485/92963979


1. 项目定位

本工程面向 KITTI 3D 目标检测 场景,围绕 zhulf0804/PointPillarsepoch_160.pth checkpoint,构建一套可部署、可验证、可视化、可对齐的 PointPillars 推理工程。

工程目标不是单纯训练模型,而是完成从 PyTorch 参考模型 → 拆分 ONNX → ONNXRuntime/MNN 推理 → 后处理 → BEV/相机图可视化 → 结果对齐诊断 的完整部署链路。


2. 资源说明

2.1 CSDN 资源下载

资源下载地址:

text 复制代码
https://download.csdn.net/download/m0_60827485/92963979

建议资源内容包括:

  • PointPillars 部署工程源码;
  • 示例 KITTI 输入数据;
  • PyTorch checkpoint 配置说明;
  • 拆分 ONNX 模型或导出脚本;
  • ONNXRuntime/MNN 推理脚本;
  • BEV 与相机图可视化结果;
  • 部署说明与调试命令。

2.2 推荐目录结构

text 复制代码
PointPillars_deploy/
├── configs/                  # KITTI/运行时配置
├── data/                     # 示例 KITTI 输入:点云、图像、标定、标签
├── models/                   # checkpoint、ONNX、MNN 与 manifest
│   ├── checkpoints/          # PyTorch checkpoint
│   ├── pfn.onnx
│   ├── backbone_head.onnx
│   ├── pfn_sim.onnx
│   ├── backbone_head_sim.onnx
│   ├── pfn.mnn
│   └── backbone_head.mnn
├── outputs_demo/             # 示例推理与可视化输出
├── pointpillars/             # PointPillars 模型、ops、IO、后处理、可视化工具
├── ThirdParty/               # ONNXRuntime C/C++ 等第三方库
└── tools/                    # 模型准备、导出、推理、验证、可视化、对比脚本

3. 总体部署架构

PointPillars 原始 PyTorch 模型包含点云体素化、Pillar 特征编码、BEV 特征散射、Backbone/Neck、检测头、anchor decode、NMS、坐标投影等步骤。部署时不建议直接整体导出,而是采用 拆分模型 + C++/Python 前后处理 的方式。

推荐拆分方式如下:

text 复制代码
KITTI 点云 .bin
    │
    ▼
点云读取 / 范围过滤 / Pillarization
    │
    ├── pillar_features
    ├── pillar_mask
    └── coords
    │
    ▼
PFN ONNX/MNN
    │
    ▼
pillar_embed
    │
    ▼
Scatter BEV
    │
    ▼
bev_feature
    │
    ▼
Backbone + Neck + Head ONNX/MNN
    │
    ├── cls_preds
    ├── box_preds
    └── dir_cls_preds
    │
    ▼
Anchor Decode / Direction 修正 / Rotated NMS
    │
    ▼
3D 检测框 JSON
    │
    ├── BEV 可视化
    └── 相机图投影可视化

当前工程的模型拆分方式:

模块 输入 输出 部署位置
Pillarization 原始点云 pillar_features / pillar_mask / coords Python/C++ 前处理
PFN pillar_features + pillar_mask pillar_embed ONNX/MNN
Scatter pillar_embed + coords bev_feature Python/C++ 前处理
Backbone/Neck/Head bev_feature cls_preds / box_preds / dir_cls_preds ONNX/MNN
Decode/NMS Head 输出 3D boxes Python/C++ 后处理
Visualization boxes + calib + image BEV/相机图 Python/C++ 可视化

4. 关键配置

4.1 点云范围

yaml 复制代码
point_cloud_range: [0.0, -39.68, -3.0, 69.12, 39.68, 1.0]

含义:

text 复制代码
x: [0.0, 69.12]
y: [-39.68, 39.68]
z: [-3.0, 1.0]

4.2 Voxel 参数

yaml 复制代码
voxel_size: [0.16, 0.16, 4.0]
grid_size: [432, 496, 1]
max_points_per_pillar: 32
max_pillars: 12000

4.3 类别顺序

必须保持与源码一致:

text 复制代码
0 -> Pedestrian
1 -> Cyclist
2 -> Car

如果类别顺序错误,会出现 Car 被画成 Pedestrian、Pedestrian anchor 解成 Car box 等问题。

4.4 Anchor 参数

推荐使用源码顺序:

text 复制代码
Pedestrian: [w=0.6, l=0.8,  h=1.73], z=-0.60
Cyclist:    [w=0.6, l=1.76, h=1.73], z=-0.60
Car:        [w=1.6, l=3.9,  h=1.56], z=-1.78
rotations:  [0, 1.57]

5. 环境部署

5.1 Python 环境

建议 Python 3.9+:

bash 复制代码
python3 -m pip install numpy opencv-python pyyaml onnx onnxruntime onnxsim torch

依赖说明:

依赖 作用
torch PyTorch checkpoint 加载与参考推理
onnx ONNX 导出与模型检查
onnxruntime ONNX 推理验证
onnxsim ONNX 简化
opencv-python BEV/相机图可视化
pyyaml 配置文件读取
numpy 前后处理与数据格式转换

5.2 MNN 环境

MNN 部署需要准备:

text 复制代码
MNNConvert
MNN Python 包,或 C++ 推理库

ONNX 转 MNN 示例:

bash 复制代码
tools/convert_mnn.sh --mnnconvert /path/to/MNNConvert

6. 模型准备流程

6.1 一键准备

bash 复制代码
tools/prepare_models.sh

只导出/验证 ONNX,不转换 MNN:

bash 复制代码
tools/prepare_models.sh --skip-mnn

只做工具链冒烟测试:

bash 复制代码
tools/prepare_models.sh --dummy-export --skip-mnn

6.2 分步执行

bash 复制代码
python tools/download_models.py --manifest models/model_manifest.json

python tools/export_pointpillars_onnx.py \
  --manifest models/model_manifest.json

python tools/verify_onnx.py \
  --manifest models/model_manifest.json

tools/simplify_onnx.sh

tools/convert_mnn.sh

6.3 从 checkpoint 导出拆分 ONNX

bash 复制代码
python tools/export_pointpillars_split.py \
  --ckpt models/checkpoints/epoch_160.pth \
  --config configs/pointpillars_kitti.yaml \
  --pfn-out models/pfn.onnx \
  --backbone-out models/backbone_head.onnx \
  --opset 17

导出后建议固定输入尺寸并简化:

bash 复制代码
tools/simplify_onnx.sh

输出:

text 复制代码
models/pfn_sim.onnx
models/backbone_head_sim.onnx

7. PyTorch 参考推理

PyTorch 参考推理用于确认 checkpoint、输入数据、标定文件和可视化流程是否正确。

bash 复制代码
python tools/infer_pointpillars_pytorch.py \
  --ckpt models/checkpoints/epoch_160.pth \
  --pc-path data/sample.bin \
  --calib-path data/sample_calib.txt \
  --img-path data/sample.png \
  --gt-path data/sample_label.txt \
  --device cpu \
  --save-dir outputs/pytorch_ref \
  --save-bev \
  --save-image \
  --show-gt

输出示例:

text 复制代码
outputs/pytorch_ref/detections_pytorch_refactor.json
outputs/pytorch_ref/vis_bev.png
outputs/pytorch_ref/vis_image.png

PyTorch 结果应作为 ONNX/MNN 对齐的基准。


8. ONNX 推理流程

bash 复制代码
python tools/infer_pointpillars_onnx.py \
  --pc-path data/sample.bin \
  --calib-path data/sample_calib.txt \
  --img-path data/sample.png \
  --gt-path data/sample_label.txt \
  --pfn models/pfn_sim.onnx \
  --backbone models/backbone_head_sim.onnx \
  --backend onnx \
  --save-dir outputs/onnx \
  --visualize \
  --score-thr 0.3 \
  --nms-thr 0.01 \
  --nms-pre 100 \
  --max-num 50

输出:

text 复制代码
outputs/onnx/detections_runtime.json
outputs/onnx/vis_bev.png
outputs/onnx/vis_image.png

8.1 ONNX 对齐重点

ONNX 侧容易出现以下问题:

问题 现象 修复方向
PFN 输入特征维度不一致 检测框位置大幅偏移 确认 pillar_features 最后一维与导出模型一致
scatter y 方向不一致 BEV 上检测整体上下/左右偏移 对齐源码 scatter 坐标定义
anchor stride 错误 y 方向集中到半幅区域 使用 head 输出 H/W 覆盖完整 point cloud range
类别/anchor 顺序错误 类别错乱、尺寸异常 固定 Pedestrian/Cyclist/Car 顺序
NMS 不一致 同一目标重复框很多 使用 rotated NMS,按 score 排序后映射索引
图像投影未过滤 相机图出现长射线 过滤相机后方、深度过小、投影跨度异常框

9. MNN 推理流程

MNN 推荐沿用 ONNX 拆分结构:

text 复制代码
pfn.onnx -> pfn.mnn
backbone_head.onnx -> backbone_head.mnn

转换命令:

bash 复制代码
tools/convert_mnn.sh --mnnconvert /path/to/MNNConvert

启用 FP16:

bash 复制代码
tools/convert_mnn.sh --mnnconvert /path/to/MNNConvert --fp16

MNN 推理命令示例:

bash 复制代码
python tools/infer_pointpillars_onnx.py \
  --pc-path data/sample.bin \
  --calib-path data/sample_calib.txt \
  --img-path data/sample.png \
  --gt-path data/sample_label.txt \
  --pfn models/pfn.mnn \
  --backbone models/backbone_head.mnn \
  --backend mnn \
  --save-dir outputs/mnn \
  --visualize

10. C++ 部署设计

10.1 推荐模块划分

text 复制代码
cpp/
├── include/
│   ├── PointPillarsPipeline.hpp
│   ├── VoxelGenerator.hpp
│   ├── PillarFeatureBuilder.hpp
│   ├── ScatterBEV.hpp
│   ├── RuntimeEngine.hpp
│   ├── OnnxRuntimeEngine.hpp
│   ├── MNNRuntimeEngine.hpp
│   ├── AnchorDecoder.hpp
│   ├── RotatedNMS.hpp
│   ├── Calibration.hpp
│   └── Visualizer.hpp
├── src/
│   ├── PointPillarsPipeline.cpp
│   ├── VoxelGenerator.cpp
│   ├── ScatterBEV.cpp
│   ├── OnnxRuntimeEngine.cpp
│   ├── MNNRuntimeEngine.cpp
│   ├── AnchorDecoder.cpp
│   ├── RotatedNMS.cpp
│   ├── Calibration.cpp
│   └── Visualizer.cpp
└── demo/
    └── demo_pointpillars.cpp

10.2 Pipeline 接口

cpp 复制代码
struct Detection3D {
    float x;
    float y;
    float z;
    float w;
    float l;
    float h;
    float yaw;
    float score;
    int cls_id;
};

class PointPillarsPipeline {
public:
    bool Init(const std::string& runtime_config);
    std::vector<Detection3D> Infer(const std::vector<float>& point_cloud_xyzi);
};

10.3 RuntimeEngine 抽象

cpp 复制代码
class IRuntimeEngine {
public:
    virtual ~IRuntimeEngine() = default;
    virtual bool LoadModel(const std::string& model_path) = 0;
    virtual bool Infer(const std::vector<Tensor>& inputs,
                       std::vector<Tensor>& outputs) = 0;
};

ONNXRuntime 与 MNN 分别实现:

text 复制代码
OnnxRuntimeEngine : IRuntimeEngine
MNNRuntimeEngine  : IRuntimeEngine

这样 C++ 端可以通过配置切换后端:

yaml 复制代码
runtime_backend: onnx   # onnx / mnn
pfn_model: models/pfn_sim.onnx
backbone_model: models/backbone_head_sim.onnx

11. 数据格式定义

11.1 输入点云

KITTI .bin 点云格式:

text 复制代码
float32 x, y, z, intensity

读取后形状:

text 复制代码
[N, 4]

11.2 PFN 输入

text 复制代码
pillar_features: [1, max_pillars, max_points_per_pillar, feature_dim]
pillar_mask:     [1, max_pillars, max_points_per_pillar, 1]
coords:          [max_pillars, 4]

11.3 Backbone 输入

text 复制代码
bev_feature: [1, 64, H, W]

11.4 Head 输出

text 复制代码
cls_preds:     [1, 18, H, W]
box_preds:     [1, 42, H, W]
dir_cls_preds: [1, 12, H, W]

11.5 输出 JSON

json 复制代码
{
  "x": 10.3070,
  "y": 0.0077,
  "z": -1.7240,
  "w": 1.6548,
  "l": 3.5103,
  "h": 1.5760,
  "yaw": -1.6265,
  "score": 0.9654,
  "cls_id": 2,
  "class_name": "Car"
}

12. 结果验证与对齐

12.1 PyTorch vs ONNX 对比

bash 复制代码
python tools/compare_outputs.py \
  --ref outputs/pytorch_ref/detections_pytorch_refactor.json \
  --test outputs/onnx/detections_runtime.json \
  --tolerance 1e-3

12.2 诊断检测结果

bash 复制代码
python tools/diagnose_pointpillars_output.py outputs/onnx/detections_runtime.json

重点检查:

text 复制代码
box 数量
类别分布
score 分布
x/y/z 范围
w/l/h 是否符合类别尺寸
yaw 是否异常
重复框数量
是否存在投影异常框

12.3 重新可视化

bash 复制代码
python tools/visualize_detection.py \
  --points data/sample.bin \
  --detections outputs/onnx/detections_runtime.json \
  --image data/sample.png \
  --calib data/sample_calib.txt \
  --label data/sample_label.txt \
  --bev-output outputs/onnx/vis_bev_replot.png \
  --image-output outputs/onnx/vis_image_replot.png \
  --bev-reference-style

13. 常见问题与修复建议

13.1 BEV 中 GT 与 Pred 旋转角度不一致

原因:

text 复制代码
GT camera box 维度顺序错误
bbox_camera2lidar yaw 被额外转换
BEV corner 公式与源码不一致

修复:

text 复制代码
GT camera box 使用 [x, y, z, l, h, w, ry]
GT lidar box 仅用于 BEV
图像 GT 直接 camera box -> image
BEV GT/Pred 统一使用 bbox3d2bevcorners

13.2 图像中出现异常长射线

原因:

text 复制代码
NMS 未生效
投影时存在相机后方或近深度 corner
box decode 异常导致尺寸过大
calib 与点云/图像不匹配

修复:

text 复制代码
使用 rotated NMS
过滤 camera z <= min_depth 的 box
过滤投影跨度过大的 box
确认 calib/image/point cloud 同帧

13.3 ONNX 与 PyTorch 结果不一致

优先检查:

text 复制代码
PFN 输入 feature_dim
pillar 坐标顺序
scatter y 方向
decode anchor_y stride
anchor size/class 顺序
head 输出顺序
NMS 实现

13.4 检测框集中到 y 负方向或正方向

原因通常不是简单镜像,而是:

text 复制代码
scatter 坐标解释与 decode anchor_y 不一致
head stride 使用 voxel_size=0.16,而不是 point_cloud_range / head feature size

修复:

text 复制代码
anchor_x = x_min + (col + 0.5) * ((x_max - x_min) / W)
anchor_y = y_min + (row + 0.5) * ((y_max - y_min) / H)

16. 参考资源

相关推荐
coft1 小时前
Hermes 多角色实战:我做了一个智能投研系统
人工智能
AIGS0011 小时前
向量空间JBoltAI:重塑工业智能的四大支柱
java·人工智能·ai大模型应用
2301_764441331 小时前
用户用部署在手机上的ai模型都做些什么
人工智能·智能手机
Hali_Botebie1 小时前
PyTorch 2.x核心变革torch.compile(),Triton 是其中最重要的 kernel 生成方式之一
人工智能·pytorch·python
weifengma-wish1 小时前
test测试 用
人工智能
赫媒派1 小时前
Claude Code 实战技巧:从 Prompt 范式转变说起
人工智能
道友可好1 小时前
用 Linter 驾驭 AI:机械化执行的艺术
前端·人工智能·后端
王牌狮AIen1 小时前
AI营销智能体实战:OPC如何重构自主获客闭环?
大数据·人工智能·重构·数据挖掘·geo·ai营销
stsdddd1 小时前
YOLO系列目标检测数据集大全【第十九期】
yolo·目标检测·目标跟踪