Reproduces the SUM Parts (CVPR 2025) face-labeling benchmark on a single consumer GPU, then applies it to drone-photogrammetry road survey meshes. Verified on RTX 3060 12GB / WSL2 Ubuntu 22.04 / CUDA 11.8 / torch 2.0.1: - CUDA extensions build (pointnet2_batch, pointops, chamfer_dist, emd, subsampling) - PointNet 100 epochs reaches mIoU 17.19, matching the paper's reported 15.1 - OBJ -> PLY conversion round-trips through the model and yields per-point predictions Four upstream source patches, all idempotent, originals preserved: - numpy aliases removed in 1.24 (np.long etc.) and collections ABCs moved in python 3.10 - the blind test split ships label = -1, which crashed ConfusionMatrix - mode=val referenced `epoch` before assignment Documents the traps that cost the most time, including VRAM overflow silently falling back to host RAM on WSL2 (25-100x slowdown, no OOM) and the colour scale mismatch between r/g/b float32 and red/green/blue uint8. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
48 lines
1.5 KiB
Bash
48 lines
1.5 KiB
Bash
#!/usr/bin/env bash
|
|
# SUM Parts - inspect label values in the test split
|
|
#
|
|
# test() crashed in ConfusionMatrix.update with
|
|
# RuntimeError: bincount only supports 1-d non-negative integral inputs
|
|
# which means true*num_classes + pred went negative, non-integral, or 2-D.
|
|
# Check what the files actually contain.
|
|
set -uo pipefail
|
|
|
|
DATA="${1:-$HOME/sum-parts/data/face_labeling/texsp_pcl}"
|
|
|
|
source "$HOME/miniconda3/etc/profile.d/conda.sh"
|
|
conda activate sumparts
|
|
|
|
python - "$DATA" <<'PY'
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import numpy as np
|
|
from plyfile import PlyData
|
|
|
|
root = Path(sys.argv[1])
|
|
print(f"root: {root}\n")
|
|
|
|
for split in ("test", "train"):
|
|
files = sorted((root / split).glob("*.ply"))
|
|
print(f"=== {split}: {len(files)} files ===")
|
|
for f in files:
|
|
v = PlyData.read(str(f))["vertex"]
|
|
props = [p.name for p in v.properties]
|
|
if "label" not in props:
|
|
print(f" {f.name:<34} NO LABEL FIELD props={props}")
|
|
continue
|
|
lab = np.asarray(v["label"])
|
|
u = np.unique(lab)
|
|
neg = int((lab < 0).sum())
|
|
flag = ""
|
|
if neg:
|
|
flag += f" NEGATIVE x{neg}"
|
|
if u.max() > 12:
|
|
flag += f" OUT-OF-RANGE max={u.max()}"
|
|
if not np.issubdtype(lab.dtype, np.integer):
|
|
flag += f" NON-INTEGER dtype={lab.dtype}"
|
|
print(f" {f.name:<34} n={len(lab):>8,} dtype={str(lab.dtype):<8} "
|
|
f"range=[{u.min()},{u.max()}] uniq={len(u)}{flag}")
|
|
print()
|
|
PY
|