Detections
Base class
Detections API: abstract base class, low-level utilities, and auto-detect factory.
- byotrack.api.detections.detections.draw_disk_2d(segmentation: ndarray, positions: ndarray, radii: ndarray, labels: ndarray, *, overwrite=True) ndarray
Draw disks on a 2D segmentation mask.
Modify
segmentationinplace.- Parameters:
segmentation (np.ndarray) – 2D segmentation mask. Empty or pre-filled with other instances. Shape: (H, W), dtype: int
positions (np.ndarray) – Position of the disks to draw. Shape: (N, 2), dtype: float
radii (np.ndarray) – Radii of the disks to draw. Shape: (N, 2), dtype: float
labels (np.ndarray) – Instance labels for each disk. As usual, an offset of 1 is applied, i.e. the ith disk is drawn with labels[i] + 1. Shape: (N,), dtype: int
overwrite (bool) – Allow disk to overwrite the pre-filled segmentation. Default: True
- Returns:
The modified segmentation.
- Return type:
np.ndarray
- byotrack.api.detections.detections.draw_disk_3d(segmentation: ndarray, positions: ndarray, radii: ndarray, labels: ndarray, *, overwrite=True) ndarray
Draw disks on a 3D segmentation mask.
Modify
segmentationinplace.- Parameters:
segmentation (np.ndarray) – 3D segmentation mask. Empty or pre-filled with other instances. Shape: (D, H, W), dtype: int
positions (np.ndarray) – Position of the disks to draw. Shape: (N, 3), dtype: float
radii (np.ndarray) – Radii of the disks to draw. Shape: (N, 3), dtype: float
labels (np.ndarray) – Instance labels for each disk. As usual, an offset of 1 is applied, i.e. the ith disk is drawn with labels[i] + 1. Shape: (N,), dtype: int
overwrite (bool) – Allow disk to overwrite the pre-filled segmentation. Default: True
- Returns:
The modified segmentation.
- Return type:
np.ndarray
- byotrack.api.detections.detections.fast_relabel(segmentation: ndarray, labels: ndarray) None
Inplace fast relabel with given mapping.
It keeps the background as is (0 => 0) and assumes labeling from 0 to N-1 (offset of 1 in segmentation). In practice, it maps instance i to mapping[i-1] + 1.
- Parameters:
segmentation (np.ndarray) – Instance segmentation frame. Shape: ([D, ]H, W), dtype: int
labels (np.ndarray) – Mapping to the targeted labels. Shape: (N,), dtype: int
- byotrack.api.detections.detections.labels_of(segmentation: Tensor) Tensor
- byotrack.api.detections.detections.labels_of(segmentation: ndarray) ndarray
Extract the sorted labels of an instance segmentation mask.
The background is excluded, and labels starts at 0 (offset of 1 with the segmentation mask where the background is 0 and the first label is 1).
- Parameters:
segmentation (torch.Tensor | np.ndarray) – Segmentation mask Shape: ([D, ]H, W), dtype: int
- Returns:
- Sorted labels inside the segmentation mask.
Shape: (N,), dtype: int
- Return type:
torch.Tensor | np.ndarray
- byotrack.api.detections.detections.relabel_consecutive(segmentation: Tensor, *, inplace: bool = True) Tensor
- byotrack.api.detections.detections.relabel_consecutive(segmentation: ndarray, *, inplace: bool = True) ndarray
Relabel a segmentation mask so that labels are consecutive.
For N instances, labels are 0 for background and [1:N] for each instance.
- Parameters:
segmentation (torch.Tensor | np.ndarray) – Segmentation mask Shape: ([D, ]H, W), dtype: int
inplace (bool) – Modify in place. Default: True
- Returns:
Relabeled segmentation (same object if inplace=True)
- Return type:
torch.Tensor | np.ndarray
- byotrack.api.detections.detections.compress(tensor: Tensor, level: int = 3) Tensor
Compress a tensor using zstd.
- byotrack.api.detections.detections.decompress(tensor: Tensor, dtype: dtype = torch.int32) Tensor
Decompress a zstd-compressed tensor.
- byotrack.api.detections.detections.cached(fn: Callable[[_D], torch.Tensor]) Callable[[_D], torch.Tensor]
Enable detections properties caching.
Reads and writes
self._cache(adict[str, torch.Tensor]) using the wrapped method’s__name__as the key. Caching is skipped whenself._use_cacheisFalseor ifselfhas a backing attributef'_{fn.__name__}'(i.e. the property is simply derived from a dedicated storage).Note that
segmentationis compressed before caching ifself._compressis set.- Parameters:
fn – Method to wrap. Its
__name__is used as the cache key.- Returns:
Wrapped callable that checks / populates
self._cache.
- class byotrack.api.detections.detections.Detections(*, confidence: Tensor | None = None, labels: Tensor | None = None, cache: bool = True, compress: bool = False)
Bases:
ABCAbstract base class for frame-level detections.
Represents the set of detected objects in a single video frame. Three concrete implementations exist:
PointDetections: center positions + optional spot radiusBBoxDetections: axis-aligned bounding boxesSegmentationDetections: full instance-segmentation mask
All implementations expose the same properties:
position,bbox,segmentation,confidence,length,dim,shape,mass.The easiest way to create a
Detectionsobject from raw array-like data is viaas_detections(), which automatically selects the right subclass based on the shape and dtype of the input.Note
All positions/bounding boxes use the index coordinate system (not xyz). In ByoTrack the depth axis (k) comes before height (i, row) and width (j, column):
(k, i, j)in 3-D,(i, j)in 2-D.Note
Properties are derived lazily on first access and cached (controlled by the
cacheconstructor argument). For example,PointDetectionscachesbboxandsegmentationthe first time they are requested; subsequent accesses return the cached tensor without recomputation.Note
The
segmentationtensor can additionally be stored in compressed form (ZSTD) to reduce memory usage, controlled by thecompressconstructor argument (defaults to theZSTD_SEGenvironment variable).- position
Center positions. Shape: (N, dim), dtype: float32.
- Type:
torch.Tensor
- bbox
Bounding boxes ([front, ]top, left, [depth, ]height, width), Shape: (N, 2*dim), dtype: int32.
- Type:
torch.Tensor
- segmentation
Instance segmentation mask. Labels are consecutive, from 1 to the length (N), where the detection i is labeled i+1. 0 is assigned to each background pixel. Shape: ([D, ]H, W), dtype: int32.
- Type:
torch.Tensor
- confidence
Per-detection confidence score. Defaults to all-ones. Shape: (N,), dtype: float32.
- Type:
torch.Tensor
- labels
Labels of the detections. Defaults to consecutive labels from 0 to N-1. If given, stored and used to draw
labeled_segmentation. As 0 is the background, labels drawn on segmentation start at 1 (off-by-one). Shape: (N,), dtype: int32.- Type:
torch.Tensor
- mass
Per-detection pixel count (or approximation). Shape: (N,), dtype: int32.
- Type:
torch.Tensor
- labeled_segmentation
Segmentation mask using the
labels. As for thesegmentation, detection i is labeled with labels[i] + 1. ForSegmentationDetections, it provides a mapping to the original segmentation map which has been relabeled consecutively internally. Shape: ([D, ]H, W), dtype: int32.- Type:
torch.Tensor
- metadata
Arbitrary per-detection tensors stored by external components (e.g.
byotrack.FeaturesExtractor). Not persisted bysave().
- abstractmethod filter(kept: Tensor) Detections
Filter the detections based on a boolean tensor.
- Parameters:
kept (torch.Tensor) – Detection to keep. Shape: (N,), dtype: bool
- Returns:
Filtered detections.
- Return type:
byotrack.Detections
- save(path: str | os.PathLike) None
Save detections to a file using
torch.save.- Parameters:
path (str | os.PathLike) – Output path (expected
.ptextension).
- static load(path: str | os.PathLike, *, cache: bool = True, compress: bool = False) Detections
Load detections from a file written by
save().Dispatches to the appropriate subclass based on the
"_type"key.- Parameters:
path (str | os.PathLike) – Input path.
cache (bool) – Cache lazily-computed properties. Default: True.
compress (bool) – Compress the segmentation mask in memory using ZSTD. Defaults to the
ZSTD_SEGenvironment variable value.
- Returns:
The loaded detections object.
- Return type:
- static save_multi_frames_detections(detections_sequence: Sequence[Detections], path: str | os.PathLike) None
Save a sequence of per-frame detections as
{path}/0.pt,1.pt, …- Parameters:
detections_sequence (Sequence[Detections]) – Detections for each frame.
path (str | os.PathLike) – Output folder (created if absent).
- static load_multi_frames_detections(path: str | os.PathLike) list[Detections]
Load a sequence of per-frame detections from a folder.
Expects files named
0.pt,1.pt, …,N.ptin path.- Parameters:
path (str | os.PathLike) – Input folder.
- Returns:
Detections for each frame (ordered by index).
- Return type:
- byotrack.api.detections.detections.as_detections(data: Detections | ndarray | Tensor, **kwargs: Any) Detections
Convert array-like data to the appropriate
Detectionssubclass.Heuristic rules:
Detectionsinstance -> returned unchanged.2-D floating tensor/array of shape
(N, 2)or(N, 3)->PointDetections.2-D integer tensor/array of shape
(N, 4)or(N, 6)->BBoxDetections.2-D or 3-D integer tensor/array ->
SegmentationDetections.
- Parameters:
data (DetectionsLike) – Input data.
**kwargs – Forwarded to the chosen subclass constructor.
- Returns:
Wrapped detections object.
- Return type:
- Raises:
ValueError – If the format cannot be determined.
Instance Segmentation
SegmentationDetections: detections represented by a full instance-segmentation mask.
- class byotrack.api.detections.segmentation_detections.SegmentationDetections(segmentation: torch.Tensor, *, confidence: torch.Tensor | None = None, position_method: str | Callable = 'median', cache: bool = True, compress: bool = False)
Bases:
DetectionsDetections represented by a full instance-segmentation mask.
The primary data is a 2-D or 3-D integer tensor of shape
([D, ]H, W). Labels can be any non-negative integers (consecutive or not); 0 is always background. Non-consecutive labels are stored inlabelsso the original mapping is preserved; internally the mask is relabelled to the consecutive sequence 1, …, N for efficient computation.All other properties (position, bbox, mass) are derived lazily.
- segmentation
Instance segmentation mask. Labels are consecutive, from 1 to the length (N), where the detection i is labeled i+1. 0 is assigned to each background pixel. Shape: ([D, ]H, W), dtype: int32.
- Type:
torch.Tensor
- labels
Labels of the detections. Defaults to the labels of the input segmentation mask so that
labeled_segmentationremap the input segmentation. As 0 is the background, labels drawn on segmentation start at 1 (off-by-one). Shape: (N,), dtype: int32.- Type:
torch.Tensor
- filter(kept: Tensor) SegmentationDetections
Filter the detections based on a boolean tensor.
- Parameters:
kept (torch.Tensor) – Detection to keep. Shape: (N,), dtype: bool
- Returns:
Filtered detections.
- Return type:
byotrack.Detections
Bounding Box
BBoxDetections: detections represented as axis-aligned bounding boxes.
- class byotrack.api.detections.bbox_detections.BBoxDetections(bbox: Tensor, *, confidence: Tensor | None = None, labels: Tensor | None = None, shape: tuple[int, ...] | None = None, cache: bool = True, compress: bool = False)
Bases:
DetectionsDetections represented as axis-aligned bounding boxes.
The primary data is a tensor of bounding boxes
(N, 2*dim)in the format([front, ]top, left, [depth, ]height, width)— i.e. start coordinates followed by sizes in index coordinates.All other properties (position, segmentation, mass) are derived lazily.
Note
Bounding boxes use integer index coordinates. All box sizes must be strictly positive; a zero-size box raises
ValueErrorat construction time.- bbox
Bounding boxes
([k, ]i, j, [dk, ], di, dj)of each detection in index coordinates. Shape: (N, 2*dim), dtype: int32.- Type:
torch.Tensor
- filter(kept: Tensor) BBoxDetections
Filter the detections based on a boolean tensor.
- Parameters:
kept (torch.Tensor) – Detection to keep. Shape: (N,), dtype: bool
- Returns:
Filtered detections.
- Return type:
byotrack.Detections
Point
PointDetections: detections represented as center positions with optional spot radii.
- class byotrack.api.detections.point_detections.PointDetections(position: Tensor, *, radius: float | Tensor = 2.0, confidence: Tensor | None = None, labels: Tensor | None = None, shape: tuple[int, ...] | None = None, cache: bool = True, compress: bool = False)
Bases:
DetectionsDetections represented as center positions with an optional spot radius.
The primary data is a tensor of center positions
(N, dim). All other properties (bbox, segmentation, mass) are derived lazily from the positions and radius.- position
Position
([k, ]i, j)of each detection in index coordinates. Shape: (N, dim), dtype: float32.- Type:
torch.Tensor
- radius
Per detection and axis spot radius for segmentation / bbox conversion. Shape: (N, dim), dtype: float32.
- Type:
torch.Tensor
- filter(kept: Tensor) PointDetections
Filter the detections based on a boolean tensor.
- Parameters:
kept (torch.Tensor) – Detection to keep. Shape: (N,), dtype: bool
- Returns:
Filtered detections.
- Return type:
byotrack.Detections
Statistics utils
Statistics utilities for sequences of detections.
Provides functions to estimate aggregate properties (mass, radius, nearest-neighbor distance,
anisotropy) over a sequence of per-frame byotrack.Detections objects.
- byotrack.api.detections.statistics.average_mass(detections_sequence: Sequence[byotrack.Detections]) float
Return the average mass (pixel surface or volume) per detection over a sequence of frames.
- Parameters:
detections_sequence (Sequence[byotrack.Detections]) – Sequence of per-frame detections.
- Returns:
- Average number of pixels (2D) or voxels (3D) per detection. Returns 0.0 if the
sequence is empty or contains no detections.
- Return type:
- byotrack.api.detections.statistics.average_radius(detections_sequence: Sequence[byotrack.Detections], anisotropy: tuple[float, float, float] = (1.0, 1.0, 1.0)) float
Return the average radius of detections over a sequence of frames.
Assumes each detection is roughly spherical (3D) or circular (2D), and derives the radius from the average mass using the corresponding volume formula:
2D:
mass = π * R²=>R = sqrt(mass / π)3D:
mass = 4/3 * π * R³=>R = (3 * mass / (4 * π)) ** (1/3)
- Parameters:
detections_sequence (Sequence[byotrack.Detections]) – Sequence of per-frame detections.
anisotropy (tuple[float, float, float]) – Anisotropy factors
(ani_z, ani_y, ani_x)used to scale the average mass before computing the radius. These factors convert voxel coordinates to isotropic ones. Default: (1.0, 1.0, 1.0) (no scaling).
- Returns:
- Average detection radius in isotropic coordinates. Returns 0.0 if the sequence
is empty.
- Return type:
- byotrack.api.detections.statistics.average_min_dist(detections_sequence: Sequence[byotrack.Detections], anisotropy: tuple[float, float, float] = (1.0, 1.0, 1.0)) float
Return the average minimal distance between two detections in the same frame.
For each frame with at least two detections, computes the per-detection minimum distance to its nearest neighbor, then takes the median across all detections in that frame (to reduce the influence of outliers). The result is averaged over all eligible frames.
- Parameters:
detections_sequence (Sequence[byotrack.Detections]) – Sequence of per-frame detections. Frames with fewer than two detections are ignored.
anisotropy (tuple[float, float, float]) – Anisotropy factors
(ani_z, ani_y, ani_x)used to scale detection positions before computing distances. Only the lastdimelements of the tuple are applied. Default: (1.0, 1.0, 1.0) (no scaling).
- Returns:
- Average (over frames) of the per-frame median nearest-neighbor distance.
Returns 0.0 if no frame contains at least two detections.
- Return type:
- byotrack.api.detections.statistics.anisotropy(detections_sequence: Sequence[byotrack.Detections], *, only_depth=True) tuple[float, float, float]
Return the average anisotropy found in the detections based on their size.
It makes the assumption that objects do not have a preferential direction and therefore their average size should be isotrope.
The anisotropy is defined as the scaling factors (ani_z, ani_y, ani_x) to scale original coordinates to isotrope ones.
This always takes the last dimension (X) as reference and therefore anisotropy = (ani_z, ani_y, 1).
If only_depth is set to true, the two last dimensions (YX) are used as references and only the axis Z is anisotrope: anisotropy = (ani_z, 1, 1).