Paper Walkthroughs
3D Object DetectionPart 5

PointPillars: drop the height axis

PointPillars makes every voxel as tall as the scene, encodes each pillar with a one-layer PointNet and hands a 2D pseudo-image to a plain 2D CNN — no 3D convolution anywhere, and 3D detection at 62 Hz.

October 30, 2026 · 9 min read

Motivation & Main Contribution

  • VoxelNet runs at 4.4 Hz; SECOND reaches 20 Hz with sparse convolution, but its 3D layers remain the bottleneck.
  • Question: do we need 3D convolution at all? After the middle layers, both detectors flatten height into channels anyway.
  • PointPillars answers no: use pillars — voxels spanning the full height — so the grid is 2D from the start.
  • Main contributions:
    • A pillar encoder: a simplified PointNet per pillar, scattered into a 2D pseudo-image.
    • A detector built only from 2D convolutions that runs at 62 Hz, 2–4× faster than prior methods.
    • State of the art on KITTI BEV and 3D among published methods by mAP, LiDAR only.
  • Reading tip: the pillar encoder is the simplest possible use of PointNet in a detector — one linear layer and a max.

Challenges at the Time

  • 3D convolutions are slow, even sparse ones: VoxelNet’s encoder takes 190 ms; SECOND’s open-source encoder 48 ms.
  • Fixed BEV encoders (MV3D, PIXOR, Complex-YOLO) are fast but hand-crafted and need re-engineering for new sensors.
  • Vertical binning is one more hyper-parameter to tune by hand.
  • Sparsity: at 0.1620.16^2 m² cells a 64-beam scan has only 6k–9k non-empty pillars in the KITTI range — about 97% empty.

Naive Questions

  • Doesn’t a pillar lose all height information? No: each point keeps its zz (and offsets) as input features; the PointNet learns the vertical shape.
  • Then why did VoxelNet need 3D convolutions? To aggregate across height; with pillars that aggregation happens inside the per-pillar PointNet.
  • How can a PointNet output become an image? Each pillar vector is written back to its (x,y)(x, y) cell; empty cells stay zero → a C×H×WC \times H \times W pseudo-image.
  • Isn’t one linear layer too weak? The paper uses one PointNet instead of VoxelNet’s two; it saved 2.5 ms with no loss in accuracy.
  • Why care about 62 Hz if a LiDAR spins at 20 Hz? KITTI uses only the ~10% of points in the camera view, and cars run on embedded GPUs.
  • Learned vs fixed encoder — how big is the gap? At equal backbone, learned encoders win at every resolution, and more so with larger pillars (Table 4).

Key Idea

Key idea. Make each voxel a full-height pillar, encode it with a tiny PointNet, scatter the vectors into a 2D pseudo-image, and detect with a 2D CNN — no 3D convolution anywhere.

Encoder for pillar pp with points l^1,…,l^N\hat l_1, \dots, \hat l_N:

fp=MAX⁡i=1..N ReLU⁡(BN⁡(Wl^i))∈RC,pseudo-image[:,yp,xp]=fpf_p = \operatorname{MAX}_{i=1..N}\, \operatorname{ReLU}\big(\operatorname{BN}(W \hat l_i)\big) \in \mathbb{R}^{C}, \qquad \text{pseudo-image}[:, y_p, x_p] = f_p
  • l^i∈R9\hat l_i \in \mathbb{R}^9: the decorated point (x,y,z,r,xc,yc,zc,xp,yp)(x, y, z, r, x_c, y_c, z_c, x_p, y_p) — see below.
  • WW: one linear layer (a 1×11 \times 1 convolution), shared by all points and pillars; C=64C = 64.
  • (xp,yp)(x_p, y_p) in the second formula: the pillar’s grid cell.

Dive into Model Architecture & Key Components

PointPillars end to end (after Fig. 2 of the paper), stage by stage, with the tensor shapes of the car network: a one-layer PointNet per pillar, a pseudo-image, and from there only 2D convolutions.

PointPillars, step by step (car network)

Range x∈(0,70.4)x \in (0, 70.4), y∈(−40,40)y \in (-40, 40), z∈(−3,1)z \in (-3, 1) m; pillar size 0.16 m; at most P=12000P = 12000 pillars and N=100N = 100 points per pillar (Section 4.2):

