dirtybeets-lab-targets-v1-pointnet
This repository contains the locked non-IR PointNet release for dirtybeets lab-target prediction.
What It Predicts
cleanweightuncleanweightgap = unclean - cleantare = 100 * gap / unclean
The shipped checkpoint is the current best non-IR PointNet joint model on the signalalign_v1_pointcloud_v1 split.
Headline Metrics
Held-out test metrics from model/summary.json:
clean: MAE2.4220, RMSE3.0135, R²0.5343, count106unclean: MAE2.4472, RMSE3.0504, R²0.5338, count106gap: MAE0.1265, RMSE0.1621, R²0.1033, count106tare: MAE0.5855, RMSE0.8348, R²0.2770, count106
Bundle Contents
model/model.pt: trained PointNet checkpointmodel/summary.json: training summary and metricsmodel/val_predictions.csv: validation predictionsmodel/test_predictions.csv: held-out test predictionsinfer_from_capture.py: end-to-end inference from raw capture folderstraining/train_clean_unclean_pointnet_joint.py: exact joint non-IR PointNet trainer used for this releasetraining/train_clean_pointnet_beetset.py: training utilities and cache builder used by the joint trainerresources/: ROI detector, beet detector, viability classifier, and beet segmenterrequirements.txt: inference dependenciesdeployment_config.json: release metadataresource_manifest.json: packaged file inventory
Input Contract
Each capture directory must contain:
rgb.jpgpointcloud_rgb.ply
The point cloud must be the organized RGB-aligned PLY used in the dirtybeets pipeline, with one (x, y, z, r, g, b) vertex per RGB pixel.
Running Inference
Install dependencies:
pip install -r requirements.txt
Single capture:
python infer_from_capture.py \
--rgb /path/to/capture/rgb.jpg \
--pointcloud /path/to/capture/pointcloud_rgb.ply \
--capture-id capture_001
Batch directory:
python infer_from_capture.py --input-root /path/to/captures
Jetson-safe GPU invocation:
python infer_from_capture.py \
--input-root /path/to/captures \
--device cuda \
--yolo-device 0 \
--viability-batch-size 4 \
--seg-batch-size 1 \
--yolo-half \
--no-tta
The script writes:
detections.csvcrop_manifest.csvsample_manifest.csvpredictions.csvpredictions.json
under the chosen work directory.
Pipeline Structure
- detect the conveyor ROI from
rgb.jpg - detect beet boxes inside the ROI
- classify viability for the stage-3 crops
- segment viable beet crops
- slice the aligned
pointcloud_rgb.plyunder each segmented crop - build beet-set point features
- run the joint PointNet model
Reproducing Training
The exact training code for this release is bundled under training/.
The joint trainer expects the same dataset layout used in dirtybeets training:
sample_manifest.csvcrop_manifest.csvstage1_stage2_stage3_detections_with_viability.csv- aligned
pointcloud_rgb.plycapture folders
Example command:
python training/train_clean_unclean_pointnet_joint.py \
--sample-manifest /path/to/sample_manifest.csv \
--crop-manifest /path/to/crop_manifest.csv \
--detections-csv /path/to/stage1_stage2_stage3_detections_with_viability.csv \
--pointcloud-root /path/to/pointcloud_root \
--out-dir /path/to/output_dir
This locked release corresponds to the non-IR high-tail-oversampled configuration.
Important Note
This release is the locked non-IR PointNet model. An IR-augmented variant was tested later, but it did not beat this model on tare RMSE.
The bundled inference entrypoint uses staged model loading and explicit CUDA cleanup so the full pipeline can run on low-memory Jetson-class GPUs. It was smoke-tested on an 8 GB Orin with the Jetson-safe GPU invocation above.