PC²-AD
September 7, 2026 · View on GitHub
Official implementation of PC²-AD, a detector-agnostic resolution-alignment framework for low-resolution 3D point-cloud anomaly detection.
PC²-AD restores a sparse test cloud to its protocol-defined sampling scale without deleting or moving the observed input points. It then exposes the aligned cloud to an existing 3D anomaly detector without changing the detector's anomaly-scoring rule.
Method at a glance
PC²-AD separates candidate construction, geometric safety, and normality guidance:
- Resolution-controlled preparation creates
test_inputand projects point-level ground truth with the exact same FPS indices. - Candidate Generator adaptation learns an unsigned local point-to-normal-surface distance field from normal training clouds.
- Contrastive normality learning trains a PointNet encoder on patches produced by the frozen Candidate Generator, then builds classwise normal Feature Banks.
- Formal alignment generates an over-complete candidate pool, performs exact-count geometry-safe selection, and applies same-anchor one-to-one normality replacement.
- Traceable output preserves the input as the unchanged output prefix and writes point provenance arrays.
The Candidate Generator does not directly regress final XYZ offsets. P2PNet predicts one non-negative distance per query point; formal generation minimizes that learned distance with respect to query coordinates for ten iterations.
See docs/ARCHITECTURE.md and the code-level Chinese walkthrough docs/PIPELINE_WALKTHROUGH_ZH.md.
Supported protocols
| Dataset configuration | Sparse-input policy | Output target | Rounds |
|---|---|---|---|
Anomaly-ShapeNet pcd | floor(class normal-train mean / 4) | 1 | |
Anomaly-ShapeNet new_pcd | floor(class normal-train mean / 4) | 1 | |
| Real3D-AD | floor(original sample count / 4) | original per-sample count | 1 |
The exact contracts are in docs/DATA_CONTRACT.md, docs/OUTPUT_CONTRACT.md, and docs/EXPERIMENT_PROTOCOL.md.
External resources
The original datasets and third-party downstream anomaly detectors are not included in this Git repository. Please obtain them from their official sources and comply with their respective licenses and terms of use.
The released PC²-AD checkpoints and frozen training/evaluation data are available from Google Drive.
checkpoints.tar.gzcontains the pretrained and adapted distance estimators, contrastive learning checkpoints, category-specific feature centers, normal feature banks, distance statistics, and normality thresholds.data.tar.gzcontains normal training point clouds, low-resolution test inputs, resolution-compensated outputs, projected ground-truth labels, FPS indices, and point provenance information.
See Section S1 of the supplementary material for details of the
released files. The expected local directories are checkpoints/
and data/ under the repository root.
Repository layout
PC2-AD/
├── approach/
│ ├── data_preparation/ # plans, sparse inputs, projected GT, audits
│ ├── train/ # Candidate Generator and normality training
│ └── generate/ # formal queue, scheduler, generation pipeline
├── checkpoints/ # frozen asset registry and integrity records
├── configs/ # training, normality-data, and generation
├── data/ # local datasets and plan CSV files
├── docs/ # contracts, architecture, status, release guidance
├── environments/ # build and environment guidance
├── results/ # local generated/evaluation workspaces
├── scripts/ # launchers and audits
├── tests/ # contract and regression tests
└── training_artifacts/ # local generated training data/checkpoints
Canonical data layout
Original datasets are not committed. The canonical local layout is:
data/
├── anomaly_shapenet/
│ ├── pcd/<class>/
│ └── new_pcd/<class>/
└── real3d_ad/<class>/
Prepared classes contain the relevant subset of:
train/
test_input/
gt_projected/
fps_indices/
test_output/
is_input_point/
source_index/
round_id/
metadata/
Preparation never overwrites the source dataset.
Environment
The validated workflow uses Python 3.8, CUDA-enabled PyTorch, Open3D 0.18, FAISS-GPU, NumPy, SciPy, pandas, scikit-learn, PyYAML, h5py, and TensorBoard. Vendored CUDA extensions must be compiled in the same PyTorch/CUDA environment used for training and generation.
Set executable paths explicitly:
export PC2AD_GENERATE_PYTHON=/path/to/generation/environment/bin/python
export PC2AD_TRAIN_PYTHON="$PC2AD_GENERATE_PYTHON"
Asset isolation
Every dataset configuration has its own:
- Candidate Generator checkpoint;
- Contrastive Normality Pretraining and Mean-Shifted Contrastive Fine-Tuning checkpoints;
- class centers and Feature Banks;
- distance statistics and thresholds;
- plan, queue, cache, logs, and output directories.
Do not mix assets across anomaly_shapenet_pcd, anomaly_shapenet_new_pcd, and real3d_ad. Registered public assets and hashes are listed in checkpoints/ASSET_REGISTRY.csv and the selected configuration.
Data preparation
Build an Anomaly-ShapeNet plan
python -m approach.data_preparation.anomaly_shapenet.build_plan \
--dataset_root /path/to/Anomaly-ShapeNet/pcd \
--output_root "$PWD/data" \
--subset pcd \
--plan_csv data/plans/anomaly_shapenet_pcd_plan.csv
Use --subset new_pcd for the second configuration.
Build a Real3D-AD plan
python -m approach.data_preparation.real3d_ad.build_plan \
--dataset_root /path/to/Real3D-AD \
--output_root "$PWD/data" \
--plan_csv data/plans/real3d_ad_plan.csv
Run the dependency-light data contract tests:
python -m unittest approach.data_preparation.tests.test_synthetic -v
Archived formal preparation audits report 1312/1312 pcd, 411/411 new_pcd, and 1206/1206 Real3D-AD samples passed.
Training
Use one dataset configuration at a time.
1. Build Candidate Generator pairs
"$PC2AD_TRAIN_PYTHON" \
-m approach.train.candidate_generator.build_candidate_data \
--config configs/train/anomaly_shapenet_new_pcd.yaml \
--device cuda:0
This writes normalized candidate_1024/gt_1024 H5 pairs.
2. Train the Candidate Generator
CUDA_VISIBLE_DEVICES=0,1,2,3,4 \
PC2AD_TRAIN_PYTHON="$PC2AD_TRAIN_PYTHON" \
bash scripts/train_candidate_generator_5gpu.sh \
anomaly_shapenet_new_pcd
The formal trainer is approach.train.candidate_generator.train. The released configuration uses 90 epochs, per-GPU batch size 8, Adam at 1e-5, AMP, TF32, and exact-once no-padding DDP sampling.
3. Build normality patches
"$PC2AD_TRAIN_PYTHON" \
-m approach.train.contrastive_normality.build_normality_data \
--config configs/train/anomaly_shapenet_new_pcd.yaml \
--candidate_checkpoint \
training_artifacts/anomaly_shapenet_new_pcd/candidate_generator/selected/best.pth \
--gpus 0,1,2,3,4
Normal training clouds are sparsified, restored by the frozen Candidate Generator, and converted to normalized 1024-point patches.
4. Contrastive Normality Pretraining
CUDA_VISIBLE_DEVICES=0,1,2,3,4 \
"$PC2AD_TRAIN_PYTHON" \
-m approach.train.contrastive_normality.train_contrastive_pretrain \
--config configs/train/anomaly_shapenet_new_pcd.yaml \
--run_id formal_seed42
Contrastive Normality Pretraining runs for 60 epochs and saves every epoch. Preserve epoch_0050.pth.
5. Mean-Shifted Contrastive Fine-Tuning
CUDA_VISIBLE_DEVICES=0,1,2,3,4 \
"$PC2AD_TRAIN_PYTHON" \
-m approach.train.contrastive_normality.train_contrastive_msc \
--config configs/train/anomaly_shapenet_new_pcd.yaml \
--init_checkpoint \
checkpoints_retrained/anomaly_shapenet_new_pcd/contrastive_pretrain/<run>/checkpoints/epoch_0050.pth \
--run_id formal_seed42
Mean-Shifted Contrastive Fine-Tuning computes classwise centers and trains for 50 epochs.
6. Build Feature Banks
"$PC2AD_TRAIN_PYTHON" \
-m approach.train.contrastive_normality.build_feature_bank \
--config configs/train/anomaly_shapenet_new_pcd.yaml \
--checkpoint \
checkpoints_retrained/anomaly_shapenet_new_pcd/contrastive_msc/<run>/checkpoints/best.pth \
--run_id formal_seed42 \
--gpus 0,1,2,3,4
The Feature Bank stores normalized 128-dimensional normal projections and two-neighbor cosine-distance statistics.
See docs/TRAINING_STATUS.md for the audited formal artifact identities.
Formal generation
Build an isolated SQLite queue:
"$PC2AD_GENERATE_PYTHON" \
-m approach.generate.common.build_queue \
--config approach/generate/configs/anomaly_shapenet_new_pcd.json \
--stage_round 1 \
--scheduler_db \
results/generation/anomaly_shapenet_new_pcd/scheduler/tasks.sqlite \
--reset
Start one persistent worker on each configured physical GPU:
"$PC2AD_GENERATE_PYTHON" \
-m approach.generate.common.scheduler \
--config approach/generate/configs/anomaly_shapenet_new_pcd.json
Formal generation uses deterministic Morton-block FPS, 1024-point candidate patches, ten gradient refinement steps, geometry-safe exact-count selection, and same-anchor one-to-one normality replacement.
Generation is audited as complete for 2929 samples. See docs/GENERATION_STATUS.md.
Output contract
For upsampled samples:
test_output[0:N] == test_input
is_input_point[0:N] == 1
round_id[0:N] == 0
source_index[0:N] == 0..N-1
is_input_point[N:] == 0
round_id[N:] == 1
source_index[N:] == -1
Object-level inference uses all test_output points. Point-level metrics use only is_input_point == 1 and gt_projected.
Reproducibility evidence
docs/DATA_PREPARATION_STATUS.mddocs/TRAINING_STATUS.mddocs/GENERATION_STATUS.mddocs/TASK_STATUS.mddocs/RELEASE_CHECKLIST.md
Release hygiene
Do not publish machine-specific build products, __pycache__, smoke outputs, training workspaces, result workspaces, migration backups, or ABI-specific compiled extensions. Do not run destructive cleanup commands on a dirty worktree. Follow docs/RELEASE_CHECKLIST.md and the release audit.
Every redistributed vendor tree must include confirmed upstream license evidence. See THIRD_PARTY_NOTICES.md.
License
Repository-original PC²-AD code is released under the repository-level license. Vendored components retain their upstream licenses and notices.
Citation
Citation information will be added after publication.