missing_node
sleap.qc.features.missing_node
¶
Missing-node detection: labelable points left unlabeled.
This module implements a geometry/visibility-only heuristic (Tier-1) for detector (f): "labelable points left unlabeled". The idea is to flag instances that are missing a node which their peers (instances where the same co-visible nodes are present) usually keep visible.
The detector reuses the co-visibility statistics learned by
:class:sleap.qc.features.visibility.VisibilityModel: the integration layer
fits that model on the labeled dataset and passes the learned
co_visibility_matrix (P(node_j visible | node_i visible)) here. This
module itself is a pure function and learns nothing.
Honest scope / limitations: This only catches outlier drops -- an individual instance that is missing a node its co-visible peers keep. It does NOT catch dataset-wide systematic under-labeling (e.g. nobody in the project ever labels the tail tip). When a node is rarely labeled, the co-visibility column for that node is small for everyone, so its expected probability stays low and it is never flagged. Detecting systematic under-labeling requires a model-based (Tier-2) approach that compares against learned appearance/geometry rather than only the project's own visibility statistics.
Functions:
| Name | Description |
|---|---|
score_missing_nodes |
Score whether an instance is missing nodes its peers usually keep. |
score_missing_nodes(visibility_mask, co_visibility_matrix, edges, threshold=0.9, require_neighbors_visible=False)
¶
Score whether an instance is missing nodes its peers usually keep.
For each invisible node k we estimate the probability that it
should be visible given the nodes that are actually present::
p_expected[k] = mean over visible nodes i of co_visibility_matrix[i, k]
where co_visibility_matrix[i, k] = P(node k visible | node i visible)
(the convention used by :class:VisibilityModel). A node is flagged as
suspiciously-missing when p_expected[k] >= threshold -- i.e. nodes that
co-occur with the visible nodes nearly always also bring k along, yet
k is absent here.
Optionally (require_neighbors_visible=True) a node is only flagged when
all of its skeleton neighbors (from edges) are visible, which makes
the heuristic stricter: an isolated missing node surrounded by present
neighbors is a much stronger signal of an accidental drop than a node on
the boundary of an occluded region.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
visibility_mask
|
ndarray
|
|
required |
co_visibility_matrix
|
ndarray
|
|
required |
edges
|
list[tuple[int, int]]
|
List of |
required |
threshold
|
float
|
Minimum expected visibility probability for a missing node to
be flagged as suspicious. Defaults to |
0.9
|
require_neighbors_visible
|
bool
|
If |
False
|
Returns:
| Type | Description |
|---|---|
dict
|
Dictionary with:
|
Source code in sleap/qc/features/missing_node.py
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | |