Equal GridCells on Image!


#1

I am new to ImageJ. I want to layout a 1cm^2 grid cell on 76x52 mm image. The grid in imageJ give grid not start from the corner of the image. It starts with half square. Any thoughts.

Thanks!


#2

You can change and compile the original plugin here:

https://imagej.nih.gov/ij/plugins/grid.html

Eventually this plugin is helpful where the grid starts in the top-left (0,0) coordinate:

https://imagej.nih.gov/ij/plugins/graphic-overlay.html

Here is a slightly modified version (fast hacked) of the Grid plugin (called Grid2_) with an option to start at the 0,0 coordinate:

Source:

    import ij.*;
    import ij.process.*;
    import ij.gui.*;
    import java.awt.*;
    import java.awt.geom.*;
    import java.util.*;
    import ij.plugin.*;
    import ij.measure.*;

    public class Grid2_ implements PlugIn, DialogListener {
        private static double crossSize = 0.1;
        private static String[] colors = {"Red","Green","Blue","Magenta","Cyan","Yellow","Orange","Black","White"};
        private static String color = "Cyan";
        private final static int LINES=0, HLINES=1, CROSSES=2, POINTS=3, NONE=4;
        private static String[] types = {"Lines","Horizontal Lines", "Crosses", "Points", "None"};
        private static String type = types[LINES];
        private static double areaPerPoint;
        private static boolean randomOffset, startAtTopLeft;
        private static boolean bold;    
        private Random random = new Random(System.currentTimeMillis());
        private ImagePlus imp;
        private double tileWidth, tileHeight;
        private int xstart, ystart;
        private int linesV, linesH;
        private double pixelWidth=1.0, pixelHeight=1.0;
        private String units = "pixels";

        public void run(String arg) {
            imp = IJ.getImage();
            showDialog();
        }
            
        void drawPoints() {
            int one = 1;
            int two = 2;
            GeneralPath path = new GeneralPath();
            for(int h=0; h<linesV; h++) {
                for(int v=0; v<linesH; v++) {
                    float x = (float)(xstart+h*tileWidth);
                    float y = (float)(ystart+v*tileHeight);
                    path.moveTo(x-two, y-one); path.lineTo(x-two, y+one);
                    path.moveTo(x+two, y-one); path.lineTo(x+two, y+one);
                    path.moveTo(x-one, y-two); path.lineTo(x+one, y-two);
                    path.moveTo(x-one, y+two); path.lineTo(x+one, y+two);
                }
            }
            showGrid(path);
        }

        void drawCrosses() {
            GeneralPath path = new GeneralPath();
            float arm  = (int)Math.round(crossSize*tileWidth);
            if (arm<3) arm=3;
            for(int h=0; h<linesV; h++) {
                for(int v=0; v<linesH; v++) {
                    float x = (float)(xstart+h*tileWidth);
                    float y = (float)(ystart+v*tileHeight);
                    path.moveTo(x-arm, y);
                    path.lineTo(x+arm, y);
                    path.moveTo(x, y-arm);
                    path.lineTo(x, y+arm);
                }
            }
            showGrid(path);
        }

        void showGrid(Shape shape) {
            if (shape==null)
                imp.setOverlay(null);
            else {
                Roi roi = new ShapeRoi(shape);
                roi.setStrokeColor(getColor());
                if (bold && linesV*linesH<5000) {
                    ImageCanvas ic = imp.getCanvas();
                    double mag = ic!=null?ic.getMagnification():1.0;
                    double width = 2.0;
                    if (mag<1.0)
                        width = width/mag;
                    roi.setStrokeWidth(width);
                }
                imp.setOverlay(new Overlay(roi));
            }
        }

        void drawLines() {
            GeneralPath path = new GeneralPath();
            int width = imp.getWidth();
            int height = imp.getHeight();
            for(int i=0; i<linesV; i++) {
                float xoff = (float)(xstart+i*tileWidth);
                path.moveTo(xoff,0f);
                path.lineTo(xoff, height);
            }
            for(int i=0; i<linesH; i++) {
                float yoff = (float)(ystart+i*tileHeight);
                path.moveTo(0f, yoff);
                path.lineTo(width, yoff);
            }
            showGrid(path);
        }

        void drawHorizontalLines() {
            GeneralPath path = new GeneralPath();
            int width = imp.getWidth();
            int height = imp.getHeight();
            for(int i=0; i<linesH; i++) {
                float yoff = (float)(ystart+i*tileHeight);
                path.moveTo(0f, yoff);
                path.lineTo(width, yoff);
            }
            showGrid(path);
        }

        void showDialog() {
            int width = imp.getWidth();
            int height = imp.getHeight();
            Calibration cal = imp.getCalibration();
            int places;
            if (cal.scaled()) {
                pixelWidth = cal.pixelWidth;
                pixelHeight = cal.pixelHeight;
                units = cal.getUnits();
                places = 2;
            } else {
                pixelWidth = 1.0;
                pixelHeight = 1.0;
                units = "pixels";
                places = 0;
            }
            if (areaPerPoint==0.0)
                areaPerPoint = (width*cal.pixelWidth*height*cal.pixelHeight)/81.0; // default to 9x9 grid
            GenericDialog gd = new GenericDialog("Grid...");
            gd.addChoice("Grid type:", types, type);
            gd.addNumericField("Area per point:", areaPerPoint, places, 6, units+"^2");
            gd.addChoice("Color:", colors, color);
            gd.addCheckbox("Bold", bold);
            gd.addCheckbox("Random offset", randomOffset);
            gd.addCheckbox("Start at coordinate 0,0", startAtTopLeft);
            gd.addDialogListener(this);
            dialogItemChanged(gd, null);
            gd.showDialog();
            if (gd.wasCanceled()) 
                showGrid(null);
        }

        public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) {
            int width = imp.getWidth();
            int height = imp.getHeight();
            type = gd.getNextChoice();
            areaPerPoint = gd.getNextNumber();
            color = gd.getNextChoice();
            bold = gd.getNextBoolean();
            randomOffset = gd.getNextBoolean();
            startAtTopLeft = gd.getNextBoolean();
            double minArea= (width*height)/50000.0;
            if (type.equals(types[CROSSES])&&minArea<50.0)
                minArea = 50.0;
            else if (minArea<16)
                minArea = 16.0;
            if (areaPerPoint/(pixelWidth*pixelHeight)<minArea) {
                String err = "\"Area per Point\" too small";
                if (gd.wasOKed())
                    IJ.error("Grid", err);
                else
                    IJ.showStatus(err);
                return true;
            }
            double tileSize = Math.sqrt(areaPerPoint);
            tileWidth = tileSize/pixelWidth;
            tileHeight = tileSize/pixelHeight;
            if (randomOffset) {
                xstart = (int)(random.nextDouble()*tileWidth);
                ystart = (int)(random.nextDouble()*tileHeight);
            } 
            else if(startAtTopLeft){
                xstart = 0;
                ystart = 0;
            }
            
            else {
                xstart = (int)(tileWidth/2.0+0.5);
                ystart = (int)(tileHeight/2.0+0.5);
            }
            linesV = (int)((width-xstart)/tileWidth)+1; 
            linesH = (int)((height-ystart)/tileHeight)+1;
            if (gd.invalidNumber())
                return true;
            showGrid();
                return true;
        }

        private void showGrid() {
            if (type.equals(types[LINES]))
                drawLines();
            else if (type.equals(types[HLINES]))
                drawHorizontalLines();
            else if (type.equals(types[CROSSES]))
                drawCrosses();
            else  if (type.equals(types[POINTS]))
                drawPoints();
            else
                showGrid(null);
        }

        Color getColor() {
            Color c = Color.cyan;
            if (color.equals(colors[0])) c = Color.red;
            else if (color.equals(colors[1])) c = Color.green;
            else if (color.equals(colors[2])) c = Color.blue;
            else if (color.equals(colors[3])) c = Color.magenta;
            else if (color.equals(colors[4])) c = Color.cyan;
            else if (color.equals(colors[5])) c = Color.yellow;
            else if (color.equals(colors[6])) c = Color.orange;
            else if (color.equals(colors[7])) c = Color.black;
            else if (color.equals(colors[8])) c = Color.white;
            return c;
        }
    }

#3

Hi Bio7,
Thanks for modifying the code. I tried to use the code, however it gives me this message" undefined variable in line 1". Do I need to specify the image file?.

Thanks!


#4

It is a Java plugin like the original.

So you have to save this file as Grid2_.java and compile it, see:


http://imagejdocu.tudor.lu/doku.php?id=howto:plugins:how_to_install_a_plugin


#5

Hi Bio7,

I have some experience with ImageJ, but not experience with java. I included the grid plugin with one of my macros, but I want the grid to start at an specific selected point. In imageJ I was able to set the selected point as my 0,0 coordinate, however, the grid2 java app, always set it on the top left. I checked the code and I asume that I need to obtain the values from the image, and then set the as the x and y coordinates. How can I do it? Any help will be really appreciated.

Thanks


#6

It just added an option to start the grid at the 0,0 coordinates in java.

else if(startAtTopLeft){
                xstart = 0;
                ystart = 0;
            }

You could change xstart, ystart with you selected coordinates (for instance set them from your macro code).