Downloads · 30 days
0
cpraschl/bambi-red-deer-sex-classifiers
bambi-red-deer-sex-classifiers is a image classification model from cpraschl. Use it when you need a label for an image. It is set up for pytorch. The card lists the license as mit.
Sex classification (male vs femalejuvenile) for red deer in UAV imagery, in the same embedding + head design as bambi-occlusion-classifiers: a raw DINOv3 ViT-H+ embedding goes in, a triplet-loss-trained projection red…
Downloads · 30 days
0
Access
Public
Updated Jul 12, 2026
Repo size
36.4 MB
Likes
0
Public
Click a slice to open those files.
.pt36.4 MB · 100%
From the Hugging Face model README
Sex classification (male vs female_juvenile) for red deer in UAV imagery, in the same
embedding + head design as bambi-occlusion-classifiers:
a raw DINOv3 ViT-H+ embedding goes in, a triplet-loss-trained projection reduces it to a 256-d
embedding, and a logistic head reads that. Each self-contained TorchScript .pt records both the
reducer and the classifier.
Nine models — three projection types x three modalities:
| directory | projection | renders |
|---|---|---|
non_geo/ | perspective (non-orthographic) | — |
geo_1k/ | orthographic | 1k |
geo_2k/ | orthographic | 2k |
Each contains sex_rgb.pt, sex_thermal.pt, and sex_matched.pt.
female_juvenile is a merged class, not "female". It means female or juvenile — juvenile
sex is not determinable from aerial crops, so juveniles of both sexes are pooled with adult females.
Consequences you must design around:
male prediction means adult male. A female_juvenile prediction means "not an adult
male" — it does not mean female.The models are also trained on clear (non-occluded) crops only — occlusion hides the sex cues (antlers, body shape). Filter your crops first; the occlusion classifiers exist for exactly this, and feeding occluded crops in here is out-of-distribution.
forward(x) takes raw DINOv3 CLS features (N, D) and returns a tuple:
embedding (N, 256), L2-normalisedprobs (N, 2) — in classes order ["female_juvenile", "male"]| modality | D | features |
|---|---|---|
rgb | 1280 | RGB CLS |
thermal | 1280 | thermal CLS |
matched | 2560 | [rgb, thermal] concatenated, in that order |
import torch
from huggingface_hub import hf_hub_download
path = hf_hub_download("cpraschl/bambi-red-deer-sex-classifiers", "non_geo/sex_rgb.pt")
m = torch.jit.load(path) # no .eval() needed (BatchNorm folded in)
with torch.no_grad(): # see note below
emb, probs = m(feats) # feats: (N, 1280) raw DINOv3 features
label = m.classes[int(probs[0].argmax())]
confidence = float(probs[0].max())
Wrap inference in torch.no_grad(). These were exported with parameters still requiring grad, so
calling them outside no_grad builds an autograd graph every call and returns requires_grad=True
outputs. (.eval() genuinely is unnecessary — BatchNorm is folded in.)
Attributes: m.classes, m.emb_dim (256), m.reduction ("triplet-loss (batch-hard)"),
m.task ("sex").
These consume DINOv3 features, not images — you must run the DINOv3 ViT-H+ backbone yourself. It is not redistributed here; see the licensing note below.
standardize(mu, sd)
-> Linear(D, 512) + BatchNorm (folded)
-> ReLU
-> Linear(512, 256)
-> L2-normalise <- triplet loss, batch-hard
-> logistic head
Held-out balanced accuracy, GroupKFold by track. Sex is a per-individual property, so track-vote is the headline number (per-crop in parentheses):
| version | rgb | thermal | matched |
|---|---|---|---|
non_geo | 0.758 (0.728) | 0.702 (0.671) | 0.688 (0.712) |
geo_1k | 0.756 (0.734) | 0.719 (0.689) | 0.721 (0.706) |
geo_2k | 0.738 (0.750) | 0.671 (0.628) | 0.685 (0.680) |
RGB is strongest — sex cues are visual (antlers, body shape) and thermal washes them out. Note
that unlike the occlusion task, matched does not help here: fusing a weak thermal signal with a
stronger RGB one drags the result below RGB alone. If you use one model from this repo, use rgb.
These are weak classifiers. Treat them as a research signal, not a label. Best track-vote
balanced accuracy is 0.758 against a 0.5 chance baseline, and the worst configuration
(geo_2k/thermal, 0.671) is not far above coin-flip territory. Roughly one in four track-level calls
is wrong even in the best configuration.
female_juvenile, a naive ratio will be badly biased.The BAMBI UAV dataset — 389 paired RGB/thermal aerial sequences from dual-sensor nadir UAVs over Austrian forest habitats, ~5,100 annotated animal tracks. Evaluation uses GroupKFold by track, so frames from one animal never straddle the train/test split — without this, near-duplicate consecutive frames would inflate accuracy.
Please cite the underlying BAMBI dataset — the authors ask that work building on it cite their CV4Animals workshop paper (Praschl et al., 2026). See bambi-eco/Dataset for the current citation.
These lightweight heads are released under the MIT license. They are only useful on top of DINOv3, which Meta distributes under its own separate, non-MIT terms. MIT here covers these heads only and grants no rights to DINOv3 — review its license yourself before use.