Issue with ParticleAnalyzer output

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Issue with ParticleAnalyzer output

Ludgate, David
Hi,
I'm using the ParticleAnalyzer class to find particles and I need to
record the irregular ROIs that define each particle. I did this simply
by overriding the drawParticle method to record each ROI as it drew
them. So now my program displays an image of all the filled particles
and records the ROIs, which I use elsewhere.
My problem is that I run though this procedure many times and if I leave
all those images open I run out of memory really quickly. So I've been
trying to look for a way to close the images that the ParticleAnalyzer
makes automatically. I'm working directly with classes so i'd rather not
have to go to ImageJ's window manager and try to find each image, and
instead get the ImagePlus object used directly from the ParticleAnalyzer
class.
Unfortunately, as far as I can see, this is the line that creates that
window:
new ImagePlus
<file:///E:/documents/apps/imagej/imagej%20source/html-source/ij/ImagePl
us.java.html> (prefix+title, outlines).show();
The ParticleAnalyzer thus has no way of keeping track of that window
once it is created.
Furthermore, I cannot override the method (at least, my IDE tells me I
can't) since "it is private to a different package".
 
Does anyone know of a way I can get around this? At the moment I do not
directly use the ImageJ program and deal with the classes directly,
thus, ImageJ doesn't recognise the windows I open as existing.
 
TIA, dave
Reply | Threaded
Open this post in threaded view
|

Re: Issue with ParticleAnalyzer output

audrey karperien
Hi. If you want to wade through some code, FracLac does just what you describe (see attached).
 
Audrey

"Ludgate, David" <[hidden email]> wrote:
Hi,
I'm using the ParticleAnalyzer class to find particles and I need to
record the irregular ROIs that define each particle. I did this simply
by overriding the drawParticle method to record each ROI as it drew
them. So now my program displays an image of all the filled particles
and records the ROIs, which I use elsewhere.
My problem is that I run though this procedure many times and if I leave
all those images open I run out of memory really quickly. So I've been
trying to look for a way to close the images that the ParticleAnalyzer
makes automatically. I'm working directly with classes so i'd rather not
have to go to ImageJ's window manager and try to find each image, and
instead get the ImagePlus object used directly from the ParticleAnalyzer
class.
Unfortunately, as far as I can see, this is the line that creates that
window:
new ImagePlus
us.java.html> (prefix+title, outlines).show();
The ParticleAnalyzer thus has no way of keeping track of that window
once it is created.
Furthermore, I cannot override the method (at least, my IDE tells me I
can't) since "it is private to a different package".

Does anyone know of a way I can get around this? At the moment I do not
directly use the ImageJ program and deal with the classes directly,
thus, ImageJ doesn't recognise the windows I open as existing.

TIA, dave
Reply | Threaded
Open this post in threaded view
|

Re: Issue with ParticleAnalyzer output

audrey karperien
In reply to this post by Ludgate, David
Hello.
 
Below is some code that you can cut and paste and compile as a new plugin that analyzes an image with the particle analyzer then writes the coordinates for the rois and optionally colours over them in a new image.  Its ripped out of another plugin so is rather bulky and hacky as is but I think it is relevant to your question.
 
Audrey
 
import ij.*;
import ij.IJ;
import ij.ImagePlus;
import ij.WindowManager;
import ij.gui.*;
import ij.gui.GenericDialog;
import ij.gui.ImageWindow;
import ij.gui.PolygonRoi;
import ij.gui.Roi;
import ij.gui.Toolbar;
import ij.gui.Wand;
import ij.measure.ResultsTable;
import ij.plugin.*;
import ij.plugin.filter.Analyzer;
import ij.plugin.filter.ParticleAnalyzer;
import ij.process.ImageProcessor;
import ij.process.ImageStatistics;
import java.awt.*;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.*;
/*
 * UsePARois.java
 *
 * Created on August 3, 2005, 4:34 PM
 *
* Code ripped out of FracLac and quickly hacked into a demo of pa rois.
 *It analyzes an image and writes out the x,y and width and height of the rois,
 *and optionally draws them back on the original image.  It is just a quick hack that
 *will likely be prunable to something elegant.
 */
/**
 *
 * @author Audrey_2 Charles Sturt University, Neuroscience
 */
public class Use_PA_Rois implements PlugIn{
   
    /** Creates a new instance of UsePARois */
    public Use_PA_Rois() {
    }
    public void run(String  args){
        MakeImage=IJ.showMessageWithCancel("Make Image?",
                "Choose OK to draw the rois or cancel to make no new image");
        Go();}
    int minparticle=30, maxparticle=99999;
  boolean MakeImage=false;
 
        public void Go(){
           
            String imgtitle=null;
            String x="", y="";
            ImageWindow wm = WindowManager.getCurrentWindow();
            if(wm==null) { IJ.noImage(); return;}
            else
            {                
               
                ImagePlus workingcopy=wm.getImagePlus();
                if(workingcopy==null) { IJ.noImage(); return;}
                else
                {                    
                    workingcopy.setSlice(1);                                  
                                   
                   {int lastslice=workingcopy.getStackSize();
                     for (int thisslice = 1; thisslice <= lastslice; ++thisslice)
                    {//for each slice in the stack
                           workingcopy.setSlice(thisslice);                        
                           workingcopy.setRoi(0, 0, workingcopy.getWidth(), workingcopy.getHeight());
                           if(!ScanParticles(workingcopy,   thisslice, lastslice))return;                                                            
                         
                     }              
                   }}}}
 
   
   
    /**
     * Copies the current ROI to the clipboard. The entire
     *         image is copied if there is no ROI.
     * (Aug 2, 2005)@param cut boolean always false FIXME
     * @param imp ImagePlus to analyze
     * @param title String for image's title
     * @return ImagePlus copy of the roi selected
     */
    public ImagePlus copy(boolean cut, ImagePlus imp, String title
            ) {
        Roi roi = imp.getRoi();
       
       
        String msg = (cut)?"Cut":"Copy";
        IJ.showStatus(msg+ "ing...");
        ImageProcessor ip = imp.getProcessor();
        ImageProcessor ip2 = ip.crop();
        ImagePlus clipboard = new ImagePlus(title, ip2);
        if (roi!=null && roi.getType()!=Roi.RECTANGLE)
            clipboard.setRoi((Roi)roi.clone());
//        if (cut) {
//            ip.snapshot();
//            ip.setColor(F.V.background==F.V.WHITE?Color.white:Color.black);
//            ip.fill();
//            if (roi!=null && roi.getType()!=Roi.RECTANGLE)
//                ip.reset(imp.getMask());
//            imp.setColor( F.V.foreground==F.V.WHITE?Color.white:Color.black);
//            Undo.setup(Undo.FILTER, imp);
//            imp.updateAndDraw();
//        }
        int bytesPerPixel = 1;
        switch (clipboard.getType()) {
            case ImagePlus.GRAY16: bytesPerPixel = 2; break;
            case ImagePlus.GRAY32: case ImagePlus.COLOR_RGB: bytesPerPixel = 4;
        }
        IJ.showStatus(msg + ": "
                + (clipboard.getWidth()*
                clipboard.getHeight()*bytesPerPixel)/1024 + "k");
       
        return paste(clipboard, title);
    }
   
   
    /**
     * Pastes the passed image. I am trying to paste an roi without
     * (Aug 2, 2005)collecting the surrounding rectangle. FIXME
     * @return ImagePlus pasted
     * @param s needs fixing
     * @param clipboard ImagePlus copied
     */
    public ImagePlus paste(ImagePlus clipboard, String s) {
       
        ImagePlus imp = new ImagePlus("pasted"+s, clipboard.getImage());
        imp.setRoi(0, 0, imp.getWidth(), imp.getHeight());
        imp.setColor(Color.white);//F.V.background==F.V.WHITE?Color.white:Color.black);
        imp.getProcessor().fill();
        if (clipboard==null)
            return imp;
        int cType = clipboard.getType();
        int iType = imp.getType();
       
        boolean sameType = false;
        if ((cType==ImagePlus.GRAY8|cType==ImagePlus.COLOR_256)&&
                (iType==ImagePlus.GRAY8|iType==ImagePlus.COLOR_256)) sameType = true;
        else if ((cType==ImagePlus.COLOR_RGB|cType==ImagePlus.GRAY8|cType
                ==ImagePlus.COLOR_256)&&iType==ImagePlus.COLOR_RGB) sameType = true;
        else if (cType==ImagePlus.GRAY16&&iType==ImagePlus.GRAY16)
            sameType = true;
        else if (cType==ImagePlus.GRAY32&&iType==ImagePlus.GRAY32)
            sameType = true;
        if (!sameType) {
            IJ.error("Images must be the same type to paste.");
            return imp;
        }
        int w = clipboard.getWidth();
        int h = clipboard.getHeight();
        if (w>imp.getWidth() || h>imp.getHeight()) {
            IJ.error("Image is too large to paste.");
            return  imp;
        }
        Roi roi = imp.getRoi();
        Rectangle r = null;
        if (roi!=null) r = roi.getBounds();
       
        if (true)
        {
            //non-interactive paste
            int pasteMode = Roi.getCurrentPasteMode();
            boolean nonRect = roi.getType()!=Roi.RECTANGLE;
            ImageProcessor ip = imp.getProcessor();
            if (nonRect) ip.snapshot();
            r = roi.getBounds();
           
            ip.copyBits(clipboard.getProcessor(), r.x, r.y, pasteMode);
            if (nonRect)
                ip.reset(imp.getMask());
            imp.updateAndDraw();
            imp.killRoi();
        } else {}
       
        return imp;
    }
   
    /**
     * Gets the rois for all particles in a passed ImagePlus,
     * then calls a method to scan them, returning nothing.
     * Invokes the ImageJ ParticleAnalyzer to segment
     * the image, then passes the image and the ResultsTable
     * containing roi coordinates to the
     * {@link #ScanTheProcessorFromEachParticlesRoi scanning method} to
     * scan each particle. The data from the scans are
     * accessed through the
     * ImageJ Results window eventually;
     * refer to the scanning method for the next
     * step.
     * @param thisslice int for the current slice or 1 if this is not a stack
     * @param lastslice int for the number of slices in this stack or 1 if this is not a stack
     * @param img ImagePlus to scan
     * @return boolean true if not cancelled; false if the call to the{@link #setupPA particle anlayzer}
     * set up is cancelled
     */
    public boolean ScanParticles(ImagePlus img,  int thisslice, int lastslice) {
        boolean quit=false;
        boolean goOn=true;
        //store information
        String title = img.getTitle();
        ImageProcessor ip = img.getProcessor();
        Roi roi = img.getRoi();
        if(roi==null) {
            img.setRoi(0,0, img.getWidth(), img.getHeight());
            roi=img.getRoi();
        }//get user's options for the particle analyzer
        goOn=true;
        if(thisslice==1){
             goOn=setupPA();}//quit if cancelled here
        if (!goOn) return false;
        else//if not cancelled, go on
        {
            ImageStatistics stats = img.getStatistics();
            if ((stats.histogram[0]+stats.histogram[255])!=stats.pixelCount) {
                IJ.showMessage("Binary (thresholded) image required.");
                quit=true;
            }//quit if the image is not binary
            else if (!quit)//or else go on
            {
//                if (F.V.background==F.V.BLACK) {
//                    img.killRoi();
//                    invert(ip);
//                    img.updateAndRepaintWindow();
//                }
               
                //get the rois
                img.setRoi(roi);
                Analyzer ana=new Analyzer();
                int measurements = Analyzer.getMeasurements();
                ResultsTable rt = ana.getResultsTable();
                int options=
                        (ParticleAnalyzer.EXCLUDE_EDGE_PARTICLES|
                        ParticleAnalyzer.RECORD_STARTS
                        |ParticleAnalyzer.SHOW_NONE);
                measurements =
                        (ana.PERIMETER|ana.AREA);
                ParticleAnalyzer pa=new ParticleAnalyzer
                        (options, measurements, rt, minparticle, maxparticle);
                Analyzer.resetCounter();
                img.setRoi(roi);
                pa.analyze(img);
                ip.setRoi(roi);
                ScanTheProcessorFromEachParticlesRoi(rt, img, thisslice, lastslice, title);
               
            }
        }return true;
    }
   
     public void ScanTheProcessorFromEachParticlesRoi
            (ResultsTable rt, ImagePlus img, int thisslice, int lastslice, String title) {
        ImageWindow win = img.getWindow();
        int nResults = rt.getCounter();
        ImageProcessor ip = img.getProcessor();
        Image StoredCopyOfOriginal = ip.createImage();
        float[] wandx=new float[nResults];
        float []wandy=new float [nResults];
       
        Roi [] RoisFromParticleAnalyzer=new PolygonRoi [nResults];
        float [][] ParticleRectangleXY=new float[2][nResults];
        for (int i=0; i<nResults; i++) {
            wandx[i] =(float) rt.getValue("XStart", i);
            wandy[i] =(float) rt.getValue("YStart", i);
            Wand w = new Wand(img.getProcessor());
           
            w.autoOutline(
                    (int)wandx[i],(int)wandy[i]);
            RoisFromParticleAnalyzer[i]= new PolygonRoi(w.xpoints, w.ypoints,
                    w.npoints, Roi.TRACED_ROI);
           
            {ParticleRectangleXY[0][i]=
                     (int)RoisFromParticleAnalyzer[i].getBounds().getBounds2D().getX();
            ParticleRectangleXY[1][i]=
                    (int)RoisFromParticleAnalyzer[i].getBounds().getBounds2D().getY();}
           
        }
       
        for (int i=0; i<nResults; i++)
        {
            WindowManager.setCurrentWindow(win);//img=win.getImagePlus();
            img.setRoi(RoisFromParticleAnalyzer[i]);            
            ImagePlus copied=copy(false, img, title);
            copied.killRoi();  
           
            IJ.write(ParticleRectangleXY[0][i]+","+
                    ParticleRectangleXY[1][i]+","+
                    (int)RoisFromParticleAnalyzer[i].getBounds().getBounds2D().getWidth()+","+
                    (int)RoisFromParticleAnalyzer[i].getBounds().getBounds2D().getHeight());
        }    
       
        if (MakeImage)
        {
         img.setSlice(thisslice);
           img.updateAndRepaintWindow();
           BufferedImage bi
                    = new BufferedImage(img.getWidth(),
                    img.getHeight(), BufferedImage.TYPE_INT_ARGB);
           Graphics2D g = (Graphics2D)bi.getGraphics();
           g.drawImage(StoredCopyOfOriginal, 0, 0, null);
           
            ColourRois
                    (ip,
                    1,//TYPE,
                    g,
                    RoisFromParticleAnalyzer, 190, 5,
                    0
                    );
           
            ImagePlus imgg = new ImagePlus("new"+title, bi);
           
            if(thisslice==1)
            {
                ColouredRoisStack = new ImageStack(img.getWidth(), img.getHeight());
                ColouredRoisStack.addSlice(title, imgg.getProcessor());                
            }
            else ColouredRoisStack.addSlice(title, imgg.getProcessor());
            if(thisslice==lastslice)
            {
                StackWindow iww = new StackWindow(new ImagePlus(img.getTitle()
                        + thisslice, ColouredRoisStack));
                iww.setVisible(true);
            }
        }
    }
   
     ImageStack ColouredRoisStack =null;
       /**Sets up the ij.plugin.filter.ParticleAnalyzer using
     * a ij.gui.GenericDialog to get values for the minimum and
     * maximum particle size to find, and the background and
     * foreground arrangement (i.e., which is white and which is black).
     * Changes these variables in the {@link FLAnalyzer.FLVars variable class}.
     * @return boolean false if cancelled or else true
     */
    public boolean setupPA() {
        GenericDialog gd
                = new GenericDialog("Particle Options", IJ.getInstance());
        String [] C =
        {"Black", "White"};
        String ch = C[1];
     
        gd.addChoice("Background Colour", C, ch);
        gd.addNumericField("Minimum particle", minparticle, 0);
        gd.addNumericField("Maximum particle", maxparticle, 0);
        gd.showDialog();
        if (gd.wasCanceled()) {
            return false;} else {
            Color bg=Color.white;
            int t=gd.getNextChoiceIndex();
            if (t==0)bg=Color.black;
            Toolbar.setBackgroundColor(bg);
            minparticle=(int)gd.getNextNumber();
            maxparticle=(int)gd.getNextNumber();
            }
        return true;
    }
   
    public static void ColourRois (ImageProcessor ip,
    int TYPE,    
    Graphics2D g2,
    Roi [] rois,
    //float[] colours,
    //int ColourCode,
    float LocalAlpha,
    int comp,
    int foreground
    //boolean makescaleimage,
    //float [] DFS
   )
    {        
       
        Color gcolour= new Color (210, 240, 240);
        Color basecolour= new Color (210, 240, 240);
        for (int i = 0; i <rois.length; i++)
        {
           
            g2.setColor (gcolour);
            AlphaComposite acc
            = AlphaComposite.getInstance (AlphaComposite.SRC_OVER,  newAlpha(LocalAlpha,
            1.5f));
            g2.setComposite (acc);
            //colour the roi using the appropriate rule
           
            {          
             g2.fillPolygon (rois[i].getPolygon ());
            }
           
            //else if (TYPE==DRAW_IRREGULAR_ROI_NO_STRING)
            {          
             g2.drawPolygon (rois[i].getPolygon ());
            }
         
            ReplaceForegroundPixelsInIrregularRoi(rois[i], g2, ip, foreground);
           
           
                   
        }
       
       
               
    }
   
    /**
      * Colours only the pixels that are the foreground
      * colour and in the passed roi on the passed image.
      *
      * @param  roi Roi to colour
      * @param  g2 Graphics2D on which to colour the roi
      * @param  ip ImageProcessor to colour
      * @param  foreground int for the foreground colour
      */    
    public static void ReplaceForegroundPixelsInIrregularRoi(
    Roi roi,
    Graphics2D g2,
    ImageProcessor ip,
    int foreground)
    {        
                int startx = (int)(roi.getBoundingRect().getX());
                int starty = (int)(roi.getBoundingRect().getY());
               
                for (int xx = startx;
                    xx< startx+(int)(roi.getBoundingRect().getWidth());
                    xx++)
                {
                   
                    for (int yy = starty;
                        yy< starty+(int)(roi.getBoundingRect().getHeight());
                        yy++)
                    {
                        ip.setRoi (xx, yy, 1, 1);
                        //Roi smallroi = ip.getRoi ();
                        int [] histogram=ip.getHistogram ();
                        if (histogram[foreground]>0)
                        {                          
                           if(roi.contains(xx, yy))
                            g2.fillRect (xx, yy, 1, 1);
                        }                  
                }
                }
    }
   
    static float newAlpha(float LocalAlpha, float colour)
    {
        float floatLocalAlpha=(float)LocalAlpha/255.0f;
            floatLocalAlpha=floatLocalAlpha>1.0f?1.0f:floatLocalAlpha;
            floatLocalAlpha=floatLocalAlpha<0.0f?0.0f:floatLocalAlpha;
            return floatLocalAlpha;
    }
}

"Ludgate, David" <[hidden email]> wrote:
Hi,
I'm using the ParticleAnalyzer class to find particles and I need to
record the irregular ROIs that define each particle. I did this simply
by overriding the drawParticle method to record each ROI as it drew
them. So now my program displays an image of all the filled particles
and records the ROIs, which I use elsewhere.
My problem is that I run though this procedure many times and if I leave
all those images open I run out of memory really quickly. So I've been
trying to look for a way to close the images that the ParticleAnalyzer
makes automatically. I'm working directly with classes so i'd rather not
have to go to ImageJ's window manager and try to find each image, and
instead get the ImagePlus object used directly from the ParticleAnalyzer
class.
Unfortunately, as far as I can see, this is the line that creates that
window:
new ImagePlus
us.java.html> (prefix+title, outlines).show();
The ParticleAnalyzer thus has no way of keeping track of that window
once it is created.
Furthermore, I cannot override the method (at least, my IDE tells me I
can't) since "it is private to a different package".

Does anyone know of a way I can get around this? At the moment I do not
directly use the ImageJ program and deal with the classes directly,
thus, ImageJ doesn't recognise the windows I open as existing.

TIA, dave
Reply | Threaded
Open this post in threaded view
|

Re: Issue with ParticleAnalyzer output

Ludgate, David
In reply to this post by Ludgate, David
Hi,
After your first email pointing out FracLac, I duplicated what seemed
the relevent code, and it seems to work - most of the time. One of my
processing steps is to go through the ROIs and dialate them (by taking
the mask, then dilating, then gettign the ROI for that mask). However,
after 713 successful dilations, one invariably causes an
ArrayIndexOutOfBoundsException in ByteProcessor (line 446). My
inclination is to put in an if statement to simply ignore this particle
- but I can't find any obvious difference between it and the rest.

Have you encountered similar errors, or am I missing some code? Here is
what I do:


-----Original Message-----
From: ImageJ Interest Group [mailto:[hidden email]] On Behalf Of
audrey karperien
Sent: Wednesday, August 03, 2005 6:35 PM
To: [hidden email]
Subject: Re: Issue with ParticleAnalyzer output


Hello.
 
Below is some code that you can cut and paste and compile as a new
plugin that analyzes an image with the particle analyzer then writes the
coordinates for the rois and optionally colours over them in a new
image.  Its ripped out of another plugin so is rather bulky and hacky as
is but I think it is relevant to your question.
 
Audrey
 
import ij.*;
import ij.IJ;
import ij.ImagePlus;
import ij.WindowManager;
import ij.gui.*;
import ij.gui.GenericDialog;
import ij.gui.ImageWindow;
import ij.gui.PolygonRoi;
import ij.gui.Roi;
import ij.gui.Toolbar;
import ij.gui.Wand;
import ij.measure.ResultsTable;
import ij.plugin.*;
import ij.plugin.filter.Analyzer;
import ij.plugin.filter.ParticleAnalyzer;
import ij.process.ImageProcessor;
import ij.process.ImageStatistics;
import java.awt.*;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.*;
/*
 * UsePARois.java
 *
 * Created on August 3, 2005, 4:34 PM
 *
* Code ripped out of FracLac and quickly hacked into a demo of pa rois.
 *It analyzes an image and writes out the x,y and width and height of
the rois,
 *and optionally draws them back on the original image.  It is just a
quick hack that
 *will likely be prunable to something elegant.
 */
/**
 *
 * @author Audrey_2 Charles Sturt University, Neuroscience
 */
public class Use_PA_Rois implements PlugIn{
   
    /** Creates a new instance of UsePARois */
    public Use_PA_Rois() {
    }
    public void run(String  args){
        MakeImage=IJ.showMessageWithCancel("Make Image?",
                "Choose OK to draw the rois or cancel to make no new
image");
        Go();}
    int minparticle=30, maxparticle=99999;
  boolean MakeImage=false;
 
        public void Go(){
           
            String imgtitle=null;
            String x="", y="";
            ImageWindow wm = WindowManager.getCurrentWindow();
            if(wm==null) { IJ.noImage(); return;}
            else
            {                
               
                ImagePlus workingcopy=wm.getImagePlus();
                if(workingcopy==null) { IJ.noImage(); return;}
                else
                {                    
                    workingcopy.setSlice(1);

                                   
                   {int lastslice=workingcopy.getStackSize();
                     for (int thisslice = 1; thisslice <= lastslice;
++thisslice)
                    {//for each slice in the stack
                           workingcopy.setSlice(thisslice);

                           workingcopy.setRoi(0, 0,
workingcopy.getWidth(), workingcopy.getHeight());
                           if(!ScanParticles(workingcopy,   thisslice,
lastslice))return;

                         
                     }              
                   }}}}
 
   
   
    /**
     * Copies the current ROI to the clipboard. The entire
     *         image is copied if there is no ROI.
     * (Aug 2, 2005)@param cut boolean always false FIXME
     * @param imp ImagePlus to analyze
     * @param title String for image's title
     * @return ImagePlus copy of the roi selected
     */
    public ImagePlus copy(boolean cut, ImagePlus imp, String title
            ) {
        Roi roi = imp.getRoi();
       
       
        String msg = (cut)?"Cut":"Copy";
        IJ.showStatus(msg+ "ing...");
        ImageProcessor ip = imp.getProcessor();
        ImageProcessor ip2 = ip.crop();
        ImagePlus clipboard = new ImagePlus(title, ip2);
        if (roi!=null && roi.getType()!=Roi.RECTANGLE)
            clipboard.setRoi((Roi)roi.clone());
//        if (cut) {
//            ip.snapshot();
//
ip.setColor(F.V.background==F.V.WHITE?Color.white:Color.black);
//            ip.fill();
//            if (roi!=null && roi.getType()!=Roi.RECTANGLE)
//                ip.reset(imp.getMask());
//            imp.setColor(
F.V.foreground==F.V.WHITE?Color.white:Color.black);
//            Undo.setup(Undo.FILTER, imp);
//            imp.updateAndDraw();
//        }
        int bytesPerPixel = 1;
        switch (clipboard.getType()) {
            case ImagePlus.GRAY16: bytesPerPixel = 2; break;
            case ImagePlus.GRAY32: case ImagePlus.COLOR_RGB:
bytesPerPixel = 4;
        }
        IJ.showStatus(msg + ": "
                + (clipboard.getWidth()*
                clipboard.getHeight()*bytesPerPixel)/1024 + "k");
       
        return paste(clipboard, title);
    }
   
   
    /**
     * Pastes the passed image. I am trying to paste an roi without
     * (Aug 2, 2005)collecting the surrounding rectangle. FIXME
     * @return ImagePlus pasted
     * @param s needs fixing
     * @param clipboard ImagePlus copied
     */
    public ImagePlus paste(ImagePlus clipboard, String s) {
       
        ImagePlus imp = new ImagePlus("pasted"+s, clipboard.getImage());
        imp.setRoi(0, 0, imp.getWidth(), imp.getHeight());
 
imp.setColor(Color.white);//F.V.background==F.V.WHITE?Color.white:Color.
black);
        imp.getProcessor().fill();
        if (clipboard==null)
            return imp;
        int cType = clipboard.getType();
        int iType = imp.getType();
       
        boolean sameType = false;
        if ((cType==ImagePlus.GRAY8|cType==ImagePlus.COLOR_256)&&
                (iType==ImagePlus.GRAY8|iType==ImagePlus.COLOR_256))
sameType = true;
        else if
((cType==ImagePlus.COLOR_RGB|cType==ImagePlus.GRAY8|cType
                ==ImagePlus.COLOR_256)&&iType==ImagePlus.COLOR_RGB)
sameType = true;
        else if (cType==ImagePlus.GRAY16&&iType==ImagePlus.GRAY16)
            sameType = true;
        else if (cType==ImagePlus.GRAY32&&iType==ImagePlus.GRAY32)
            sameType = true;
        if (!sameType) {
            IJ.error("Images must be the same type to paste.");
            return imp;
        }
        int w = clipboard.getWidth();
        int h = clipboard.getHeight();
        if (w>imp.getWidth() || h>imp.getHeight()) {
            IJ.error("Image is too large to paste.");
            return  imp;
        }
        Roi roi = imp.getRoi();
        Rectangle r = null;
        if (roi!=null) r = roi.getBounds();
       
        if (true)
        {
            //non-interactive paste
            int pasteMode = Roi.getCurrentPasteMode();
            boolean nonRect = roi.getType()!=Roi.RECTANGLE;
            ImageProcessor ip = imp.getProcessor();
            if (nonRect) ip.snapshot();
            r = roi.getBounds();
           
            ip.copyBits(clipboard.getProcessor(), r.x, r.y, pasteMode);
            if (nonRect)
                ip.reset(imp.getMask());
            imp.updateAndDraw();
            imp.killRoi();
        } else {}
       
        return imp;
    }
   
    /**
     * Gets the rois for all particles in a passed ImagePlus,
     * then calls a method to scan them, returning nothing.
     * Invokes the ImageJ ParticleAnalyzer to segment
     * the image, then passes the image and the ResultsTable
     * containing roi coordinates to the
     * {@link #ScanTheProcessorFromEachParticlesRoi scanning method} to
     * scan each particle. The data from the scans are
     * accessed through the
     * ImageJ Results window eventually;
     * refer to the scanning method for the next
     * step.
     * @param thisslice int for the current slice or 1 if this is not a
stack
     * @param lastslice int for the number of slices in this stack or 1
if this is not a stack
     * @param img ImagePlus to scan
     * @return boolean true if not cancelled; false if the call to
the{@link #setupPA particle anlayzer}
     * set up is cancelled
     */
    public boolean ScanParticles(ImagePlus img,  int thisslice, int
lastslice) {
        boolean quit=false;
        boolean goOn=true;
        //store information
        String title = img.getTitle();
        ImageProcessor ip = img.getProcessor();
        Roi roi = img.getRoi();
        if(roi==null) {
            img.setRoi(0,0, img.getWidth(), img.getHeight());
            roi=img.getRoi();
        }//get user's options for the particle analyzer
        goOn=true;
        if(thisslice==1){
             goOn=setupPA();}//quit if cancelled here
        if (!goOn) return false;
        else//if not cancelled, go on
        {
            ImageStatistics stats = img.getStatistics();
            if
((stats.histogram[0]+stats.histogram[255])!=stats.pixelCount) {
                IJ.showMessage("Binary (thresholded) image required.");
                quit=true;
            }//quit if the image is not binary
            else if (!quit)//or else go on
            {
//                if (F.V.background==F.V.BLACK) {
//                    img.killRoi();
//                    invert(ip);
//                    img.updateAndRepaintWindow();
//                }
               
                //get the rois
                img.setRoi(roi);
                Analyzer ana=new Analyzer();
                int measurements = Analyzer.getMeasurements();
                ResultsTable rt = ana.getResultsTable();
                int options=
                        (ParticleAnalyzer.EXCLUDE_EDGE_PARTICLES|
                        ParticleAnalyzer.RECORD_STARTS
                        |ParticleAnalyzer.SHOW_NONE);
                measurements =
                        (ana.PERIMETER|ana.AREA);
                ParticleAnalyzer pa=new ParticleAnalyzer
                        (options, measurements, rt, minparticle,
maxparticle);
                Analyzer.resetCounter();
                img.setRoi(roi);
                pa.analyze(img);
                ip.setRoi(roi);
                ScanTheProcessorFromEachParticlesRoi(rt, img, thisslice,
lastslice, title);
               
            }
        }return true;
    }
   
     public void ScanTheProcessorFromEachParticlesRoi
            (ResultsTable rt, ImagePlus img, int thisslice, int
lastslice, String title) {
        ImageWindow win = img.getWindow();
        int nResults = rt.getCounter();
        ImageProcessor ip = img.getProcessor();
        Image StoredCopyOfOriginal = ip.createImage();
        float[] wandx=new float[nResults];
        float []wandy=new float [nResults];
       
        Roi [] RoisFromParticleAnalyzer=new PolygonRoi [nResults];
        float [][] ParticleRectangleXY=new float[2][nResults];
        for (int i=0; i<nResults; i++) {
            wandx[i] =(float) rt.getValue("XStart", i);
            wandy[i] =(float) rt.getValue("YStart", i);
            Wand w = new Wand(img.getProcessor());
           
            w.autoOutline(
                    (int)wandx[i],(int)wandy[i]);
            RoisFromParticleAnalyzer[i]= new PolygonRoi(w.xpoints,
w.ypoints,
                    w.npoints, Roi.TRACED_ROI);
           
            {ParticleRectangleXY[0][i]=
 
(int)RoisFromParticleAnalyzer[i].getBounds().getBounds2D().getX();
            ParticleRectangleXY[1][i]=
 
(int)RoisFromParticleAnalyzer[i].getBounds().getBounds2D().getY();}
           
        }
       
        for (int i=0; i<nResults; i++)
        {
 
WindowManager.setCurrentWindow(win);//img=win.getImagePlus();
            img.setRoi(RoisFromParticleAnalyzer[i]);            
            ImagePlus copied=copy(false, img, title);
            copied.killRoi();  
           
            IJ.write(ParticleRectangleXY[0][i]+","+
                    ParticleRectangleXY[1][i]+","+
 
(int)RoisFromParticleAnalyzer[i].getBounds().getBounds2D().getWidth()+",
"+
 
(int)RoisFromParticleAnalyzer[i].getBounds().getBounds2D().getHeight());
        }    
       
        if (MakeImage)
        {
         img.setSlice(thisslice);
           img.updateAndRepaintWindow();
           BufferedImage bi
                    = new BufferedImage(img.getWidth(),
                    img.getHeight(), BufferedImage.TYPE_INT_ARGB);
           Graphics2D g = (Graphics2D)bi.getGraphics();
           g.drawImage(StoredCopyOfOriginal, 0, 0, null);
           
            ColourRois
                    (ip,
                    1,//TYPE,
                    g,
                    RoisFromParticleAnalyzer, 190, 5,
                    0
                    );
           
            ImagePlus imgg = new ImagePlus("new"+title, bi);
           
            if(thisslice==1)
            {
                ColouredRoisStack = new ImageStack(img.getWidth(),
img.getHeight());
                ColouredRoisStack.addSlice(title, imgg.getProcessor());

            }
            else ColouredRoisStack.addSlice(title, imgg.getProcessor());
            if(thisslice==lastslice)
            {
                StackWindow iww = new StackWindow(new
ImagePlus(img.getTitle()
                        + thisslice, ColouredRoisStack));
                iww.setVisible(true);
            }
        }
    }
   
     ImageStack ColouredRoisStack =null;
       /**Sets up the ij.plugin.filter.ParticleAnalyzer using
     * a ij.gui.GenericDialog to get values for the minimum and
     * maximum particle size to find, and the background and
     * foreground arrangement (i.e., which is white and which is black).
     * Changes these variables in the {@link FLAnalyzer.FLVars variable
class}.
     * @return boolean false if cancelled or else true
     */
    public boolean setupPA() {
        GenericDialog gd
                = new GenericDialog("Particle Options",
IJ.getInstance());
        String [] C =
        {"Black", "White"};
        String ch = C[1];
     
        gd.addChoice("Background Colour", C, ch);
        gd.addNumericField("Minimum particle", minparticle, 0);
        gd.addNumericField("Maximum particle", maxparticle, 0);
        gd.showDialog();
        if (gd.wasCanceled()) {
            return false;} else {
            Color bg=Color.white;
            int t=gd.getNextChoiceIndex();
            if (t==0)bg=Color.black;
            Toolbar.setBackgroundColor(bg);
            minparticle=(int)gd.getNextNumber();
            maxparticle=(int)gd.getNextNumber();
            }
        return true;
    }
   
    public static void ColourRois (ImageProcessor ip,
    int TYPE,    
    Graphics2D g2,
    Roi [] rois,
    //float[] colours,
    //int ColourCode,
    float LocalAlpha,
    int comp,
    int foreground
    //boolean makescaleimage,
    //float [] DFS
   )
    {        
       
        Color gcolour= new Color (210, 240, 240);
        Color basecolour= new Color (210, 240, 240);
        for (int i = 0; i <rois.length; i++)
        {
           
            g2.setColor (gcolour);
            AlphaComposite acc
            = AlphaComposite.getInstance (AlphaComposite.SRC_OVER,
newAlpha(LocalAlpha,
            1.5f));
            g2.setComposite (acc);
            //colour the roi using the appropriate rule
           
            {          
             g2.fillPolygon (rois[i].getPolygon ());
            }
           
            //else if (TYPE==DRAW_IRREGULAR_ROI_NO_STRING)
            {          
             g2.drawPolygon (rois[i].getPolygon ());
            }
         
            ReplaceForegroundPixelsInIrregularRoi(rois[i], g2, ip,
foreground);
           
           
                   
        }
       
       
               
    }
   
    /**
      * Colours only the pixels that are the foreground
      * colour and in the passed roi on the passed image.
      *
      * @param  roi Roi to colour
      * @param  g2 Graphics2D on which to colour the roi
      * @param  ip ImageProcessor to colour
      * @param  foreground int for the foreground colour
      */    
    public static void ReplaceForegroundPixelsInIrregularRoi(
    Roi roi,
    Graphics2D g2,
    ImageProcessor ip,
    int foreground)
    {        
                int startx = (int)(roi.getBoundingRect().getX());
                int starty = (int)(roi.getBoundingRect().getY());
               
                for (int xx = startx;
                    xx< startx+(int)(roi.getBoundingRect().getWidth());
                    xx++)
                {
                   
                    for (int yy = starty;
                        yy<
starty+(int)(roi.getBoundingRect().getHeight());
                        yy++)
                    {
                        ip.setRoi (xx, yy, 1, 1);
                        //Roi smallroi = ip.getRoi ();
                        int [] histogram=ip.getHistogram ();
                        if (histogram[foreground]>0)
                        {                          
                           if(roi.contains(xx, yy))
                            g2.fillRect (xx, yy, 1, 1);
                        }                  
                }
                }
    }
   
    static float newAlpha(float LocalAlpha, float colour)
    {
        float floatLocalAlpha=(float)LocalAlpha/255.0f;
            floatLocalAlpha=floatLocalAlpha>1.0f?1.0f:floatLocalAlpha;
            floatLocalAlpha=floatLocalAlpha<0.0f?0.0f:floatLocalAlpha;
            return floatLocalAlpha;
    }
}

"Ludgate, David" <[hidden email]> wrote:
Hi,
I'm using the ParticleAnalyzer class to find particles and I need to
record the irregular ROIs that define each particle. I did this simply
by overriding the drawParticle method to record each ROI as it drew
them. So now my program displays an image of all the filled particles
and records the ROIs, which I use elsewhere.
My problem is that I run though this procedure many times and if I leave
all those images open I run out of memory really quickly. So I've been
trying to look for a way to close the images that the ParticleAnalyzer
makes automatically. I'm working directly with classes so i'd rather not
have to go to ImageJ's window manager and try to find each image, and
instead get the ImagePlus object used directly from the ParticleAnalyzer
class.
Unfortunately, as far as I can see, this is the line that creates that
window:
new ImagePlus
us.java.html> (prefix+title, outlines).show();
The ParticleAnalyzer thus has no way of keeping track of that window
once it is created.
Furthermore, I cannot override the method (at least, my IDE tells me I
can't) since "it is private to a different package".

Does anyone know of a way I can get around this? At the moment I do not
directly use the ImageJ program and deal with the classes directly,
thus, ImageJ doesn't recognise the windows I open as existing.

TIA, dave
Reply | Threaded
Open this post in threaded view
|

Re: Issue with ParticleAnalyzer output

Ludgate, David
In reply to this post by Ludgate, David
Sorry for the incompleted email just now. I'm adding in the code to the
bottom for this version.

Hi,
After your first email pointing out FracLac, I duplicated what seemed
the relevent code, and it seems to work - most of the time. One of my
processing steps is to go through the ROIs and dialate them (by taking
the mask, then dilating, then gettign the ROI for that mask). However,
after 713 successful dilations, one invariably causes an
ArrayIndexOutOfBoundsException in ByteProcessor (line 446). My
inclination is to put in an if statement to simply ignore this particle
- but I can't find any obvious difference between it and the rest.

Have you encountered similar errors, or am I missing some code? Here is
what I do:


for(int i = 0; i < rt.getCounter(); i++){
        Wand w = new Wand(ip);
        w.autoOutline((int)rt.getValue(6, i),(int)rt.getValue(7, i));
        Roi r = new PolygonRoi(w.xpoints, w.ypoints, w.npoints,
Roi.TRACED_ROI);
                               
        procList.add(r.getMask());
        roiList.add(r);
}


-----Original Message-----
From: ImageJ Interest Group [mailto:[hidden email]] On Behalf Of
audrey karperien
Sent: Wednesday, August 03, 2005 6:35 PM
To: [hidden email]
Subject: Re: Issue with ParticleAnalyzer output


Hello.
 
Below is some code that you can cut and paste and compile as a new
plugin that analyzes an image with the particle analyzer then writes the
coordinates for the rois and optionally colours over them in a new
image.  Its ripped out of another plugin so is rather bulky and hacky as
is but I think it is relevant to your question.
 
Audrey
 
import ij.*;
import ij.IJ;
import ij.ImagePlus;
import ij.WindowManager;
import ij.gui.*;
import ij.gui.GenericDialog;
import ij.gui.ImageWindow;
import ij.gui.PolygonRoi;
import ij.gui.Roi;
import ij.gui.Toolbar;
import ij.gui.Wand;
import ij.measure.ResultsTable;
import ij.plugin.*;
import ij.plugin.filter.Analyzer;
import ij.plugin.filter.ParticleAnalyzer;
import ij.process.ImageProcessor;
import ij.process.ImageStatistics;
import java.awt.*;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.*;
/*
 * UsePARois.java
 *
 * Created on August 3, 2005, 4:34 PM
 *
* Code ripped out of FracLac and quickly hacked into a demo of pa rois.
 *It analyzes an image and writes out the x,y and width and height of
the rois,
 *and optionally draws them back on the original image.  It is just a
quick hack that
 *will likely be prunable to something elegant.
 */
/**
 *
 * @author Audrey_2 Charles Sturt University, Neuroscience
 */
public class Use_PA_Rois implements PlugIn{
   
    /** Creates a new instance of UsePARois */
    public Use_PA_Rois() {
    }
    public void run(String  args){
        MakeImage=IJ.showMessageWithCancel("Make Image?",
                "Choose OK to draw the rois or cancel to make no new
image");
        Go();}
    int minparticle=30, maxparticle=99999;
  boolean MakeImage=false;
 
        public void Go(){
           
            String imgtitle=null;
            String x="", y="";
            ImageWindow wm = WindowManager.getCurrentWindow();
            if(wm==null) { IJ.noImage(); return;}
            else
            {                
               
                ImagePlus workingcopy=wm.getImagePlus();
                if(workingcopy==null) { IJ.noImage(); return;}
                else
                {                    
                    workingcopy.setSlice(1);

                                   
                   {int lastslice=workingcopy.getStackSize();
                     for (int thisslice = 1; thisslice <= lastslice;
++thisslice)
                    {//for each slice in the stack
                           workingcopy.setSlice(thisslice);

                           workingcopy.setRoi(0, 0,
workingcopy.getWidth(), workingcopy.getHeight());
                           if(!ScanParticles(workingcopy,   thisslice,
lastslice))return;

                         
                     }              
                   }}}}
 
   
   
    /**
     * Copies the current ROI to the clipboard. The entire
     *         image is copied if there is no ROI.
     * (Aug 2, 2005)@param cut boolean always false FIXME
     * @param imp ImagePlus to analyze
     * @param title String for image's title
     * @return ImagePlus copy of the roi selected
     */
    public ImagePlus copy(boolean cut, ImagePlus imp, String title
            ) {
        Roi roi = imp.getRoi();
       
       
        String msg = (cut)?"Cut":"Copy";
        IJ.showStatus(msg+ "ing...");
        ImageProcessor ip = imp.getProcessor();
        ImageProcessor ip2 = ip.crop();
        ImagePlus clipboard = new ImagePlus(title, ip2);
        if (roi!=null && roi.getType()!=Roi.RECTANGLE)
            clipboard.setRoi((Roi)roi.clone());
//        if (cut) {
//            ip.snapshot();
//
ip.setColor(F.V.background==F.V.WHITE?Color.white:Color.black);
//            ip.fill();
//            if (roi!=null && roi.getType()!=Roi.RECTANGLE)
//                ip.reset(imp.getMask());
//            imp.setColor(
F.V.foreground==F.V.WHITE?Color.white:Color.black);
//            Undo.setup(Undo.FILTER, imp);
//            imp.updateAndDraw();
//        }
        int bytesPerPixel = 1;
        switch (clipboard.getType()) {
            case ImagePlus.GRAY16: bytesPerPixel = 2; break;
            case ImagePlus.GRAY32: case ImagePlus.COLOR_RGB:
bytesPerPixel = 4;
        }
        IJ.showStatus(msg + ": "
                + (clipboard.getWidth()*
                clipboard.getHeight()*bytesPerPixel)/1024 + "k");
       
        return paste(clipboard, title);
    }
   
   
    /**
     * Pastes the passed image. I am trying to paste an roi without
     * (Aug 2, 2005)collecting the surrounding rectangle. FIXME
     * @return ImagePlus pasted
     * @param s needs fixing
     * @param clipboard ImagePlus copied
     */
    public ImagePlus paste(ImagePlus clipboard, String s) {
       
        ImagePlus imp = new ImagePlus("pasted"+s, clipboard.getImage());
        imp.setRoi(0, 0, imp.getWidth(), imp.getHeight());
 
imp.setColor(Color.white);//F.V.background==F.V.WHITE?Color.white:Color.
black);
        imp.getProcessor().fill();
        if (clipboard==null)
            return imp;
        int cType = clipboard.getType();
        int iType = imp.getType();
       
        boolean sameType = false;
        if ((cType==ImagePlus.GRAY8|cType==ImagePlus.COLOR_256)&&
                (iType==ImagePlus.GRAY8|iType==ImagePlus.COLOR_256))
sameType = true;
        else if
((cType==ImagePlus.COLOR_RGB|cType==ImagePlus.GRAY8|cType
                ==ImagePlus.COLOR_256)&&iType==ImagePlus.COLOR_RGB)
sameType = true;
        else if (cType==ImagePlus.GRAY16&&iType==ImagePlus.GRAY16)
            sameType = true;
        else if (cType==ImagePlus.GRAY32&&iType==ImagePlus.GRAY32)
            sameType = true;
        if (!sameType) {
            IJ.error("Images must be the same type to paste.");
            return imp;
        }
        int w = clipboard.getWidth();
        int h = clipboard.getHeight();
        if (w>imp.getWidth() || h>imp.getHeight()) {
            IJ.error("Image is too large to paste.");
            return  imp;
        }
        Roi roi = imp.getRoi();
        Rectangle r = null;
        if (roi!=null) r = roi.getBounds();
       
        if (true)
        {
            //non-interactive paste
            int pasteMode = Roi.getCurrentPasteMode();
            boolean nonRect = roi.getType()!=Roi.RECTANGLE;
            ImageProcessor ip = imp.getProcessor();
            if (nonRect) ip.snapshot();
            r = roi.getBounds();
           
            ip.copyBits(clipboard.getProcessor(), r.x, r.y, pasteMode);
            if (nonRect)
                ip.reset(imp.getMask());
            imp.updateAndDraw();
            imp.killRoi();
        } else {}
       
        return imp;
    }
   
    /**
     * Gets the rois for all particles in a passed ImagePlus,
     * then calls a method to scan them, returning nothing.
     * Invokes the ImageJ ParticleAnalyzer to segment
     * the image, then passes the image and the ResultsTable
     * containing roi coordinates to the
     * {@link #ScanTheProcessorFromEachParticlesRoi scanning method} to
     * scan each particle. The data from the scans are
     * accessed through the
     * ImageJ Results window eventually;
     * refer to the scanning method for the next
     * step.
     * @param thisslice int for the current slice or 1 if this is not a
stack
     * @param lastslice int for the number of slices in this stack or 1
if this is not a stack
     * @param img ImagePlus to scan
     * @return boolean true if not cancelled; false if the call to
the{@link #setupPA particle anlayzer}
     * set up is cancelled
     */
    public boolean ScanParticles(ImagePlus img,  int thisslice, int
lastslice) {
        boolean quit=false;
        boolean goOn=true;
        //store information
        String title = img.getTitle();
        ImageProcessor ip = img.getProcessor();
        Roi roi = img.getRoi();
        if(roi==null) {
            img.setRoi(0,0, img.getWidth(), img.getHeight());
            roi=img.getRoi();
        }//get user's options for the particle analyzer
        goOn=true;
        if(thisslice==1){
             goOn=setupPA();}//quit if cancelled here
        if (!goOn) return false;
        else//if not cancelled, go on
        {
            ImageStatistics stats = img.getStatistics();
            if
((stats.histogram[0]+stats.histogram[255])!=stats.pixelCount) {
                IJ.showMessage("Binary (thresholded) image required.");
                quit=true;
            }//quit if the image is not binary
            else if (!quit)//or else go on
            {
//                if (F.V.background==F.V.BLACK) {
//                    img.killRoi();
//                    invert(ip);
//                    img.updateAndRepaintWindow();
//                }
               
                //get the rois
                img.setRoi(roi);
                Analyzer ana=new Analyzer();
                int measurements = Analyzer.getMeasurements();
                ResultsTable rt = ana.getResultsTable();
                int options=
                        (ParticleAnalyzer.EXCLUDE_EDGE_PARTICLES|
                        ParticleAnalyzer.RECORD_STARTS
                        |ParticleAnalyzer.SHOW_NONE);
                measurements =
                        (ana.PERIMETER|ana.AREA);
                ParticleAnalyzer pa=new ParticleAnalyzer
                        (options, measurements, rt, minparticle,
maxparticle);
                Analyzer.resetCounter();
                img.setRoi(roi);
                pa.analyze(img);
                ip.setRoi(roi);
                ScanTheProcessorFromEachParticlesRoi(rt, img, thisslice,
lastslice, title);
               
            }
        }return true;
    }
   
     public void ScanTheProcessorFromEachParticlesRoi
            (ResultsTable rt, ImagePlus img, int thisslice, int
lastslice, String title) {
        ImageWindow win = img.getWindow();
        int nResults = rt.getCounter();
        ImageProcessor ip = img.getProcessor();
        Image StoredCopyOfOriginal = ip.createImage();
        float[] wandx=new float[nResults];
        float []wandy=new float [nResults];
       
        Roi [] RoisFromParticleAnalyzer=new PolygonRoi [nResults];
        float [][] ParticleRectangleXY=new float[2][nResults];
        for (int i=0; i<nResults; i++) {
            wandx[i] =(float) rt.getValue("XStart", i);
            wandy[i] =(float) rt.getValue("YStart", i);
            Wand w = new Wand(img.getProcessor());
           
            w.autoOutline(
                    (int)wandx[i],(int)wandy[i]);
            RoisFromParticleAnalyzer[i]= new PolygonRoi(w.xpoints,
w.ypoints,
                    w.npoints, Roi.TRACED_ROI);
           
            {ParticleRectangleXY[0][i]=
 
(int)RoisFromParticleAnalyzer[i].getBounds().getBounds2D().getX();
            ParticleRectangleXY[1][i]=
 
(int)RoisFromParticleAnalyzer[i].getBounds().getBounds2D().getY();}
           
        }
       
        for (int i=0; i<nResults; i++)
        {
 
WindowManager.setCurrentWindow(win);//img=win.getImagePlus();
            img.setRoi(RoisFromParticleAnalyzer[i]);            
            ImagePlus copied=copy(false, img, title);
            copied.killRoi();  
           
            IJ.write(ParticleRectangleXY[0][i]+","+
                    ParticleRectangleXY[1][i]+","+
 
(int)RoisFromParticleAnalyzer[i].getBounds().getBounds2D().getWidth()+",
"+
 
(int)RoisFromParticleAnalyzer[i].getBounds().getBounds2D().getHeight());
        }    
       
        if (MakeImage)
        {
         img.setSlice(thisslice);
           img.updateAndRepaintWindow();
           BufferedImage bi
                    = new BufferedImage(img.getWidth(),
                    img.getHeight(), BufferedImage.TYPE_INT_ARGB);
           Graphics2D g = (Graphics2D)bi.getGraphics();
           g.drawImage(StoredCopyOfOriginal, 0, 0, null);
           
            ColourRois
                    (ip,
                    1,//TYPE,
                    g,
                    RoisFromParticleAnalyzer, 190, 5,
                    0
                    );
           
            ImagePlus imgg = new ImagePlus("new"+title, bi);
           
            if(thisslice==1)
            {
                ColouredRoisStack = new ImageStack(img.getWidth(),
img.getHeight());
                ColouredRoisStack.addSlice(title, imgg.getProcessor());

            }
            else ColouredRoisStack.addSlice(title, imgg.getProcessor());
            if(thisslice==lastslice)
            {
                StackWindow iww = new StackWindow(new
ImagePlus(img.getTitle()
                        + thisslice, ColouredRoisStack));
                iww.setVisible(true);
            }
        }
    }
   
     ImageStack ColouredRoisStack =null;
       /**Sets up the ij.plugin.filter.ParticleAnalyzer using
     * a ij.gui.GenericDialog to get values for the minimum and
     * maximum particle size to find, and the background and
     * foreground arrangement (i.e., which is white and which is black).
     * Changes these variables in the {@link FLAnalyzer.FLVars variable
class}.
     * @return boolean false if cancelled or else true
     */
    public boolean setupPA() {
        GenericDialog gd
                = new GenericDialog("Particle Options",
IJ.getInstance());
        String [] C =
        {"Black", "White"};
        String ch = C[1];
     
        gd.addChoice("Background Colour", C, ch);
        gd.addNumericField("Minimum particle", minparticle, 0);
        gd.addNumericField("Maximum particle", maxparticle, 0);
        gd.showDialog();
        if (gd.wasCanceled()) {
            return false;} else {
            Color bg=Color.white;
            int t=gd.getNextChoiceIndex();
            if (t==0)bg=Color.black;
            Toolbar.setBackgroundColor(bg);
            minparticle=(int)gd.getNextNumber();
            maxparticle=(int)gd.getNextNumber();
            }
        return true;
    }
   
    public static void ColourRois (ImageProcessor ip,
    int TYPE,    
    Graphics2D g2,
    Roi [] rois,
    //float[] colours,
    //int ColourCode,
    float LocalAlpha,
    int comp,
    int foreground
    //boolean makescaleimage,
    //float [] DFS
   )
    {        
       
        Color gcolour= new Color (210, 240, 240);
        Color basecolour= new Color (210, 240, 240);
        for (int i = 0; i <rois.length; i++)
        {
           
            g2.setColor (gcolour);
            AlphaComposite acc
            = AlphaComposite.getInstance (AlphaComposite.SRC_OVER,
newAlpha(LocalAlpha,
            1.5f));
            g2.setComposite (acc);
            //colour the roi using the appropriate rule
           
            {          
             g2.fillPolygon (rois[i].getPolygon ());
            }
           
            //else if (TYPE==DRAW_IRREGULAR_ROI_NO_STRING)
            {          
             g2.drawPolygon (rois[i].getPolygon ());
            }
         
            ReplaceForegroundPixelsInIrregularRoi(rois[i], g2, ip,
foreground);
           
           
                   
        }
       
       
               
    }
   
    /**
      * Colours only the pixels that are the foreground
      * colour and in the passed roi on the passed image.
      *
      * @param  roi Roi to colour
      * @param  g2 Graphics2D on which to colour the roi
      * @param  ip ImageProcessor to colour
      * @param  foreground int for the foreground colour
      */    
    public static void ReplaceForegroundPixelsInIrregularRoi(
    Roi roi,
    Graphics2D g2,
    ImageProcessor ip,
    int foreground)
    {        
                int startx = (int)(roi.getBoundingRect().getX());
                int starty = (int)(roi.getBoundingRect().getY());
               
                for (int xx = startx;
                    xx< startx+(int)(roi.getBoundingRect().getWidth());
                    xx++)
                {
                   
                    for (int yy = starty;
                        yy<
starty+(int)(roi.getBoundingRect().getHeight());
                        yy++)
                    {
                        ip.setRoi (xx, yy, 1, 1);
                        //Roi smallroi = ip.getRoi ();
                        int [] histogram=ip.getHistogram ();
                        if (histogram[foreground]>0)
                        {                          
                           if(roi.contains(xx, yy))
                            g2.fillRect (xx, yy, 1, 1);
                        }                  
                }
                }
    }
   
    static float newAlpha(float LocalAlpha, float colour)
    {
        float floatLocalAlpha=(float)LocalAlpha/255.0f;
            floatLocalAlpha=floatLocalAlpha>1.0f?1.0f:floatLocalAlpha;
            floatLocalAlpha=floatLocalAlpha<0.0f?0.0f:floatLocalAlpha;
            return floatLocalAlpha;
    }
}

"Ludgate, David" <[hidden email]> wrote:
Hi,
I'm using the ParticleAnalyzer class to find particles and I need to
record the irregular ROIs that define each particle. I did this simply
by overriding the drawParticle method to record each ROI as it drew
them. So now my program displays an image of all the filled particles
and records the ROIs, which I use elsewhere.
My problem is that I run though this procedure many times and if I leave
all those images open I run out of memory really quickly. So I've been
trying to look for a way to close the images that the ParticleAnalyzer
makes automatically. I'm working directly with classes so i'd rather not
have to go to ImageJ's window manager and try to find each image, and
instead get the ImagePlus object used directly from the ParticleAnalyzer
class.
Unfortunately, as far as I can see, this is the line that creates that
window:
new ImagePlus
us.java.html> (prefix+title, outlines).show();
The ParticleAnalyzer thus has no way of keeping track of that window
once it is created.
Furthermore, I cannot override the method (at least, my IDE tells me I
can't) since "it is private to a different package".

Does anyone know of a way I can get around this? At the moment I do not
directly use the ImageJ program and deal with the classes directly,
thus, ImageJ doesn't recognise the windows I open as existing.

TIA, dave