itasc.correction.labels¶
Label correction operations on a single (H, W) segmentation frame.
All functions accept a 2-D seg array and modify it in-place.
They return True on success and False when the operation is
rejected (e.g. labels don’t touch, result too small, background click).
Functions
|
Spawn a new cell at pos in empty space. |
|
Return the non-zero target label with most overlap against source_label. |
|
Cut neighbouring cells along the drawn line and annex the near pieces. |
|
Remove disconnected same-label fragments, keeping each label's largest component. |
|
Draw a closed region from the user's stroke and fill its interior. |
|
Set all pixels of the label under pos (or label) to 0. |
|
Expand |
|
Fill background holes enclosed within a single cell. |
|
Fill a hole enclosed by a single cell except for a narrow image-edge opening. |
|
Return a 2D frame view from a time-indexed label stack. |
|
Merge the cell at pos_start into the cell at pos_end. |
|
Assign new_label to the cell at pos in seg (in-place). |
|
Watershed-split the cell under pos_start using two seeds. |
|
Split a cell along a manually drawn line. |
|
Swap the label values at the two click positions across the whole frame. |
- itasc.correction.labels.frame_view_2d(arr, t)[source]¶
Return a 2D frame view from a time-indexed label stack.
- itasc.correction.labels.best_overlapping_label(target_labels, source_labels, t, source_label)[source]¶
Return the non-zero target label with most overlap against source_label.
- itasc.correction.labels.expand_label_to_foreground(seg, foreground, label, *, max_distance)[source]¶
Expand
labelinto connected foreground background pixels in-place.Returns the number of newly labelled pixels. A
max_distanceof 0 means no distance cap.
- itasc.correction.labels.erase_cell(seg, pos=None, *, label=None)[source]¶
Set all pixels of the label under pos (or label) to 0.
- itasc.correction.labels.add_cell(seg, pos, *, new_label, radius=6, image=None, protected_mask=None)[source]¶
Spawn a new cell at pos in empty space.
When image (a nucleus/intensity frame the same shape as seg) carries a clear local signal the new cell snaps to it; otherwise a disk of radius is stamped. Only background pixels are written — existing cells and any protected_mask pixels are never overwritten — so the result can’t clobber neighbours. Returns
Falsewhen pos is on an existing cell or nothing paintable remains.
- itasc.correction.labels.merge_cells(seg, pos_start, pos_end, *, label_a=None, label_b=None)[source]¶
Merge the cell at pos_start into the cell at pos_end.
- itasc.correction.labels.split_across(seg, img, pos_start, pos_end, *, new_label=None)[source]¶
Watershed-split the cell under pos_start using two seeds.
- itasc.correction.labels.split_draw(seg, positions, *, curlabel=None, new_label=None)[source]¶
Split a cell along a manually drawn line.
- itasc.correction.labels.carve_into_selected(seg, positions, *, selected_label)[source]¶
Cut neighbouring cells along the drawn line and annex the near pieces.
The user draws a line through one or more neighbouring cells, starting from (or towards) the selected cell. Every other cell the line crosses end to end is split along that line — exactly like the Shift+Right split gesture of the nucleus widget — into two fragments. The fragment that touches the selected cell is then merged into it; if both fragments touch, the smaller one is taken so the neighbour keeps its bulk. A cell the line only clips (without dividing it in two) is left alone.
Cells are merged iteratively: a fragment that is not adjacent to the selection at first can become adjacent once a cell between them has been annexed, so each pass re-checks adjacency against the grown selection until no further fragment touches it. Only one fragment per neighbour is ever annexed, so the cell label set stays in lock-step with the nuclei — no label is created, deleted or renumbered.
Cutting clean through the selected cell takes priority and is exclusive: if the line divides the selection in two, its smaller piece is removed entirely (set to background), the larger piece stays as the selected cell, and no neighbour is annexed on that stroke.
A line that divides nothing (e.g. a straight swipe over background, or a stroke that never fully crosses a cell) is a no-op. Returns
Trueif any pixel changed.
- itasc.correction.labels.draw_cell_path(seg, positions, *, curlabel=None, new_label=None, protected_mask=None)[source]¶
Draw a closed region from the user’s stroke and fill its interior.
- itasc.correction.labels.swap_labels(seg, pos_a, pos_b)[source]¶
Swap the label values at the two click positions across the whole frame.
- itasc.correction.labels.relabel_cell(seg, pos, new_label)[source]¶
Assign new_label to the cell at pos in seg (in-place).
If new_label already exists in the frame, the two cells are swapped so no label is lost. Returns
Falsewhen pos hits background, already has new_label, or new_label is 0.
- itasc.correction.labels.fill_label_holes(labels, radius=5)[source]¶
Fill background holes enclosed within a single cell.
A “hole” is a background component that does not touch the image border and is surrounded by exactly one label; it is filled with that label. Background bordered by two or more cells is an inter-cellular gap, not a hole, and is left untouched (so cells are never expanded into the space between them).
radiuscaps the hole depth: a hole is only filled when its deepest pixel lies withinradiusof the surrounding cell.radius <= 0is a no-op.
- itasc.correction.labels.fix_label_semiholes(labels, radius=5, max_opening=3)[source]¶
Fill a hole enclosed by a single cell except for a narrow image-edge opening.
Like
fill_label_holes(), but for background that escapes to the image border through a thin gap (up tomax_openingpixels of edge contact). The opening’s edge flanks are ignored; the hole is filled only when its interior is enclosed by exactly one label, so cells are never expanded into inter-cellular gaps.radiuscaps the hole depth as infill_label_holes().radius <= 0ormax_opening <= 0is a no-op.
- itasc.correction.labels.clean_stranded_pixels(seg, min_size=4, *, exclude=None)[source]¶
Remove disconnected same-label fragments, keeping each label’s largest component.
Fragments are cleared and then
expand_labelsis used to propose a new label. The proposal is only accepted (written back) when the reassigned fragment pixels are 8-connected to an existing component of that same label — this preventsexpand_labelsfrom recreating a disconnected fragment.Labels in exclude are left untouched. This is used by
merge_cellsto preserve a merge target whose components are intentionally disconnected (e.g. after merging a fragmented nucleus).