Top-down pose with a box detector¶
A top-down pose pipeline finds each animal first, then runs a centered-instance
model on a crop around it. Stage 1 is usually a centroid model. It can instead be a
bounding-box detector (bbox_centernet or bbox_ssd, see
Bounding-box detection), and the centered-instance model can then
crop each animal by its box — resized to a fixed crop size — instead of a
fixed-size window around a point:
sleap-nn predict --data_path video.mp4 \
--model_paths models/bbox_centernet \
--model_paths models/centered_instance
The detections that seeded the crops are kept in the output: each predicted instance
comes with a sio.PredictedBoundingBox on LabeledFrame.bboxes, linked to it
(box.instance). The same works for multi_class_topdown and (with fixed crops)
centered_instance_segmentation models.
To generate both configs from your labels:
sleap-nn config labels.slp --auto --pipeline topdown_bbox_centernet -o config.yaml
# -> config_bbox_centernet.yaml + config_centered_instance.yaml (crop_mode: bbox)
sleap-nn train config_bbox_centernet.yaml
sleap-nn train config_centered_instance.yaml
(topdown_bbox_ssd uses the SSD-style detector.) The two configs share
bbox_source / bbox_padding, as they must (below). The TUI (sleap-nn config
labels.slp) offers the same pair.
Crop modes¶
The centered-instance model's data_config.preprocessing.crop_mode decides how a box
becomes a crop. Inference reads it from the model's saved config, so it always crops
the way the model was trained.
crop_mode |
crop_bbox_aspect |
Crop | Animal in the crop |
|---|---|---|---|
fixed (default) |
– | crop_size px window centered on the box center |
native pixel size, like the centroid pipeline |
bbox |
square (default) |
padded box, squared on its longest side, resized to crop_size |
fills the crop at any size, aspect kept |
bbox |
letterbox |
as square, with pixels outside the padded box zeroed |
as square, neighbors masked out |
bbox |
stretch |
padded box resized to the square crop per axis | fills the crop, aspect distorted |
Box-scaled crops (crop_mode: bbox) normalize animal size: a pup and an adult, a
curled and a stretched mouse, or a near and a far animal all fill the crop the same
way. Fixed crops keep pixel size and need a crop big enough for the largest animal.
crop_mode: bbox is supported for centered_instance and multi_class_topdown.
Training a box-scaled centered-instance model¶
data_config:
bbox_source: auto # where boxes come from: the detector's own setting
bbox_padding: 0.0 # pixels added to derived boxes: the detector's own setting
preprocessing:
crop_mode: bbox
crop_bbox_aspect: square
crop_bbox_padding: 0.1 # margin on every side, fraction of the box's longest side
crop_bbox_min_size: null # smallest window side (px); auto: a quarter of the median
crop_size: null # auto: median padded box side, rounded up to max_stride
scale: 1.0
model_config:
head_configs:
centered_instance:
confmaps:
anchor_part: null
centroid_method: bbox_center
- Use the detector's box definition. Each training box is derived exactly as the
detector's ground truth is:
bbox_sourceandbbox_paddingmean the same thing in both configs (a user box linked to the instance, the user mask linked to it, or the tight box of its visible keypoints). Train both models with the same two values —sleap-nn predictwarns when they differ. crop_sizesets resolution, not coverage. Every box is resized to the crop, so the crop no longer has to hold the largest animal. Left unset it is the median padded box side (rounded up to the backbone's max stride), so a typical animal keeps its pixel size; larger animals are downsampled and smaller ones upsampled.crop_bbox_min_sizefloors the window side so a tiny or partial box (one labeled keypoint) is not magnified without bound. Left unset it is a quarter of the median window side. Both values are written into the saved config.- Augmentation works as for fixed crops (rotation, scale, intensity …): it is applied to the scale-normalized crop.
The sleap-nn train log prints the resolved crop size, the p5/p50/p95 window sides
and the resulting scale range.
Fixed crops behind a detector¶
A fixed-crop model can also follow a detector; crops are then centered on the box
centers. Train it with centroid_method: bbox_center (and no anchor_part) so its
training crops are centered the same way — sleap-nn predict warns when the model was
trained on another centroid.
How training and inference stay aligned¶
One rule turns a box into a crop window (BBoxCropSpec in
sleap_nn/data/instance_cropping.py), and both the training datasets and the
inference layer call it. Training cuts crops with Skia and inference with
grid_sample; both put pixel centers at the same coordinates and treat the frame edge
the same way, so the two crops of a box agree to within ~2/255 gray levels. Training
cuts a √2-larger window at the final scale for rotation headroom, augments it, and
re-crops on whole pixels, so an un-augmented training crop is exactly the inference
crop. Keypoints are mapped into and out of the crop by the same affine transform. The
frame is size-matched to the centered-instance model's own max_height/max_width
before cropping.
Evaluation¶
sleap-nn evalscores the pose predictions as for any top-down model.- A box-scaled model run alone on labeled frames (
sleap-nn predict -m centered_instance -i labels.slp) uses ground-truth boxes, derived from the labeled keypoints with the model'sbbox_padding— the box analog of the GT-centroid fallback. Post-training evaluation uses this, so its numbers measure pose quality given perfect boxes.
Limits¶
- A centroid model cannot feed a box-scaled model (it has no boxes); that pairing is refused.
- One first stage per pipeline: a centroid model and a detector together are refused.
sleap-nn exportexports each model on its own; a combined detector + top-down bundle is not supported yet.- The legacy
sleap-nn trackpipeline does not run detectors; usesleap-nn predict --tracking.