Skip to content

Configuration

deeperfly reads three kinds of TOML file. This page lists the keys of each, with their defaults.

File Says Read by
Project manifest, deeperfly.toml What the videos are every command
Run config What to compute, and what to draw deeperfly run -c
Training config How to train a detector deeperfly train -c

For an introduction, read the tutorial first. examples/octacam.toml and examples/hexaview.toml are complete, commented run configs.

Conventions

These hold in every file:

  • A mistake is reported when the file loads, before anything runs, with the table and key it is in. An unknown key is a mistake, so a typo cannot be silently ignored. deeperfly run --dry-run checks a run config against a project without running it.
  • A table's presence turns its stage on. An empty table means the defaults, and there are no enabled keys.
  • Paths are relative to the file they are written in: to the config's folder in a config, to the project folder in a manifest. ~ expands.
  • A list of names takes * patterns: points = ["lf_*", "neck"]. A pattern that matches nothing is an error.
  • A zero turns a weight, a radius or a width off.
  • Units are in the key's name where they could be mistaken: _deg, _px, _frames, and _p for a probability.
  • Boxes are [x0, y0, x1, y1], sizes are [height, width], and colors are "#rrggbb", "black" or "white".

Project manifest

A folder is a project when it holds deeperfly.toml. The usual place is a folder deeperfly/ inside the folder of videos.

format_version = 1
skeleton = "fly38"
animals = 1
active_calibration = 2
mirrored = ["east", "west", "north", "south"]

[videos]
bottom = ["../bottom.mp4"]
top = ["../top/part-*.mp4"]

[layout]
bottom = ["ventral", "east", "west"]
top = ["dorsal", "north", "south"]

[detections]
runs = ["260925_091200", "pass1"]
Key Default Meaning
format_version 1 The version of this file format.
skeleton "fly38" A packaged skeleton, or the path of a skeleton .toml.
animals 1 How many animals are tracked.
active_calibration none The number of the calibration the GUI labels with, calibrations/0002-*.toml for 2.
mirrored [] The views seen through a mirror or prism.
[videos] required Each video's name and its files. Several files, or a pattern, are played in order. A folder of images is a pattern, "../top/*.png".
[layout] one view per video For each video, the views its frame carries. A video left out carries one view of its own name.
[detections] runs [] The runs whose 2D the GUI and training use, the first listed winning where two cover a frame. Empty means every run, the most recently written winning.

The views of a project are those of [layout], in its order, or else the video names. All videos must have the same number of frames.

A command that takes a project accepts the project folder or the folder of videos that holds its deeperfly/. Given a folder of videos with no project, deeperfly run creates the default one (one view per video file, fly38, one animal) and deeperfly gui opens a form to set one up.

The project folder holds everything deeperfly makes for its videos:

<videos>/
  a.mp4  b.mp4  c.mp4
  deeperfly/
    deeperfly.toml                    the manifest
    skeleton.toml                     only with a custom skeleton
    labels.h5                         the hand labels
    calibrations/0001-<label>.toml    the calibrations
    results/<run>.h5                  a run's arrays
    results/<run>.toml                the config it ran with
    renders/<run>/<output>.mp4        its videos

Run config

deeperfly run <project>... -c config.toml. A run config holds a few top-level keys, [calibration], [compute], and one table per stage. Stages run in the order below, whatever their order in the file.

format_version = 4
name = "nightly"
frames = ["0:1000:2", 5000]
Key Default Meaning
format_version required 4. A file written for another version is refused with a message that says what changed.
name the start time The run's name: it is written to results/<name>.h5. --name overrides it.
frames every frame The frames to compute, as indices and Python slices. --frames overrides it.

Every key can also be set for one run from the command line, as --set table.key=value.

[calibration]

The camera parameters the run starts from. Give either from or [calibration.views]. Every stage after [pose2d] needs one of them.

Key Meaning
from "active" for the project's active calibration, a number for another of its calibrations, or the path of a calibration .toml. The values are copied into the run when it starts.
[calibration.views] One entry per view of the project, by name.

A view is placed on a ring around the animal:

[calibration.views]
distance = 107.463
focal = 22388.125
rh = { azimuth_deg = -120 }
rm = { azimuth_deg = -90 }
rf = { azimuth_deg = -45 }
f  = { }
lf = { azimuth_deg = 45 }
lm = { azimuth_deg = 90 }
lh = { azimuth_deg = 120 }
h  = { azimuth_deg = 180, elevation_deg = 60 }