StageOperation → purposeShape
Inputpoints inside the camera view → the raw measurementn×4n \times 4 (x,y,z,r)(x, y, z, r)
Pillarize + decorategroup by (x,y)(x, y) cell, add 5 features, sample or zero-pad → a dense, fixed-size tensor; no height bins, so no 3D convolutions laterD×P×N=9×12000×100D \times P \times N = 9 \times 12000 \times 100
Linear + BN + ReLUshared over all points → a learned 64-d feature per point (a simplified PointNet)64×12000×10064 \times 12000 \times 100
Maxover the points of each pillar → one feature per pillar, independent of the point order64×1200064 \times 12000
Scatterwrite each pillar to its cell → a 2D pseudo-image, so a standard 2D CNN can follow64×H×W64 \times H \times W
Block1(S=2, L=4, F=64)4 × Conv2D(64, 3), first stride 2 → fine features64×H/2×W/264 \times H/2 \times W/2
Block2(4, 6, 128)6 × Conv2D(128, 3), first stride 2 → larger receptive field128×H/4×W/4128 \times H/4 \times W/4
Block3(8, 6, 256)6 × Conv2D(256, 3), first stride 2 → largest receptive field, scene context256×H/8×W/8256 \times H/8 \times W/8
Up1, Up2, Up3 → stride 2transposed conv to 128 each, concat → combine detail and context at one resolution384×H/2×W/2384 \times H/2 \times W/2
SSD head1×11 \times 1 convs on anchors at 0°0° / 90°90° → per anchor: class, 7 box residuals, directionclass, box (7), direction
  • From the stated range and pillar size, H×W=500×440H \times W = 500 \times 440 cells.
  • Pedestrian / cyclist: first block stride S=1S = 1 instead of 2; range x∈(0,48)x \in (0, 48), y∈(−20,20)y \in (-20, 20), z∈(−2.5,0.5)z \in (-2.5, 0.5) m.

Pillars and point decoration

  • Grid only in xx–yy; no binning in zz.
  • Each point (x,y,z,r)(x, y, z, r) gets:
    • xc,yc,zcx_c, y_c, z_c: offset from the mean of the points in its pillar (VoxelNet’s decoration);
    • xp,ypx_p, y_p: offset from the pillar’s x,yx, y centre (new; +0.5 mAP and more reproducible runs, Section 7.3).
Decoration of one real pillar (0.16×0.160.16 \times 0.16 m, all heights) on the side of a parked car. Each point keeps its own zz, so height is not lost; the offsets tell the PointNet where the point sits relative to the other points of its pillar and to the pillar’s cell. rr is shown as ”–” because this scan stores no reflectance.
  • Fixed-size tensor (D,P,N)(D, P, N): too many pillars or points → random sampling; too few → zero padding.

Builds on. VoxelNet’s decoration (offsets to the mean of the points, walkthrough 03); xp,ypx_p, y_p are new.

Pillar Feature Net: PointNet with one layer

  • Linear → BatchNorm → ReLU on every point, then max over the pillar’s points: exactly PointNet’s “shared MLP + max pool”, with an MLP of depth one.
  • Compared with VoxelNet’s VFE: one layer instead of two stacked VFEs, and no concatenation back to the points.
  • Encoding time 1.3 ms vs 190 ms for VoxelNet’s encoder (Section 6).

Builds on. PointNet’s shared MLP + max pool (walkthrough 01).

Backbone and head: just a 2D detector

  • Backbone like VoxelNet’s RPN: a top-down path of three blocks, each block upsampled back to stride SS and concatenated.
  • SSD head; anchors matched by 2D (BEV) IoU, height and elevation are extra regression targets.
  • Car anchor w,l,h=(1.6,3.9,1.5)w, l, h = (1.6, 3.9, 1.5) m at z=−1z = -1 m, thresholds 0.6 / 0.45. Pedestrian (0.6,0.8,1.73)(0.6, 0.8, 1.73) and cyclist (0.6,1.76,1.73)(0.6, 1.76, 1.73) at z=−0.6z = -0.6 m, thresholds 0.5 / 0.35.
  • Axis-aligned NMS at IoU 0.5: similar accuracy to rotated NMS, much faster.

Builds on. VoxelNet’s RPN-style backbone and anchors, and the SSD detection head.

Loss: SECOND’s recipe

