Exclude image edge from perimeter measurement - Fiji

Hi there,

I need to extract the perimeter of the particles shown in white in the image, I have been using Analyze >> Analyze particles… and check “perimeter” in the box. However I need to exclude any “false perimeter” that is being generated by the edge of the image - highlighted in yellow in the image. I just want to measure the “real” perimeter of my particle.

test test2

my images in reality are much more complex than the examples above so here is an example of a real image:
827C3_100_1_se2.tif (1.5 MB)
someone suggested I use a “guard frame” but I have no idea what this is or how to use one…

thanks!

Hi BD_94,

Attached is a python script the creates a new results table with the ‘corrected’ perimeter.

It needs the image to be selected and for RoiManager to contain a list of rois (usually generated by analyze particles).

To run the script:

  • Click on File > New > Script...
  • Click on Language > Python
  • Paste the attached code in
  • Press Run

It runs through each roi and counts up the number of pixels that are touch any of the 4 boundaries. it converts this the units of the image, adds it to a new results window call “Corrected perimeter”.

I couldn’t get it to append to the active Results window, the results were blank for some reason.

Cheers,

Chris

from ij import IJ

# grab the image
imp=IJ.getImage()
w = imp.getWidth()     # use these to work out the border
h = imp.getHeight()	   # of the image

cal = imp.getCalibration()
px2um = cal.pixelWidth  # we need this convert pixels to lengths

# get the roi manager (this needs to conatins the roi from a threshold)
from ij.plugin.frame import RoiManager
roim = RoiManager.getInstance()

# Make a new results table
from ij.measure import ResultsTable
rt = ResultsTable()

for i in range(roim.getCount()):
	roi = roim.getRoi(i)
	
	# these ore the points in the roi
	points = roi.getContainedPoints()
	 
	# this is an array of True,False if the pixel is on the border
	border = [ (p.x==0) or(p.x==w-1) or (p.y==0) or (p.y==h-1) for p in points]

	# this is the length of parts of the roi touching a border
	length_border = sum(border)*px2um 


	perim = roi.getLength()
	rt.setValue("Label",i,i+1)
	rt.setValue("Perim",i,perim)
	rt.setValue("Border Length",i, length_border)
	rt.setValue("Perim non-border", i, perim-length_border)

rt.show("Corrected perimeter")

thanks so much!

That worked great - solved me a massive headache.

Is there any way to make sure that the number of each particle in the corrected perimeter results table corresponds to the numbers in the ImageJ “analyze results” file? e.g. for particle 1 in corrected perimeter I would also like to be able to see things like its area and the major / minor axes of the best fit ellipse, if I knew which particle it is in the main results then I could cross-reference.
Edit
In my results the values for “perimeter” don’t correspond e.g. particle 1 has perimeter 13000 in the original “analyze particles” but particle 1 in the corrected perimeter results has perimeter of 7641. I see in your screenshot above that the perimeters match

thanks!

Hi,

The ‘label’ column in the ‘Corrected perimeter’ table should match the index column (first) of the Results table.

Its sounds like a scale mismatch between original image and the one used to make the rois.
Sometimes when copying images the scale information can be lost and it reverts to pixels.

To check this:

  • close the Results window (if its open).
  • click on the RoiManger and press Deselect then Measure. A new Results window should appear
  • Run the script again.

I’ve added some measurements to the scripts (attached at the end)

Cheers,

Chris

from ij import IJ

# grab the image
imp=IJ.getImage()
w = imp.getWidth()     # use these to work out the border
h = imp.getHeight()	   # of the image

cal = imp.getCalibration()
px2um = cal.pixelWidth  # we need this convert pixels to lengths

# get the roi manager (this needs to conatins the roi from a threshold)
from ij.plugin.frame import RoiManager
roim = RoiManager.getInstance()

# Make a new results table
from ij.measure import ResultsTable
rt = ResultsTable()

for i in range(roim.getCount()):
	roi = roim.getRoi(i)
	
	# these ore the points in the roi
	points = roi.getContainedPoints()
	 
	# this is an array of True,False if the pixel is on the border
	border = [ (p.x==0) or(p.x==w-1) or (p.y==0) or (p.y==h-1) for p in points]

	# this is the length of parts of the roi touching a border
	length_border = sum(border)*px2um 


	perim = roi.getLength()
	stats = roi.getStatistics()
	rt.setValue("Label",i,i+1)
	rt.setValue("Area", i, stats.area*px2um**2)
	rt.setValue("Perim",i,perim)
	rt.setValue("Border Length",i, length_border)
	rt.setValue("Perim non-border", i, perim-length_border)

	rt.setValue("Width",  i,stats.roiWidth*px2um)
	rt.setValue("Height", i,stats.roiHeight*px2um)
	rt.setValue("Major",  i,stats.major*px2um)
	rt.setValue("Minor",  i,stats.minor*px2um)


rt.show("Corrected perimeter")

Thanks Chris, this worked great.