Tool to make isocontours

Hello!

I like to make a tool to create isocontours in planar images, I need that for image processing. The way I want it to work is as follow:

  1. you select the tool
  2. having an image you select one pixel and with mouse down you adjust the isocontour level
  3. the tool shall look for the maximum value (MV) in the neighborhood of selected point, default level at start will be the minimum value between 50% MV and the ratio of current pixel value and MV, so current pixel is always included in the ROI.
  4. Moving up the mouse will increase isocontour level and moving down reduce that.
  5. When user agree just release mouse button and the new ROI shall be added to ROI manager.

The contour must be a unique poligon with no holes containing both the selected point and the MV point.

I wonder if there is some easy way to start with, then I will need some advices to develop the tool itself.

1 Like

I´ve found that this code is inside imagej web page, although it paints the isocontours and I want a ROI instead, but is a nice starting point.

1 Like

I have made a code to do this, however only works with 2 or more points, not 1. Why? Is there any difference between 1 and several points in a PointRoi??

the code is the following


    public static Overlay getObjects(ImagePlus imp, PointRoi p, double level) {
        ImageProcessor ip2 = imp.getProcessor().duplicate();
        ImageStatistics is2 = ip2.getStatistics();
        int xmin = (int) p.getContainedPoints()[0].getX();
        int ymin = (int) p.getContainedPoints()[0].getY();
        double value = ip2.getPixelValue(xmin, ymin);
        for (Point tp : p.getContainedPoints()) {
            double nvalue = ip2.getPixelValue((int) tp.getX(), (int) tp.getY());
            if (nvalue < value) {
                value = nvalue;
                xmin = (int) tp.getX();
                ymin = (int) tp.getY();
            }
        }
        ip2.setThreshold(Math.min(is2.max * level, ip2.getPixelValue(xmin, ymin)), is2.max, ImageProcessor.BLACK_AND_WHITE_LUT);
        ThresholdToSelection ts = new ThresholdToSelection();
        Roi roi = ts.convert(ip2);
        ShapeRoi Sroi = new ShapeRoi(roi);
        Roi[] listroi = Sroi.getRois();
        Overlay result = new Overlay();
        for (Roi r : listroi) {
            for (Point tp : p.getContainedPoints()) {
                if (r.contains((int) tp.getX(), (int) tp.getY())) {
                    result.add(r);
                }
            }
        }
        return result;
    }

For a single point in a PointRoi this is the code that do the job


    public static Roi getObject(ImagePlus imp, Point p, double level) {
        ImageProcessor ip2 = imp.getProcessor().duplicate();
        ImageStatistics is2 = ip2.getStatistics();
        ip2.setThreshold(Math.min(is2.max * level, ip2.getPixel((int) p.getX(), (int) p.getY())), is2.max, ImageProcessor.BLACK_AND_WHITE_LUT);
        ThresholdToSelection ts = new ThresholdToSelection();
        Roi roi = ts.convert(ip2);
        ShapeRoi Sroi = new ShapeRoi(roi);
        Roi[] listroi = Sroi.getRois();
        for (Roi r : listroi) {
            if (r.contains((int) p.getX(), (int) p.getY())) {
                roi = r;
            }
        }
        return roi;
    }

I wonder if any IJ main developer can include this code in a tool like the FreeHand selection, but instead of a Free hand you just need to handle the level value with the mouse position in down state.

If you like, you could try your hand at hacking the core ImageJ 1.x code, and submitting a patch to @Wayne. See http://imagej.net/Contributing#ImageJ1

I fear handling mouse events and continuous drawings in mouse down state is too much for my current knowledge level, but I think is not too complicated for an advanced developer. The main code is already here.

A little enhancement for code speed would be to eliminate the need to use statistics giving the maximum value like


    public static Roi getObject(ImagePlus imp, Point p, double level, double max) {
        ImageProcessor ip2 = imp.getProcessor().duplicate();
        ip2.setThreshold(Math.min(level * max, ip2.getPixelValue((int) p.getX(), (int) p.getY())), max, ImageProcessor.BLACK_AND_WHITE_LUT);
        ThresholdToSelection ts = new ThresholdToSelection();
        Roi roi = ts.convert(ip2);
        ShapeRoi Sroi = new ShapeRoi(roi);
        Roi[] listroi = Sroi.getRois();
        for (Roi r : listroi) {
            if (r.contains((int) p.getX(), (int) p.getY())) {
                roi = r;
            }
        }
        return roi;
    }

I made it!! Is cool to see how it actually works!!

The code is a variation of the versatile wand tool, thanks to @Wayne for his help. Installation follow the same rules as for the wand: copy this code in a file named Contour_Roi_Tool.java, create the .jar and place it in plugins/Tools. Thats it!

Here is an image of the tool working

1 Like

I created the site https://github.com/BishopWolf/Contour_Roi for contributing to this, right now it is actually mavenized, but it copies the jar file to jars instead of to plugins/Tools. Am I missing something?

What is “it”? mvn -Dimagej.app.directory=...?

@ctrueden
What is “it”? mvn -Dimagej.app.directory=…?

Precisely, I have defined that in maven, but when copy the jar to imagej it goes for jars folder instead of plugins/Tools. Thats my current problem.

OTOH, have you tried the Tool?? Do you have any suggestions??

The imagej-maven-plugin is only smart enough to copy stuff into jars/ and plugins/. It does this based on whether it detects the JAR contains ImageJ 1.x plugins. IIRC, it looks for a plugins.config inside the JAR.

Sorry, I don’t have time right now. I am at a hackathon this week. Then playing catch-up next week, then another hackathon for the next two weeks.