Trained Dinomaly anomaly-detection pipelines for industrial lentils
Three pre-trained Cuvis.AI pipelines for hyperspectral foreign-object detection on a sliding lentil conveyor. All three use the same architecture (a frozen DINOv2 backbone with a Dinomaly anomaly head and a two-stage gate-then-quantile binary decider); they differ only in which three bands the channel-selector node feeds the detector.
The companion dataset repo contains the CU3S session and annotations used by the notebook. This page is the model-side reference: pipeline folders, hparams, weights, and the minimum code to run inference.
Pipelines
| Subfolder | Selector node | Wavelengths (nm) | Image threshold | Quantile | Weight (.pt) |
|---|---|---|---|---|---|
dinomaly_rgb_full_pipeline/ |
FixedWavelengthSelector |
(650, 550, 450) | 0.140 | 0.995 | dinomaly_multifile_rgb_two_stage.pt |
dinomaly_cir_full_pipeline/ |
CIRSelector |
NIR=860, R=670, G=560 | 0.140 | 0.995 | dinomaly_multifile_cir.pt |
dinomaly_custom_selector_full_pipeline/ |
FixedWavelengthSelector |
(542, 902, 886) | 0.151 | 0.995 | dinomaly_multifile_custom_two_stage.pt |
The image_threshold is the gate on the mean of the top-0.1 % per-pixel anomaly scores; only frames above it are pixel-thresholded against the per-frame quantile (0.995). Both knobs are persisted in each pipeline YAML and loaded automatically by restore-pipeline.
Pipeline diagram
- LentilsAnomalyDataNode — reads the
.cu3scube, casts to float32, and maps the multi-class GT mask to a binary anomaly mask (used at training/eval; inference reads the cube directly from the dataloader's batch). - MinMaxNormalizer — running per-cube min-max so the selector sees data in a consistent dynamic range.
- rgb_selector / cir_selector — picks three target wavelengths and emits a 3-channel image. This is the only node that differs between the three methods.
- DinomalyDetector — pre-trained DINOv2 backbone + Dinomaly anomaly head; produces a per-pixel anomaly score map.
- TwoStageBinaryDecider — gates the frame on the mean of the top-k per-pixel scores (image-level threshold), then quantile-thresholds the score map per pixel.
How to use
The pipelines load with the standard Cuvis.AI restore helpers. Minimal end-to-end snippet:
import torch
from huggingface_hub import hf_hub_download
from cuvis_ai_core.utils.node_registry import NodeRegistry
from cuvis_ai_core.pipeline.pipeline import CuvisPipeline
REPO = "cubert-gmbh/XMR_Demo_Industrial_Foreign_Object_Detection_Lentils"
yaml_path = hf_hub_download(
repo_id=REPO,
subfolder="dinomaly_custom_selector_full_pipeline",
filename="dinomaly_multifile_custom_two_stage.yaml",
)
pt_path = hf_hub_download(
repo_id=REPO,
subfolder="dinomaly_custom_selector_full_pipeline",
filename="dinomaly_multifile_custom_two_stage.pt",
)
# The dinomaly plugin (cuvis-ai-dinomaly v0.1.3) auto-fetches its dependencies
# and the DINOv2 backbone on first use.
registry = NodeRegistry()
registry.load_plugins("configs/plugins/dinomaly.yaml") # ships with cuvis-ai
device = "cuda" if torch.cuda.is_available() else "cpu"
pipeline = CuvisPipeline.load_pipeline(
yaml_path,
weights_path=str(pt_path),
device=device,
strict_weight_loading=False,
node_registry=registry,
)
pipeline.torch_layers.eval()
# ... feed a CU3S batch into pipeline.forward(...)
For the full notebook walk-through (preview frames, video export, side-by-side comparison) see notebooks/use_cases/lentils_dinomaly.ipynb in the cuvis-ai repo.
Dataset
Recorded on the same product line and conveyor rig described on the companion dataset card:
cubert-gmbh/XMR_Demo_Industrial_Foreign_Object_Detection_Lentils (dataset)
Acquisition: Ultris XMR · 50 mm · video mode · 15 ms integration · 4 fps · white & dark references recorded.
Training details
- Framework: Cuvis.AI + cuvis-ai-dinomaly v0.1.3.
- Backbone: DINOv2 ViT-B/14 with 4 register tokens (
dinov2reg_vit_base_14), frozen. - Head: Dinomaly anomaly head from anomalib v2.1.0, image size 448, decoder depth 8, bottleneck dropout 0.2.
- Loss / optimizer: Standard Dinomaly training schedule; 50 epochs, weight 1.0 on the train-loss bridge.
- Decider: TwoStageBinaryDecider tuned on a held-out NPZ split (pixel F1) — see each yaml's
decider.hparamsfor the exact threshold values. - Data: Multi-file conveyor lentil sequences under controlled industrial belt lighting. The published CU3S in the companion dataset is one held-out evaluation session.
Contact
Trained and packaged by the AI Team @ Cubert. For pilot enquiries on your own product line, reach out via email or the contact details on https://www.cubert-hyperspectral.com.