A key written directly under [calibration.views] applies to every view that does not set it.

Key Default Meaning
distance required From the camera to look_at, in your length unit.
focal required Focal length in pixels.
azimuth_deg 0 Angle around the vertical axis: 0 is on the x axis, 90 on the y axis.
elevation_deg 0 Angle above the horizontal. Exactly 90 or -90 is refused; write 89.9.
roll_deg 0 Rotation about the camera's own axis.
look_at [0, 0, 0] The point the camera aims at.
cx, cy frame center The principal point, in pixels.

A view may instead hold solved parameters, as a calibration file writes them, so a solved calibration can be pasted in: rvec, tvec, intr = [fx, fy, cx, cy], and optionally dist (distortion coefficients, in OpenCV's order) and image_size = [height, width].

[compute]

Settings of the machine, not of the result. Each has a command-line flag (--device, --batch, ...), so a shared config does not have to name one machine's GPU.

Key Default Meaning
device CUDA if available Where the detector runs: "cuda", "cpu", ...
batch 8 Frames per forward pass.
precision "auto" "float32", "float16" or "bfloat16". "auto" picks "bfloat16" or "float16", whichever the GPU runs natively.
compile false Compile the network with torch.compile: about a third faster on a long run, after a minute of compiling.
accumulate "float32" "float16" is faster on consumer GPUs, and needs precision = "float16".

[pose2d]

Runs the detector on every view. Writes pose2d/points, pose2d/conf and pose2d/crops.

[pose2d]
weights = ["261008_mvt_dinov3b_384_octacam_fly38"]
candidates = 5
Key Default Meaning
weights required The detector: a released model's name, or the path of a trained one (a folder means its model.pth). Several are an ensemble.
combine "mean" How an ensemble's members are merged: "mean" or "median".
tta false Also run each frame mirrored and average. Twice the time for a small gain.
candidates 0 Keep this many guesses per keypoint and view, for [pose3d] method = "pictorial".
window "static" "static" crops each view once for the whole run, for a tethered animal. "per_frame" moves the crop with the animal, for a walking one.
tightness 1.5 How much wider than the animal the crop is.
crops found by the detector Fixed crops per view, { f = [x0, y0, x1, y1] }. With several animals, one box each.
locator none The model that finds the animal in the whole frame, named as weights are. Needed with "per_frame" when several views share a video.
crop_aspect the network's Per view, the crop's width / height, when the detector was trained with one ([data] view_aspect).

[pose2d.tracking] is read only with several animals and window = "per_frame". It sets how the animals found in each frame are matched across views and linked over time. Distances are in video pixels.

Key Default Meaning
min_score 0.001 What a candidate animal must score to count.
min_views 2 Views that must see an animal.
gate_px 30 How close a view's detection must be to an animal's reprojection to support it.
min_separation_px 50 Two animals closer than this in every view are one animal found twice.
max_step_px 60 The largest move between two frames.
hold_frames 12 Frames an animal keeps its place without being seen, before it counts as lost.

[bundle_adjustment]

Refines the calibration on this project's keypoints and hands the result to the stages after it. Without this table they use [calibration] as written. It is solved once, on frames sampled over the whole video.

[bundle_adjustment]
points = ["l*", "r*"]
fixed = ["*.intr", "*.dist", "f.rvec", "f.tvec"]
Key Default Meaning
source "pose2d/points" The 2D to fit: the detector's, or "labels/points", the project's hand labels, which needs no [pose2d].
points all The keypoints to fit on.
frames 200 How many frames to sample, evenly.
weighted false Weight each keypoint by the detector's confidence.
loss "huber" "linear", "soft_l1", "huber", "cauchy" or "arctan". All but "linear" tolerate outliers.
threshold_px 8.0 The error beyond which a keypoint counts as an outlier.
max_nfev 200 The solver's evaluation budget.
fixed see below Parameters held constant, as <view>.<rvec, tvec, intr or dist>, optionally with an index: "f.tvec[2]".
shared [] Groups of parameters forced to one value, such as the focal length of views that share a camera.

By default fixed holds every view's intr and dist, and the pose of the first view, which pins the coordinate frame.

[pose3d]

Triangulates the 2D into one 3D point per keypoint. Writes pose3d/points, reproj_error, inliers and support.

[pose3d]
method = "pictorial"
bone_prior = 1.0
Key Default Meaning
method "ransac" See below.
threshold_px 15.0 How far a view may be from the 3D point's reprojection and still agree with it.
min_views 2 Agreeing views a point needs. With fewer it is NaN.
weighted false Weight each view by its confidence.
bone_prior 0.0 "pictorial" only: how strongly to prefer steady bone lengths.
veto [] Views that never take part, for one whose calibration is poor.

The methods:

  • "ransac" finds the largest set of views that agree, and fits those.
  • "dlt" is a plain least-squares fit of all views.
  • "pictorial" chooses among the [pose2d] candidates of each view: it keeps the 3D point most views support, and with bone_prior, the one that keeps the bones' lengths. It recovers a view whose best guess was on the wrong leg. Needs candidates above 0.
  • "election" picks, in each view, the candidate nearest to what the other views say. Cheaper than "pictorial", and less stable.

[smoothing]

Smooths the track over time, with an ensemble Kalman smoother that works from the 2D observations and their uncertainty. Writes smoothing/points and smoothing/var.

Key Default Meaning
smooth_param fitted per keypoint How much the pose may change between frames. Smaller smooths harder.
fit_frames 2000 Frames sampled to fit smooth_param.
fit_iterations 24 Iterations of that fit.
inflate true Trust a view less where it disagrees with the others.
inflate_threshold 5.0 The disagreement beyond which a view is trusted less.
inflate_factor 10.0 By how much its uncertainty grows.
var "confidence_weighted_var" The uncertainty of an observation: the spread of an ensemble's members ("var"), or that spread weighted by their confidence.
fill_unobserved false Give a smoothed value to keypoints no view saw, instead of NaN.

[correction]

Applies anatomical constraints, static first and then symmetrize. Writes correction/points.

[correction.static]
points = ["neck", "*_thorax_coxa"]

[correction.symmetrize]
points = ["l*_thorax_coxa"]
midline = ["neck"]
Key Default Meaning
input the latest 3D The array to correct, such as "smoothing/points".

[correction.static] replaces keypoints that should not move with one position. It is for a tethered animal, and is refused with window = "per_frame".

Key Default Meaning
points [] The keypoints to hold still.
method "median" The position that stands for all frames: "mean", "median", "trimmed_mean", "mode" or "geometric_median".
trim 0.1 "trimmed_mean" only: the share cut from each end.

[correction.symmetrize] makes left-right pairs symmetric about the animal's midline.

Key Default Meaning
points [] One side of each pair. The skeleton names the other.
midline [] The keypoints that define the plane of symmetry.
per_frame false Fit the plane in every frame, for an animal that turns.
strength 1.0 How far to move toward symmetry.

[ik]

Fits a body model to the 3D pose by inverse kinematics. Writes ik/angles, the joint angles, and ik/points, where the fitted model puts each keypoint. Needs the ik extra.

[ik]
fixed_body = false

[ik.bounds]
"c_thorax-lf_coxa-yaw" = [-45, 45]
Key Default Meaning
input the latest 3D The array to fit.
model "neuromechfly" The body model: a packaged one, or the path of a model's folder.
binding from the skeleton Where the skeleton's keypoints sit on the model.
chains all The parts to fit besides the legs, which are always fitted: "head", "abdomen".
fixed_body true Hold the body still and fit the legs to it, for a tethered animal. false also fits the body's position and orientation in every frame. Refused with window = "per_frame" when true.
symmetric_segments true Give a left leg segment and its right counterpart one length.
weighted false Weight each keypoint by the detector's confidence.
iterations 60 Solver steps per frame.
damping 0.1 Damping of each step.
neutral_weight 0.001 Pull toward each joint's resting angle, which settles the angles the keypoints do not determine.
position_tolerance 0.001 Stop early when the fit moves less than this, in model units.
angle_tolerance 0.001 The same for the angles, in radians.
[ik.bounds] the model's Limits of a joint angle in degrees, by its name in ik/angles.
[ik.markers.<chain>] the binding's Where a chain's keypoints sit on the model, replacing the binding's.

[ball]

Tracks the ball under a tethered animal: where it is, how large, and how it turns. Writes ball/center, ball/radius, ball/rotation and ball/tracks. Needs the ball extra, spintrack. One animal only.

[ball]
view = "h"
Key Default Meaning
view required The view in which the ball's rotation is tracked: one that sees its texture, not mirrored.
outline all views The views whose outline of the ball locates it.
input the latest 3D The 3D pose, which tells where the legs rest on the ball.
contact ["*_pretarsus"] The keypoints that touch the ball.
stand ["*_thorax_coxa"] The keypoints whose center is where the animal stands.
front, hind the front and hind thorax_coxa The keypoints that give the body's direction.
contact_frames 1000 How many frames at the start are used to size the ball.
two_pass false Map the ball's texture in a first pass, as spintrack run --two-pass does.
tracking {} spintrack's own [tracking] settings.

How the tables depend on each other

  • [pose3d] needs [pose2d]. [smoothing], [correction], [ik] and [ball] need [pose3d].
  • [bundle_adjustment] needs [pose2d], unless it fits the labels.
  • View names, in [calibration.views], crops, veto, [ball] and the render grids, must be views of the project. [calibration.views] must place all of them.
  • With several animals, [pose2d] and a calibration are required and [ball] is refused.
  • A run config never names the videos, the views, the skeleton or the number of animals. Those are the project's.

Names and reruns

A run is results/<name>.h5 in the project folder, with its config beside it as <name>.toml and its videos in renders/<name>/. --out <folder> writes to <folder>/<project>/ instead.

Running again under the same name continues the run:

  • With the same config, only the frames asked for that are not yet computed are computed. name and frames may differ between the commands.
  • With another config, the command is refused. --force lets the new config replace the old one, and recomputes every stage selected, which --only and --skip limit.
  • A stage is also recomputed when something it depends on changed: a calibration that from names, or the manifest's mirrored.
  • Videos are redrawn over the frames of the latest command.

Render

[render] is the last stage of a run config. Each [render.outputs.<name>] table makes one video, renders/<run>/<name>.mp4. A video is a grid of panels with layers drawn over them.

To redraw videos from a run that already holds the arrays, run only this stage: deeperfly run <project> -c config.toml --name <run> --only render. Add --force if [render] changed since.

Shared settings

Keys under [render] apply to every output. An output may set its own frames, speed, fps, cell, max_size and background.

[render]
frames = [0, 600]
speed = 0.5
Key Default Meaning
frames all of the run's [start, stop] or [start, stop, step].
speed 1.0 Playback speed: 0.5 is half speed.
fps 50 The frame rate of the file. Frames are repeated to reach it, never dropped. 0 writes the playback rate itself.
cell [240, 480] The size of one grid cell, [height, width]. Line widths and text sizes are in these pixels.
max_size [1080, 1920] The largest video written. A larger one is scaled down. 0 leaves a side unlimited.
background "black" The color where a panel shows nothing.
codec "libx264" The video encoder.
crf 18 The encoder's quality: lower is better and larger.

Synthetic views

[render.views.<name>] defines a virtual camera, to look at the 3D pose from an angle no camera has. It takes the placement keys of [calibration.views]. distance and focal may be left out, and are then chosen to fit the pose.

[render.views.top]
elevation_deg = 89.9

[render.views.side]
azimuth_deg = 90

Outputs

[render.outputs.pose2d]
grid = [["rf", "f", "lf"], ["rm", "", "lm"], ["rh", "h", "lh"]]
layers = [
  { draw = "video" },
  { draw = "box", data = "pose2d/crops" },
  { draw = "skeleton", data = "pose2d/points", alpha = "pose2d/conf" },
  { draw = "text", text = "{view}" },
]

[render.outputs.model]
frames = [1000, 1200]
grid = [
  ["top", "top", "rf", "f", "lf"],
  ["top", "top", "rm", "h", "lm"],
  ["angles", "angles", "angles", "angles", "angles"],
]
layers = [
  { draw = "video" },
  { draw = "mesh", data = "ik/points", alpha = 0.55, hide = ["wings"] },
  { draw = "skeleton", data = "ik/points", select = ["lf_*", "rf_*"], radius = 3 },
  { draw = "trace", data = "ik/angles", select = ["*lf_*"], window_frames = 200, panel = ["angles"] },
  { draw = "text", text = "{project}  frame {frame}  {time:.2f}s", panel = ["angles"] },
]
Key Default Meaning
grid required The panel names, row by row.
layers required What to draw, from back to front.
crop the whole frame "pose2d/crops" shows each view cropped to what the detector saw.

A name in the grid is one of:

  • a view of the project, which shows that view's frames;
  • a video of the project, which shows its whole frame with every view it carries, as recorded on a prism rig;
  • a synthetic view from [render.views];
  • any other name, which makes a blank panel for plots and text, such as angles above;
  • "", an empty cell.

A name repeated over a rectangle of cells makes one panel that spans them, as top does above.

Layers

Each layer has a draw kind, and most name the array to draw as data. A layer is drawn in every panel that can show it. panel = ["angles"] restricts it to some.

draw Draws Keys
"video" The panel's camera frames alpha
"skeleton" Keypoints and bones, from any 2D or 3D points array select, color, colors, edge_color, radius, width, dash, outline, alpha, alpha_range, identity
"mesh" The body model, from ik/points alpha, hide
"box" A rectangle per animal and view, from pose2d/crops color, width, dash, alpha
"ball" The ball's outline and the path walked on it, from ball/center color, width, alpha, window_frames
"trace" A scrolling plot, from an array with named channels such as ik/angles select, window_frames, width, color
"text" A caption text, size, color, anchor
Key Meaning
select The keypoints, or a trace's channels, to draw.
color One color for the layer. A skeleton otherwise uses its own colors, per leg.
colors A color per keypoint name: { "lf_*" = "#ff0000" }.
edge_color One color for every bone.
radius The size of a keypoint's dot. 0 draws bones only.
width Line width. 0 draws dots only.
dash A dash pattern, [on, off].
outline The width of an outline under the marks, for contrast on pale footage.
alpha Opacity from 0 to 1, or an array to fade by: alpha = "pose2d/conf" fades uncertain keypoints.
alpha_range [lo, hi], the array values that map to transparent and opaque. [20, 0] with alpha = "pose3d/reproj_error" fades keypoints with a large error.
identity How several animals are told apart: "hue" (the default), "label", "dash" or "none".
hide Parts of the body model to leave out.
window_frames How many past frames a trace or the ball's path shows.
text The caption. {view}, {frame}, {time}, {fps} and {project} are filled in.
size Text size.
anchor Where the text sits: "top-left" to "bottom-right", "top", "center", ...

data names an array of the run, as Output lists them. 3D points are projected through the panel's camera, real or synthetic. One more name is available: labels/points, the project's hand labels.

Training config

deeperfly train -c config.toml [project...]. Training a detector explains how to use it. This file format is less settled than the run config: a key may be renamed in a later version. The tables below cover the keys you are likely to set, and the API reference documents the rest.

format_version = 3

[data]
projects = ["../octacam/recordings/*"]
holdout = ["AN07B017_260414_Fly4_00*"]

[data.crops]
tightness = [0.75, 2.2]

[data.fill]
weight = 1.0

[model]
family = "mvt"
backbone = "vit_small_patch16_dinov3.lvd1689m"
pretrained = true
input_hw = [384, 768]
attn_scopes = "llllllllglgl"
margin = 64

[augment]
degrees = 12.0
brightness = 0.3
contrast = 0.3
gamma = [0.7, 1.4]

[train]
steps = 16000
images_per_batch = 24
amp = true
ema_decay = 0.999
view_drop_p = 0.3

[train.optimizer]
lr = 5e-5

[train.loss]
field_weight = 1.0
tri_weight = 0.02

[train.eval]
every = 1000
select_best = "overall.pck"

[compute]
workers = 8

[data]

Key Default Meaning
projects [] The projects to train on, as paths or patterns. Projects given on the command line replace the list. All must share one skeleton.
holdout [] Projects kept out of training and scored, by name.
train every other Projects to train on. Empty means every project that is not held out.
split none A file that lists what to hold out, by project or by frame.
task "pose" "pose" trains a detector. "locate" trains a locator, which finds the animal in the whole frame.
center_channel false Also predict each animal's center. For several animals.
mark_others false With several animals, mark the other animals' centers in each crop, so the detector knows which animal a crop is about.
mark_jitter 6.0 The error given to those marks in training, in pixels.
keypoint_weights {} A loss weight per keypoint name.
view_aspect {} Per view, the crop's width / height, for a view far from the network's shape.
off_view_weight 1.0 The weight of a keypoint that lies outside its view's image.
view_sides {} Per view, "left" or "right", for the report's breakdown.
cache cache/ beside the file Where decoded frames are cached.
kind "project" "df3d" or "lightning_pose" train on a dataset in that format, given as root.

[data.crops] sets how training samples are cropped around the animal.

Key Default Meaning
tightness [0.9, 2.2] The range the crop's size is drawn from, relative to the animal. Below 1 cuts keypoints off on purpose.
jitter 0.1 How far the crop is shifted, as a share of its size.
eval_tightness 1.25 The crop size for held-out samples.
min_points 4 With fewer labeled keypoints than this in a view, the crop falls back to the whole frame.
full_p 0.1 The probability of training on the whole frame instead.

[data.fill] gives the views a frame does not label a target, by projecting the 3D position its labeled views fix. It needs the project's active calibration.

Key Default Meaning
weight 1.0 The weight of these targets. 0 turns the fill off.
max_residual_px 10.0 Skip a keypoint whose labeled views disagree by more than this.
min_views 2 Labeled views a keypoint needs.

[data.boost] draws some projects more often than their size gives: projects selects them, and share (default 0, off) is the part of each epoch they make up.

[model]

Key Default Meaning
family "monocular" The architecture. "mvt" is a multiview transformer that reads all views of a frame together, as the released detectors are. "fast" is a small convolutional network, as the released locators are. "monocular" and "simcc" read one view at a time.
backbone the family's A timm model name.
pretrained false Start the backbone from its published weights.
input_hw [256, 512] The network's input size, [height, width].
init_from none Start from a trained detector: a released model's name, or the path of an earlier training.

Each family takes a few keys of its own, such as margin and attn_scopes for "mvt". The config stored with each released model shows the ones it used.

[augment]

Random changes applied to training samples. Without the table there is no augmentation; an empty table means these defaults.

Key Default Meaning
degrees 5.0 Rotation, up to this angle.
scale [0.9, 1.1] Range of zoom.
aspect [1.0, 1.0] Range of stretch.
translate [0.03, 0.03] Shift, as a share of the size.
flip_p 0.5 Probability of a left-right flip.
rig_symmetry false Flip all views of a frame together, as a mirror image of the rig, instead of each on its own.
brightness, contrast 0.2 Range of change.
gamma, blur_sigma off A range, [lo, hi].
noise_std 0.0 Added noise.
photometric_p 0.5 Probability that the brightness, contrast, gamma, blur and noise changes apply.

[train]

Key Default Meaning
steps 10000 How many optimizer steps to train for.
batch_size 16 Samples per step.
images_per_batch 0 For a multiview model, a cap on the images per step, since frames differ in their number of views.
amp false Mixed precision: faster, and less memory.
ema_decay 0.0 Average the weights over training, with this decay.
view_drop_p 0.0 For a multiview model, the probability of hiding a view, so it learns to do without.
view_min 1 Views always kept.
grad_clip 0.0 Limit on the gradient's size.
grad_checkpoint false Trade speed for memory, to fit a larger model.
seed 0 The random seed.
log_every 50 Steps between log lines.
out a folder named after the file Where the training is written. --out overrides it.

[train.optimizer] takes lr (default 2e-4), weight_decay (0.05), warmup_steps (500) and backbone_lr_mult (1.0).

[train.loss] sets the weight of each term of the loss, and a zero turns a term off: fg_weight (30.0), field_weight (0.0), center_weight (0.25), coord_weight (0.0) and tri_weight (0.0), which rewards views that agree on one 3D point. sigma (2.0) is the width of the target around a keypoint.

[train.eval] scores the held-out projects.

Key Default Meaning
every 0 Steps between evaluations. 0 evaluates at the end only.
pck_px 10.0 The distance within which a keypoint counts as correct.
tta false Evaluate with the mirrored pass too.
select_best none Keep the weights that scored best on this metric, such as "overall.pck", rather than the last. Needs a holdout and every.

[compute] and [unlabeled]

[compute] takes device and workers (default 4), the number of data-loading processes.

[unlabeled] adds frames without labels to the training. A teacher detector predicts all views of sampled frames, and where enough views agree on a 3D position, its projection is used as the target.

Key Default Meaning
teacher the projects' detections The teacher, named as init_from is. It must not have trained on the holdout.
n_per_project 200 Frames sampled per project.
agree_px 6.0 How close a view must be to the consensus to agree.
min_views 3 Agreeing views a keypoint needs.
conf_min 0.3 Below this confidence a view has no say.
weight 0.5 The weight of this term against the labeled loss.
exclude [] Projects left out.