33import napari .viewer
44
55import numpy as np
6+ import nifty .tools as nt
67
78from qtpy .QtWidgets import QHBoxLayout , QVBoxLayout , QPushButton , QSpinBox , QLabel
89from skimage .measure import regionprops , label
@@ -34,9 +35,9 @@ def __init__(self):
3435 threshold_layout .addWidget (self .size_threshold_widget )
3536 layout .addLayout (threshold_layout )
3637
37- # Add a boolean field for processing binary masks .
38- self .is_mask = False
39- layout .addWidget (self ._add_boolean_param ("is_mask " , self .is_mask , title = "Binary Mask " ))
38+ # Add a boolean field for applying a label operation before size filtering .
39+ self .apply_label = True
40+ layout .addWidget (self ._add_boolean_param ("apply_label " , self .apply_label , title = "Remove Disconnected Pieces " ))
4041
4142 # Add an optional output layer name. If not given the segmentation will be over-written.
4243 self .output_layer_param , _ = self ._add_string_param ("output_layer" , "" , title = "Output Layer" , layout = layout )
@@ -48,19 +49,36 @@ def __init__(self):
4849 # Add the widgets to the layout.
4950 self .setLayout (layout )
5051
52+ def _filter_mask (self , segmentation , size_threshold ):
53+ segmentation = label (segmentation ).astype (segmentation .dtype )
54+ props = regionprops (segmentation )
55+ filter_ids = [prop .label for prop in props if prop .area < size_threshold ]
56+ segmentation [np .isin (segmentation , filter_ids )] = 0
57+ segmentation = (segmentation > 0 ).astype (segmentation .dtype )
58+ return segmentation
59+
60+ def _filter_segmentation (self , segmentation , size_threshold , apply_label ):
61+ dtype = segmentation .dtype
62+ if apply_label :
63+ original_segmentation = segmentation .copy ()
64+ segmentation = label (segmentation )
65+ props = regionprops (segmentation , original_segmentation )
66+ else :
67+ props = regionprops (segmentation )
68+ filter_ids = [prop .label for prop in props if prop .area < size_threshold ]
69+ segmentation [np .isin (segmentation , filter_ids )] = 0
70+ if apply_label :
71+ mapping = {prop .label : int (prop .max_intensity ) for prop in props if prop .label not in filter_ids }
72+ mapping [0 ] = 0
73+ segmentation = nt .takeDict (mapping , segmentation )
74+ return segmentation .astype (dtype )
75+
5176 def on_size_filter (self ):
5277 size_threshold = self .size_threshold_widget .value ()
5378 seg_layer = self ._get_layer_selector_layer (self .segmentation_selector_name )
5479 segmentation = seg_layer .data .copy ()
5580
56- if self .is_mask :
57- segmentation = label (segmentation ).astype (segmentation .dtype )
58-
59- props = regionprops (segmentation )
60- filter_ids = [prop .label for prop in props if prop .area < size_threshold ]
61- segmentation [np .isin (segmentation , filter_ids )] = 0
62- if self .is_mask :
63- segmentation = (segmentation > 0 ).astype (segmentation .dtype )
81+ segmentation = self ._filter_segmentation (segmentation , size_threshold , self .apply_label )
6482
6583 # Write or overwrite segmentation layer.
6684 layer_name = self .output_layer_param .text ()
0 commit comments