MorphoLibJ icon indicating copy to clipboard operation
MorphoLibJ copied to clipboard

Using Distance Transform Watershed without a GUI / UI

Open satorstefan opened this issue 1 year ago • 6 comments

Hello David,

I would like to use MorphoLibJ without any UI. For the moment I am focused on DistanceTransformWatershed().

Currently it seems to me the code assumes a UI is present.

Could you add a constructor to DistanceTransformWatershed() so I can pass all mandatory arguments? Or using some sort of builder pattern for DistanceTransformWatershed() would also be nice.

What I tried, but it did not work because of java.awt.HeadlessException: null:

webcam.addValueChangeListener(e -> {
            value = e.getValue();

            String[] split = value.split(",");

            data = Base64.getDecoder().decode(split[1]);

            BufferedImage img = null;
            try {
                img = ImageIO.read(new ByteArrayInputStream(data));
            } catch (IOException ex) {

            }

            ImagePlus imp = new ImagePlus("test", img);

            var watershed = new DistanceTransformWatershed();
            watershed.setup("", imp);

            ImageProcessor processor =  imp.getProcessor();
            processor.autoThreshold();

            //this is false
            BinaryImages.isBinaryImage(imp);

            GenericDialog gd = new GenericDialog("Distance Transform Watershed");
            gd.setInsets(0, 0, 0);
            gd.addMessage("Distance map options:", new Font("SansSerif", 1, 12));
            gd.addChoice("Distances", ChamferWeights.getAllLabels(), "Chessboard (1,1)");
            String[] outputTypes = new String[]{"32 bits", "16 bits"};

            boolean floatProcessing = true;
            gd.addChoice("Output Type", outputTypes, outputTypes[floatProcessing ? 0 : 1]);

            gd.setInsets(0, 0, 0);
            gd.addCheckbox("Normalize weights", false);
            gd.setInsets(20, 0, 0);
            gd.addMessage("Watershed options:", new Font("SansSerif", 1, 12));
            gd.addNumericField("Dynamic", (double)2, 2);


            String[] connectivity = {"4", "8"};
            gd.addChoice("Connectivity", connectivity, "4");
            gd.setInsets(20, 0, 0);

            watershed.dialogItemChanged(gd, null);
            watershed.run(processor);


            FileSaver fileSaver = new FileSaver(imp);

            fileSaver.saveAsBmp("...");
        });

satorstefan avatar Nov 06 '23 21:11 satorstefan

Thanks, @satorstefan for bringing this to our attention! While we create a public method for that and publish a new release, you may want to write in your code the few lines equivalent to the process in that plugin:

https://github.com/ijpb/MorphoLibJ/blob/master/src/main/java/inra/ijpb/plugins/DistanceTransformWatershed.java#L263-L268

iarganda avatar Nov 07 '23 06:11 iarganda

Hello Ignarcio,

For now it seems it also works to set: System.setProperty("java.awt.headless", "false");

But I struggle to get a binary image out of my greyscale image.

So far I tried:

 ImagePlus imp = new ImagePlus("test", img);

        ImageProcessor processor =  imp.getProcessor();
        processor.autoThreshold();

        ImagePlus binaryPlus = new ImagePlus("binary", processor);

        if(!BinaryImages.isBinaryImage(binaryPlus)){
            System.out.println("Huston we got a problem!");
        }

and I also see that ByteProcessor.threshold(int level1, int level2) gets called.

satorstefan avatar Nov 07 '23 08:11 satorstefan

To binarize an image, you can use our own method from the Threshold class:

https://github.com/ijpb/MorphoLibJ/blob/master/src/main/java/inra/ijpb/segment/Threshold.java#L57

iarganda avatar Nov 07 '23 09:11 iarganda

Hello Ignarcio,

I will try your approach.

What I did try so for seems to "work", but the image result.png is just the unchanged binary that I put in.

            watershed.dialogItemChanged(gd, null);
            watershed.run(processor);
            
            BufferedImage bufferedImage = processor.getBufferedImage();
            print("result.png", bufferedImage)
```;

satorstefan avatar Nov 07 '23 13:11 satorstefan

@iarganda Hello Ignarcio,

with your hint I could implement the algorithm.

I have one last question. Is there a easy way to give each object its own color like shown in the picture on the right here: https://imagej.net/plugins/distance-transform-watershed?

Best regards Stefan

satorstefan avatar Nov 08 '23 20:11 satorstefan

Hi Stefan, maybe late for reply, but you can assign colors to regions in a label map when performing the connected component analysis. Either via the plugin, or by using the computation classes.

best, David

dlegland avatar Jan 25 '24 13:01 dlegland