Measure within ROI/overlay using python script

I’m trying to write a python script that creates an overlay or ROI from a binary image, applies this overlay/ROI to another image, then measures this other image within the overlay/ROI.

If I were to do this interactively using ImageJ, I would do the following:

  1. Open a binary mask image
  2. Edit >> Selection >> Create Selection
  3. Selection >> Add to Manager
  4. Open an image to be measured
  5. Click on ROI in ROI manager
  6. Analyze >> Measure

I can’t seem to figure the right functions to use. Here’s what I have so far:

from ij import IJ, ImagePlus
from ij.plugin.frame import RoiManager

img = IJ.openImage(imgPath)
mask = IJ.openImage(maskPath)

roi = IJ.run(mask, "Create Selection", "")

rm = RoiManager()
rm.runCommand("Reset")
rm.addRoi(roi)

rm.runCommand(img,"Measure")

I get a message saying “There are no images open”, but I’ve verified that the paths are correct.

I’d prefer if there was a way to do this strictly with overlays (so I can run this headless), but would also be happy for a solution that uses the ROI manager.

Hello Nick -

Let me give you two answers, below.

First, looking at your code, there are a couple of things going on.

IJ.run(mask, "Create Selection", "")

doesn’t return an Roi, so roi is None (in python-speak).

Then when you call addRoi (None) (it appears to me that) the
RoiManager says no Roi – I’ll get one from an open image instead.

Even though you called IJ.openImage(maskPath), from the
perspective of the ImageJ gui you don’t have an “open” image;
you have to call mask.show(). (That is, in this context “open”
really means open and displayed.)

So the RoiManger can’t find an “open” image and gives you
your “There are no images open” message.

Here’s a complete, runnable jython script that illustrates this, and
does, I think, what you want. (Note, I’ve stored a copy of the ImageJ /
Fiji clown.jpg sample image. I also thresholded it and stored the
result as the binary clown_mask.tif. You’ll need to modify the path
names appropriately to actually get the script to run.

from ij import IJ
from ij.plugin.frame import RoiManager

img = IJ.openImage ('/home/user/clown.jpg')
mask = IJ.openImage ('/home/user/clown_mask.tif')

IJ.run (mask, "Create Selection", "")  # creates, but doesn't return an Roi

mask.show()  # need to show image for it to be "open"

rm = RoiManager()
rm.runCommand ("Reset")

rm.addRoi (None)  # no Roi given, so use selection of "open" image

rm.runCommand (img,"Measure")

You’re correct that you don’t need the RoiManager to do this. (When
running interactively, the RoiManager can be convenient for keeping
things organized, but using it is sometimes unnecessarily roundabout
when scripting.) You can simply copy the Roi from your mask image
to the image you want to measure.

Here’s a jython script (that uses the same two local clown images)
that avoids the RoiManager:

from ij import IJ

imp = IJ.openImage ('/home/user/clown.jpg')
mask = IJ.openImage ('/home/user/clown_mask.tif')

IJ.run (mask, "Create Selection", "")

roi = mask.getRoi()
imp.setRoi (roi)
stats = imp.getStatistics();
print 'stats =', stats

Thanks, mm

2 Likes