Using API to create mask with multiple rectangles

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

Using API to create mask with multiple rectangles

Leonard Sitongia
Hi,

What's the best way to create a mask that is composed of multiple
rectangles?

That is, I have an image which I want to measure the value of the pixels
in several rectangular areas in the image.  With the GUI, I could use
the ROI Manager to draw several rectangles, and Measure to get the
values in the rectangles.

It looks like there are several ways I could do this with the API,
including using the GUI to draw and save the ROIs, and reading them in
with the API, which is slick.  But, I'm wondering about the basics in
the API.

I can easily create an AWT Rectangle, and set it on an ImageProcessor.

How do I set multiple Rectangles on an ImageProcessor?  I guess that I
need to create a mask, perhaps using an AWT Shape?  Can a ROI have the
shape of multiple separate Rectangles?  Or, do I need to apply each
rectangular ROI one-at-a-time to the image and add up the values from each?

Can I easily get the sum of the values of the image in the rectangles?  
I see Measurements and ImageStatistics, but I don't see simply the sum
of the pixels.  Can I easily get the sum?  Without calculating all the
other statistics?

Thanks!

--
==Leonard E. Sitongia
   High Altitude Observatory
   National Center for Atmospheric Research
   P.O. Box 3000 Boulder CO 80307  USA
   [hidden email]  voice: (303)497-2454  fax: (303)497-1589
Reply | Threaded
Open this post in threaded view
|

Re: Using API to create mask with multiple rectangles

Albert Cardona
Use the ShapeRoi. You can add any other roi to it. For example:

// make ShapeRoi from a rectangle roi:
ShapeRoi sroi = new ShapeRoi(new Roi(0, 0, width1, height1));

