Pointcept:SmallObjectAnalysis
lastmod 2026-09-14created 2026-09-141 edits
Procedure for analyzing why PointGroup misses small objects
Background
- Running instance segmentation with Pointcept's PointGroup (
PG-v1m1, SpUNet backbone) - Quality was low with the initial 100 scans, so about 600 more PointClouds were added for training
- Even with more data, small objects are still not detected
Summary of conclusions
When small objects are still missed after adding data, the cause is usually not "the amount of data" but one of the three below.
- Size filters hard-coded in the pipeline
- Misses in the semantic branch
- Large-object bias in offset regression
Proceed in an order that checks these three separately.
Structural cause: size filters hard-coded in the code
Reference files:
-
configs/scannet/insseg-pointgroup-v1m1-0-spunet-base.py -
pointcept/models/point_group/point_group_v1m1_base.py -
pointcept/engines/hooks/evaluator.py
The PointGroup code has at least four places that filter out small objects. All are in units of grid_size=0.02 voxels.
| Location | Default | Effect |
| | 0.02 | 2cm voxelization. Point counts of small objects drop sharply |
| | 50 | Clusters with fewer than 50 points are not created |
| | 100 | Proposals with 100 points or fewer are discarded ( |
| evaluator | 100 | Predictions with fewer than 100 points are excluded from evaluation ( |
In other words, objects with 100 points or fewer after voxelization are not output even if the model gets them right, and not evaluated even if output. Increasing the data sixfold leaves this wall in place.
Other structural factors
- Clustering only groups points with the same
segment_pred. If the semantic branch classifies a small class as wall/floor, it never reaches the instance stage at all. - The offset loss is a per-point average, so large objects dominate the gradient. Center predictions for small objects are noisy, so they easily get merged with neighboring objects or split apart within
cluster_thresh=1.5(3cm).
Procedure
1. Data statistics
- Compute the number of instances per class and the distribution of points per instance, measured after applying GridSample 0.02
- Ratio of instances with fewer than 100 points = ratio that is structurally undetectable
- Check the label quality of the 600 added scans
- Whether small objects are labeled consistently
- Whether instance ids are unique within a scene
- Whether the sensor/point density matches the original 100 scans
2. Check the semantic upper bound
- Check per-class semantic IoU on the validation set
- If IoU for small classes is low, it is a semantic problem, not an instance problem
- Remedy: class-weighted CE, oversampling scenes containing small objects, reducing
grid_size
3. Isolate branches with oracle experiments
| Experiment | If AP rises sharply |
| Cluster with GT semantic + predicted offset | Semantic branch problem |
| Cluster with predicted semantic + GT centroid | Offset branch problem |
If neither rises, it is a filter or label problem.
4. Filter relaxation experiment
Just rerun test without retraining.
| Parameter | Default | Relaxed value |
| | 50 | 10 |
| | 100 | 20 |
| evaluator | 100 | 20 |
If AP25 recovers, the model was already detecting them and the filters were throwing them away.
5. Classify failure types
Compare predictions against each small-object GT and tag them into four types.
- Semantic miss
- Merged into a neighboring object
- Split into multiple fragments
- Discarded by a size filter
This distribution determines the final remedy.
6. Check training status
- Going from 100 → 700 scans means 7x the iterations even at the same 800 epochs
- Check the training curve together with AP on the train set
- If small classes are missed even on train, it is underfitting or a label problem
- If they are detected on train but not on val, it is a generalization problem
Candidate remedies
-
grid_size0.02 → 0.01 (2–4x more memory, the most direct fix for small objects) - Normalize the offset loss per instance, or give more weight to small instances
- Class weights in the semantic CE, repeated sampling of scenes containing small objects
- Check whether
SphereCrop sample_rate=0.8crops out small objects - If it is a limitation of PointGroup itself, consider the query-based SGIFormer
-
configs/scannetpp/insseg-sgiformer-v1m1-0-ptv3-base.py
-