|
1 | 1 | import time |
| 2 | +import warnings |
2 | 3 | from typing import Dict, List, Optional, Tuple, Union |
3 | 4 |
|
4 | 5 | import elf.parallel as parallel |
|
8 | 9 |
|
9 | 10 | from synapse_net.inference.util import apply_size_filter, get_prediction, _Scaler |
10 | 11 | from synapse_net.inference.postprocessing.vesicles import filter_border_objects, filter_border_vesicles |
| 12 | +from skimage.segmentation import relabel_sequential |
11 | 13 |
|
12 | 14 |
|
13 | 15 | def distance_based_vesicle_segmentation( |
@@ -148,6 +150,10 @@ def segment_vesicles( |
148 | 150 | return_predictions: Whether to return the predictions (foreground, boundaries) alongside the segmentation. |
149 | 151 | scale: The scale factor to use for rescaling the input volume before prediction. |
150 | 152 | exclude_boundary: Whether to exclude vesicles that touch the upper / lower border in z. |
| 153 | + exclude_boundary_vesicles: Whether to exlude vesicles on the boundary that have less than the full diameter |
| 154 | + inside of the volume. This is an alternative to post-processing with `exclude_boundary` that filters |
| 155 | + out less vesicles at the boundary and is better suited for volumes with small context in z. |
| 156 | + If `exclude_boundary` is also set to True, then this option will have no effect. |
151 | 157 | mask: An optional mask that is used to restrict the segmentation. |
152 | 158 |
|
153 | 159 | Returns: |
@@ -181,26 +187,23 @@ def segment_vesicles( |
181 | 187 | foreground, boundaries, verbose=verbose, min_size=min_size, **kwargs |
182 | 188 | ) |
183 | 189 |
|
184 | | - if exclude_boundary: |
| 190 | + if exclude_boundary and exclude_boundary_vesicles: |
| 191 | + warnings.warn( |
| 192 | + "You have set both 'exclude_boundary' and 'exclude_boundary_vesicles' to True." |
| 193 | + "The 'exclude_boundary_vesicles' option will have no effect." |
| 194 | + ) |
185 | 195 | seg = filter_border_objects(seg) |
186 | | - if exclude_boundary_vesicles: |
187 | | - seg_ids = filter_border_vesicles(seg) |
188 | | - # Step 1: Zero out everything not in seg_ids |
189 | | - seg[~np.isin(seg, seg_ids)] = 0 |
190 | | - |
191 | | - # Step 2: Relabel remaining IDs to be consecutive starting from 1 |
192 | | - unique_ids = np.unique(seg) |
193 | | - unique_ids = unique_ids[unique_ids != 0] # Exclude background (0) |
194 | 196 |
|
195 | | - label_map = {old_label: new_label for new_label, old_label in enumerate(unique_ids, start=1)} |
| 197 | + elif exclude_boundary: |
| 198 | + seg = filter_border_objects(seg) |
196 | 199 |
|
197 | | - # Apply relabeling using a temp array (to avoid large ints in-place) |
198 | | - new_seg = np.zeros_like(seg, dtype=np.int32) |
199 | | - for old_label, new_label in label_map.items(): |
200 | | - new_seg[seg == old_label] = new_label |
| 200 | + elif exclude_boundary_vesicles: |
| 201 | + # Filter the vesicles that are at the z-border with less than their full diameter. |
| 202 | + seg_ids = filter_border_vesicles(seg) |
201 | 203 |
|
202 | | - # Final step: replace original seg with relabelled and casted version |
203 | | - seg = new_seg |
| 204 | + # Remove everything not in seg ids and relable the remaining IDs consecutively. |
| 205 | + seg[~np.isin(seg, seg_ids)] = 0 |
| 206 | + seg = relabel_sequential(seg)[0] |
204 | 207 |
|
205 | 208 | seg = scaler.rescale_output(seg, is_segmentation=True) |
206 | 209 |
|
|
0 commit comments