L=1Npos(βlocLloc+βclsLcls+βdirLdir),βloc=2, βcls=1, βdir=0.2\mathcal{L} = \frac{1}{N_{pos}} \left( \beta_{loc} \mathcal{L}_{loc} + \beta_{cls} \mathcal{L}_{cls} + \beta_{dir} \mathcal{L}_{dir} \right), \qquad \beta_{loc} = 2,\ \beta_{cls} = 1,\ \beta_{dir} = 0.2
  • Lloc\mathcal{L}_{loc}: Smooth ℓ1\ell_1 on the 7 residuals, with Δθ=sin⁡(θgt−θa)\Delta\theta = \sin(\theta^{gt} - \theta^a) (SECOND).
  • Lcls\mathcal{L}_{cls}: focal loss, α=0.25\alpha = 0.25, γ=2\gamma = 2. Ldir\mathcal{L}_{dir}: softmax over discretised headings.
  • Adam, learning rate 2×10−42 \times 10^{-4}, decay 0.8 every 15 epochs, 160 epochs; weights initialised randomly (no pre-training).

Builds on. SECOND’s losses (sine angle residual, focal loss, direction classifier) and GT-sampling (walkthrough 04).

Where the speed comes from

  • Runtime breakdown (car network, i7 CPU + 1080 Ti GPU): load and filter 1.4 ms, pillarize and decorate 2.7 ms, upload to GPU 2.9 ms, encode 1.3 ms, scatter 0.1 ms, backbone + head 7.7 ms, NMS 0.1 ms → 16.2 ms.
  • Slimmer design: one PointNet (−2.5 ms), first block lowered to 64 channels (−4.5 ms), upsampled features halved to 128 (−3.9 ms) — none of them hurt accuracy.
  • TensorRT: 45.5% faster than the 42.4 Hz PyTorch pipeline.
  • Pillar size trades speed for accuracy: sizes from 0.1220.12^2 to 0.2820.28^2 m²; at 0.2820.28^2 m² it runs at 105 Hz at similar accuracy to previous methods (Fig. 5).

Augmentation

  • GT-sampling from SECOND: 15 cars, 0 pedestrians, 8 cyclists pasted per sample.
  • Per-box: rotation U[−π/20,π/20]U[-\pi/20, \pi/20], translation N(0,0.25)\mathcal{N}(0, 0.25) — much milder than VoxelNet / SECOND; more per-box augmentation hurt pedestrians (Section 7.2).
  • Global: mirror flip along xx, rotation and scaling, translation N(0,0.2)\mathcal{N}(0, 0.2).

Conclusion

Results

KITTI test, 3D detection (Table 2 of the paper; mAP over car / pedestrian / cyclist, moderate):

MethodModalitySpeed (Hz) ↑mAP Mod. ↑Car Easy ↑Car Mod. ↑Car Hard ↑
MV3DLiDAR & image2.8N/A71.0962.3555.12
ContFuseLiDAR & image16.7N/A82.5466.2264.04
RoarNetLiDAR & image10N/A83.7173.0459.16
AVOD-FPNLiDAR & image1055.6281.9471.8866.38
F-PointNetLiDAR & image5.957.3581.2070.3962.19
VoxelNetLiDAR4.449.0577.4765.1157.73
SECONDLiDAR2056.6983.1373.6666.20
PointPillarsLiDAR6259.2079.0574.9968.30
  • BEV (Table 1): car 88.35 / 86.10 / 79.83; mAP (moderate) 66.19 — the highest in the table.
  • Validation, moderate: 3D AP 77.98 (car), 57.86 (pedestrian), 66.02 (cyclist).
  • Encoder study (Table 4, BEV mAP on val, same network): at 0.1620.16^2 m² PointPillars 73.7 vs VoxelNet 74.4 vs MV3D’s fixed encoder 72.8; at 0.2820.28^2 m² 72.0 vs 71.9 vs 67.6.

Pros and Cons

  • Pros
    • No 3D convolution anywhere: a one-layer PointNet per pillar, then a plain 2D CNN — 62 Hz (105 Hz with larger pillars).
    • Learned encoder: no hand-tuned vertical binning, and it beats fixed encoders at every pillar size.
    • Simple to implement and deploy (TensorRT); it became the go-to fast LiDAR baseline.
  • Cons
    • Not the best everywhere: lower easy-car 3D AP than SECOND.
    • Pedestrians and cyclists are confused with each other and with poles.
    • One vector summarises a whole pillar, so fine vertical detail is compressed early.

Future Work

  • Recover fine geometry from the raw points, e.g. a second refinement stage.
  • Better small-object (pedestrian, cyclist) detection.

Next

  • PointRCNN — the point-based answer: segment the foreground points, propose boxes from them, then refine each box with its raw points.