// add a second rectangle
sroi.add(new ShapeRoi(new Roi(x,y,w,h));

All the above can be done with the java.lang.geom.Area as well, with
regular java.awt.Rectangle instances.


To get the sum of the pixel values within the ROI, get the mask first
from the roi, and if the pixel in the mask in non-zero, add the
corresponding pixel from the image.


Albert


--
Albert Cardona
http://www.mcdb.ucla.edu/Research/Hartenstein/acardona
Reply | Threaded
Open this post in threaded view
|

Re: Using API to create mask with multiple rectangles

Leonard Sitongia
Albert Cardona wrote:
> Use the ShapeRoi. You can add any other roi to it. For example:
>
> // make ShapeRoi from a rectangle roi:
> ShapeRoi sroi = new ShapeRoi(new Roi(0, 0, width1, height1));
>
> // add a second rectangle
> sroi.add(new ShapeRoi(new Roi(x,y,w,h));
I don't see an add method for the ShapeRoi.  I see that AWT Shape
subclasses like Rectangle have an add method, so one can add a Rectangle
to another Rectangle (but I don't understand what it means to have a
rectangle made up of two, possibly unrelated, rectangles).
>
> All the above can be done with the java.lang.geom.Area as well, with
> regular java.awt.Rectangle instances.
>
Yes, I see javax.awt.geom.Rectangle2D, which is a superclass of
Rectangle, can do this.

So, would I create one Rectangle and add others to it, giving me one ROI
made up of the union of all the Rectangles?  I should then be able to
set this on my ImageProcessor and have the operation apply to all pixels
within all Rectangles.  I tried this,

                Rectangle mask = new Rectangle();
                mask.add(new Rectangle(100,100,100,100));
                mask.add(new Rectangle(500,100,100,100));
                ip.setRoi(mask); // Set the Region Of Interest
                ip.multiply(1000.0); // Scale it up to make it visible

and the result is not as expected.  I don't get two separate rectangles
of 1000x value, but one rectangle of the dimensions of the largest of
the individual dimensions, that is one rectangle at (100,100) with a
size of 600x100.
>
> To get the sum of the pixel values within the ROI, get the mask first
> from the roi, and if the pixel in the mask in non-zero, add the
> corresponding pixel from the image.
I don't follow this.  I don't understand what the mask is in ImageJ.  I
see that irregular ROIs produce a mask, but I'm not sure what it is.  I
think it is what I want, the mask representing my multiple rectangles,
but I'm not sure.

Thank you!

--
==Leonard E. Sitongia
   High Altitude Observatory
   National Center for Atmospheric Research
   P.O. Box 3000 Boulder CO 80307  USA
   [hidden email]  voice: (303)497-2454  fax: (303)497-1589
Reply | Threaded
Open this post in threaded view
|

Re: Using API to create mask with multiple rectangles

Leonard Sitongia
In reply to this post by Albert Cardona
I don't get masks in ImageJ.  If I

                imageJ = new ImagePlus("Original", imageIVOA);
                ip = imageJ.getProcessor();
                ip.setColor(Color.WHITE);
               
                ip.setRoi(100, 100, 100, 100);
                ip.setRoi(500, 100, 100, 100);

                ip.fill(); // Make it visible
             
Then I get an image with only the second rectangle filled with white.

If I try to get the combination of both rectangles as a mask by doing

                ImageProcessor mask = ip.getMask();
                ip.fill(mask); // Make it visible

I still get only the second rectangle.  As the API says, the fill
applies to what is in the mask and the ROI.  If the mask contains both
rectangles, then the ROI must be the last one set, and the intersection
is the last one.

==Leonard
Reply | Threaded
Open this post in threaded view
|

making multiple movies

Jeff Spector
I"m still trying to get a macro that will read a list of directories
within a directory, then make /avi's out of the file sin each sub dir.  
I thought what I did would work, but is doesn't, can someone please
help.  Here is what I have to open each  dir as an image sequence.
***********
 macro "multi movie maker38"{
 dir = getDirectory("Choose a Directory"); //the top level dir
 list1 =  getFileList(dir) ;   //list of each dir
 stack = 0 ;
 setBatchMode(true);
  for ( i = 0 ; i < list1.length; i++) {
        if (endsWith(list1[i], "/")) {
 
           list2 = getFileList("" + dir + list1[i]); //list of the files
in the current dir

            print(dir+list1[i]+list2[0]); // this works fine
            print(" ");
            run("Image Sequence...", "open=dir+list1[i]+list2[0]  
number=list2.length increment=1 scale=100 file= sort" ); //doesn't seem
to work ?
            saveAs("AVI... ",""+dir+list1[i]+".avi");
            close();
      }
  else
   print("Error : Not an Image File!");
  }

}

****************
The print statement works fine, and prints out the correct path to the
files, but they never seem to open. please help...
thanks,
 -jeff
Reply | Threaded
Open this post in threaded view
|

Re: Using API to create mask with multiple rectangles

Gabriel Landini
In reply to this post by Leonard Sitongia
On Monday 19 November 2007 21:23:32 Leonard Sitongia wrote:
> I don't follow this.  I don't understand what the mask is in ImageJ.  I
> see that irregular ROIs produce a mask, but I'm not sure what it is.  I
> think it is what I want, the mask representing my multiple rectangles,
> but I'm not sure.

If you do not mind running a macro rather than a plugin, there is a simple way
to do this:
Take your image and find the width and height,
Create a new empty (background) image
Draw or define the rectangular ROIs and fill them with the foreground colour.
Now run the Particles8_Plus plugin on the binary image and redirect to the
original greyscale or RGB. (you can do this I think with the
Particle_Analyzer pluigin too).

The Results Table will contain now the statistics of the ROIs of the binary
image but using the greyscale values of the original.

I hope it helps.

G.
Reply | Threaded
Open this post in threaded view
|

Re: Using API to create mask with multiple rectangles

Leonard Sitongia
Gabriel Landini wrote:
> If you do not mind running a macro rather than a plugin, there is a simple way
> to do this:
>  
I appreciate your offer, but I'm using the API within my own Java code,
which isn't even a plugin.  This is outside of ImageJ.  I'm using it for
the image processing algorithms.

--
==Leonard E. Sitongia
   High Altitude Observatory
   National Center for Atmospheric Research
   P.O. Box 3000 Boulder CO 80307  USA
   [hidden email]  voice: (303)497-2454  fax: (303)497-1589
Reply | Threaded
Open this post in threaded view
|

Re: Using API to create mask with multiple rectangles

Albert Cardona
In reply to this post by Leonard Sitongia
Leonard,

You're right, the ShapeRoi doesn't have an 'add' method, but it does
have the 'or', 'and', 'not' and 'xor' methods. To add, use the 'or':
unary union operator.

What the 'or' will give you is a new Roi composed of two rectangles
,which may be intersecting each other or not. If they do, then you get a
single continuous area; if they don't, two disconnected islands.

The mask: it's meant to specify which image pixels fall under the ROI
and which don't. It's a binary.
The masks enables non-rectangular ROIs to still be able to be filled
with color properly, or measured, or whatever.

In jython:

 >>> s = ShapeRoi(Roi(100,100,300,300))
 >>> imp = IJ.getImage()
 >>> imp.setRoi(s)
 >>> s.or(Roi(500,500,300,300))
 >>> s.or(ShapeRoi(Roi(500,500,300,300)))
 >>> imp.updateAndDraw()
 >>> s.or(ShapeRoi(Roi(700,400,300,300)))
 >>> imp.updateAndDraw()

The above generates a ShapeRoi with a rectangle at top left and then two
intersecting rectangles more to lower right.

To fill it with the foreground color:

 >>> imp.getProcessor().fill(s.getMask())
 >>> imp.updateAndDraw()

The s.getMask() returns a ByteProcessor which has all its pixels as 0 or
255 (-1, in byte)


The mask, notice, is only for the pixels within the bounds of the ShapeRoi:

 >>> ip = s.getMask()
 >>> print ip
ip[width=900, height=700, min=0.0, max=255.0]

 >>> print s.getBounds()
java.awt.Rectangle[x=100,y=100,width=900,height=700]

So to find out which pixels are in and which out, you have to translate
the coordinates by the x,y of the ROI bounds.

Also: don't use ip.setColor(Color.white), which is deprecated, but the
ip.setValue().

I hope this helped. The above can be translated to java code trivially.
I used the JythonInterpreter to do it (
http://www.mcdb.ucla.edu/research/hartenstein/acardona/software.html ).

Albert

--
Albert Cardona
http://www.mcdb.ucla.edu/Research/Hartenstein/acardona