1010import ij .IJ ;
1111import ij .ImagePlus ;
1212import ij .ImageStack ;
13+ import ij .gui .GenericDialog ;
1314import ij .plugin .PlugIn ;
1415import ij .process .ImageProcessor ;
1516import inra .ijpb .label .LabelImages ;
2324 */
2425public class FillLabelHolesPlugin implements PlugIn
2526{
27+ // Widget labels and corresponding values of output type option
28+ private final static String [] resultBitDepthLabels = {"8 bits" , "16 bits" , "float" };
29+ private final static int [] resultBitDepthList = {8 , 16 , 32 };
30+
2631 /**
2732 * The shifts to identify the 2D neighbors of a pixel, using the 4-connectivity.
2833 */
@@ -42,24 +47,43 @@ public void run(String arg)
4247 // retrieve current image
4348 ImagePlus imagePlus = IJ .getImage ();
4449
50+ boolean isPlanar = imagePlus .getStackSize () == 1 ;
51+
52+ // Display dialog options
53+ GenericDialog gd = new GenericDialog ("Fill Label Holes" );
54+ String [] connLabels = isPlanar ? Connectivity2D .getAllLabels () : Connectivity3D .getAllLabels ();
55+ gd .addChoice ("Background Connectivity" , connLabels , connLabels [0 ]);
56+ gd .addChoice ("Labeling BitDepth" , resultBitDepthLabels , resultBitDepthLabels [1 ]);
57+
58+ // wait for user answer
59+ gd .showDialog ();
60+ if (gd .wasCanceled ())
61+ return ;
62+
63+ // parses dialog options
64+ String str = gd .getNextChoice ();
65+ int bitDepth = resultBitDepthList [gd .getNextChoiceIndex ()];
66+ int conn = isPlanar ? Connectivity2D .fromLabel (str ).getValue ()
67+ : Connectivity3D .fromLabel (str ).getValue ();
68+
4569 // dispatch processing according to image dimensionality
4670 if (imagePlus .getStackSize () == 1 )
4771 {
48- process2d (imagePlus .getProcessor ());
72+ process2d (imagePlus .getProcessor (), conn , bitDepth );
4973 }
5074 else
5175 {
52- process3d (imagePlus .getStack ());
76+ process3d (imagePlus .getStack (), conn , bitDepth );
5377 }
5478
5579 // refresh display
5680 imagePlus .updateAndDraw ();
5781 }
5882
59- private void process2d (ImageProcessor labelImage )
83+ private void process2d (ImageProcessor labelImage , int conn , int bitDepth )
6084 {
6185 // identified regions of the background
62- ImageProcessor bgLabelMap = LabelImages .regionComponentsLabeling (labelImage , 0 , 4 , 16 );
86+ ImageProcessor bgLabelMap = LabelImages .regionComponentsLabeling (labelImage , 0 , conn , bitDepth );
6387
6488 // for each background region, find labels of regions within original image
6589 Map <Integer , BackgroundRegion2D > map = mapNeighbors (bgLabelMap , labelImage );
@@ -72,7 +96,7 @@ private void process2d(ImageProcessor labelImage)
7296 if (region .values .size () == 1 )
7397 {
7498 int value = region .values .get (0 );
75- FloodFill .floodFill (bgLabelMap , region .x0 , region .y0 , labelImage , value , 4 );
99+ FloodFill .floodFill (bgLabelMap , region .x0 , region .y0 , labelImage , value , conn );
76100 }
77101 }
78102 }
@@ -139,10 +163,10 @@ private Map<Integer, BackgroundRegion2D> mapNeighbors(
139163 return map ;
140164 }
141165
142- private void process3d (ImageStack labelImage )
166+ private void process3d (ImageStack labelImage , int conn , int bitDepth )
143167 {
144168 // identified regions of the background
145- ImageStack bgLabelMap = LabelImages .regionComponentsLabeling (labelImage , 0 , 6 , 16 );
169+ ImageStack bgLabelMap = LabelImages .regionComponentsLabeling (labelImage , 0 , conn , bitDepth );
146170
147171 // for each background region, find labels of regions within original image
148172 Map <Integer , BackgroundRegion3D > map = mapNeighbors (bgLabelMap , labelImage );
@@ -156,7 +180,7 @@ private void process3d(ImageStack labelImage)
156180 if (region .values .size () == 1 )
157181 {
158182 int value = region .values .get (0 );
159- FloodFill3D .floodFill (bgLabelMap , region .x0 , region .y0 , region .z0 , labelImage , value , 6 );
183+ FloodFill3D .floodFill (bgLabelMap , region .x0 , region .y0 , region .z0 , labelImage , value , conn );
160184 }
161185 }
162186 }
0 commit comments