spot-wetfloor-convnext-tiny

Binary image classifier: wet (visible standing water or a wet surface) vs dry. Fine-tuned from facebook/convnext-tiny-224 (Apache-2.0). Built for SPOT Dispatch, a readiness board for Boston Dynamics Spot inspection routes. Spot's user guide says not to walk on wet or slippery surfaces, so the board can flag route photos that look wet for an operator to review.

Intended use

  • Advisory flag only. It marks a route image as "possibly wet" so a human operator checks the route before a mission.
  • "dry" never means safe. A dry prediction means only that the model did not see water. Thin films, oil, ice, glare, dark areas, and anything outside the frame are not detected reliably. The operator always confirms.
  • Not for autonomous go/no-go decisions, and not a certified safety system.

How to use

from transformers import pipeline
clf = pipeline("image-classification", model="builtbyd3v/spot-wetfloor-convnext-tiny")
clf("floor.jpg")  # [{'label': 'wet', 'score': ...}, {'label': 'dry', 'score': ...}]

transformers.js (ONNX weights in onnx/model.onnx, fp32):

import { pipeline } from "@huggingface/transformers";
const clf = await pipeline("image-classification", "builtbyd3v/spot-wetfloor-convnext-tiny", { dtype: "fp32" });
await clf("floor.jpg");

Quantized ONNX

onnx/model_quantized.onnx (33.8 MB vs 111.4 MB fp32) loads with { dtype: "q8" }. It is onnxruntime quantize_dynamic, uint8 weights, MatMul/Gemm layers only (convs stay fp32). Scored with onnxruntime on the same test split:

Weights Accuracy (752) Wet recall (752) Same-source accuracy (469) Same-source wet recall (41)
fp32 99.6% 99.1% (321/324) 99.4% 92.7% (38/41)
q8 99.5% 98.8% (320/324) 99.1% 90.2% (37/41)

q8 misses one more same-source wet image and changes 1 of 752 test predictions vs fp32 (kit images: same calls). Use fp32 when recall matters more than load time. Quantizing the convs too (28 MB) lost 2 same-source wet images, so it is not shipped.

Results (held-out test set, never used for training or model selection)

Test set: 752 images (428 dry, 324 wet). 95% CIs are Wilson score intervals per image.

Model Accuracy Wet recall (safety number) Dry recall
Majority class (always dry) 56.9% (53.3-60.4) 0.0% (0.0-1.2) 100.0% (99.1-100.0)
CLIP ViT-B/32 zero-shot 71.8% (68.5-74.9) 72.2% (67.1-76.8) 71.5% (67.0-75.6)
This model 99.6% (98.8-99.9) 99.1% (97.3-99.7) 100.0% (99.1-100.0)

Same-source subset (the honest number). All dry images come from one dataset and most wet images from another, so the full-test score can partly reflect which dataset an image is from. On the Kaggle-only subset (469 images, 41 wet, same cameras and scenes for both classes):

Model Accuracy Wet recall Dry recall
Majority class 91.3% (88.3-93.5) 0.0% (0.0-8.6) 100.0% (99.1-100.0)
CLIP zero-shot 72.9% (68.7-76.7) 87.8% (74.5-94.7) 71.5% (67.0-75.6)
This model 99.4% (98.1-99.8) 92.7% (80.6-97.5) 100.0% (99.1-100.0)

The 41 same-source wet test images come from only 2 scene groups, so the real uncertainty on that wet recall is wider than the per-image CI shows.

CLIP prompts: "a photo of standing water or a wet floor" vs "a photo of a dry floor". Threshold for this model: p(wet) > 0.5.

Domain gap (read this)

  • Training data is public outdoor scenes (sidewalk and road video stills, phone photos of puddles and wet ground). It contains no power-plant floors and no Spot camera frames. It is untested on real Spot images.
  • Sanity check on 6 synthetic plant inspection images (all dry): 4 predicted dry, 2 predicted wet (a pressure gauge close-up at p=0.51, and a thermal pump-bearing image at p=0.63). CLIP called all 6 dry. Expect false alarms on industrial close-ups and thermal images; use it on floor/route views only.

Training data and licenses

Source License Used as Images
Bhutad, S. and Patil, K. (2021). Dataset of Stagnant Water and Wet Surface with Annotations. Mendeley Data, V4. doi:10.17632/y6zyrnxbfm.4 CC BY 4.0 all annotated images (classes water, wet surface) as wet; the unannotated "Raw data" folder skipped 1,976
Mahesa, M. R. Obstacles in Public Spaces for Dist-YOLO. Kaggle: muftirestumahesa/obstacles-in-public-spaces-for-dist-yolo CC0 1.0 images with a puddle box as wet, all others as dry 3,355

Changes made to the Mendeley data (CC BY 4.0 requires saying so): relabeled both classes to one wet class, dropped bounding boxes, resized and cropped for training. These weights are released under CC BY 4.0 to keep the attribution chain clear; the base model is Apache-2.0.

Training

  • Split: StratifiedGroupKFold (7 folds, seed 0) stratified on source+label. Groups are runs of consecutive frames (40-frame blocks for Kaggle video stills, 20-image blocks per folder for Mendeley phone bursts), so near-duplicate frames do not cross splits. Train 3,828 / val 751 / test 752.
  • Recipe: transformers Trainer image classification. 4 epochs, batch 32, lr 5e-5, 10% warmup, weight decay 0.05, best epoch by val accuracy. Light augmentation: random crop 60-100% area, horizontal flip, +-20% brightness/contrast/saturation.
  • Hardware: Apple M4 Pro, PyTorch MPS, 6.5 minutes wall time.
  • ONNX: torch.onnx.export opset 17, max abs logit difference vs PyTorch 5e-7.
  • Training scripts: training/ in this repo.

Known limits

  • Label noise: Kaggle images without a puddle box can still show wet ground; these count as dry.
  • Split groups are filename-based; frames at block edges can still be near neighbors.
  • Daylight outdoor scenes dominate. Indoor floors, night, and IR are barely covered.
Downloads last month
5,639
Safetensors
Model size
27.8M params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for builtbyd3v/spot-wetfloor-convnext-tiny

Quantized
(7)
this model