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