How to measure length in an image

Hello !

In any binary image how to measure length of any feature.

For example, in the posted image, how to measure length of line tagged as No. 1 in the image.

Hi @neel

Can you attach your original binary image here as well? That would be helpful… but good that you showed us exactly what you want to measure.


1 Like


Thanks. Actually I am trying to upload that binary image itself but unfortunately it is not becoming visible on this window.

I am sharing you the link of that binary image on google drive.


Sorry, I attached link for another tiff image. But the objective is same. Actually I want to measure the length of all those features that has value 255 in the image, altogether.

Hey @neel

Actually… it should be pretty straightforward. At least this is a quick-and-dirty method to give you an idea… perhaps someone has a better method though??

Since your lines are single pixels… you can simply:

run("Make Binary");
run("Analyze Particles...", "  circularity=0.00-0.25 display exclude clear add");

By setting circularity near 0 … you will be selecting linear objects, which is what you want in this case. You can then measure your ROIs of interest using the Analyze Menu options.

The area should be the length of your lines in pixels - they are equivalent in your case - but again - only with the continued assumption that your lines are a single pixel in width.



Thank you. It worked. It’s giving me the length of all the features that are included in the image. I need one last help, I believe.

Suppose I have a stack of images. Then how can I save these lengths of the features separately from stack of images in an excel sheet. Is there any way for it?


You can run these same functions on a stack… you’ll have to modify the code a bit. Something like this:

run("Make Binary", "method=Default background=Default calculate black");
run("Analyze Particles...", "  circularity=0.00-0.25 display exclude clear add stack");

Just try it out yourself. If you are still having problems… post another example of one of your stacks and then specifically what you need or are having trouble with.



Thank you for the help. This is the last question from my side. I have 2 separate task to perform separately. And I need the help with Macro to execute these 2 tasks.

First task is:
Convert the whole stack into images back into a folder with their original name.

Second task is:
Analyze particles for all these separated images and save them with same name as an excel file for further computation.

With your above specified code, I am able to analyze particles for the whole stack but still I can’t save them as a separate file for each image. That’s why I thought first to convert the stack into individual images and then apply “Analyze particle” tool so that I can separately get their data.

I hope I am quite clear with my query.

I have a macro with me which can convert stack into images and save them separately. But it has 2 issues:

First issue is the output image from the stack has black background and white colored foreground. I am trying to convert it into white background and black foreground but couldn’t succeed.

Another issue is the name of the output image is something like “Title of Stack+ Slice number”. While I want it as original file name from which stack was prepared.

So, to save the time, I am posting that macro which needs minor changes to save image separately. And, if possible, please suggest macro for 2nd task.

> requires("1.33s"); 
> dir = getDirectory("F:\\PD-15-TOP\\stack "); 
> setBatchMode(true); 
> count = 0; 
> countFiles(dir); 
> n = 0; 
> processFiles(dir); 

> function countFiles(dir) { 
>     list = getFileList(dir); 
>     for (i=0; i<list.length; i++) { 
>         if (endsWith(list[i], "/")) 
>             countFiles(""+dir+list[i]); 
>         else 
>             count++; 
>     } 
> } 

> function processFiles(dir) { 
>     list = getFileList(dir); 
>     for (i=0; i<list.length; i++) { 
>         if (endsWith(list[i], "/")) 
>             processFiles(""+dir+list[i]); 
>         else { 
>             showProgress(n++, count); 
>             path = dir+list[i]; 
>             processFile(path); 
>         } 
>     } 

> function processFile(path) { 
>     if (endsWith(path, ".tif")) { 
>         open(path); 
>         title=getTitle(); 
>         len = lengthOf(title); 
>         lenPath = lengthOf(path); 
>         path = substring(path, 0, lenPath-len); 
>         for(i=1;i<=200; i++){ 
>           newTitle = substring(title, 0, len-4)+" Slice "+i; 
>           newPath = path+newTitle; 
>           run("Select All"); 
>           setSlice(i); 
>           run("Copy"); 
>           setAutoThreshold("Default");
>           newImage("Untitled", "8-bit Dark", 1779, 1770, 1); 
>           run("Paste"); 
>           saveAs("Tiff", newPath); 
>           close(); 
>         } 
>       close(); 
>     } 
> } 

Please see how much you can help. I will be really thankful for the efforts.

Ok @neel -

I’m not expert here. But I will answer what i can…

You can use this macro function: run("Stack to Images"); You could include this in your processFile function.

So this is still not clear to me. If you want to save a results table for each individual image or the ‘stack’ of images… the only difference is where you call this function: saveAs("Results", "NameItWhatWhereYouWant.xls");

I would suggest modifying this example code:
(the different OPTIONS I highlight will save your data in different ways depending on what you want exactly. So test it on a smaller dataset and see what you prefer)

// @File(label = "Input directory", style = "directory") input
// @File(label = "Output directory", style = "directory") output
// @String(label = "File suffix", value = ".tif") suffix

 * Macro template to process multiple images in a folder


// function to scan folders/subfolders/files to find files with correct suffix
function processFolder(input) {
	list = getFileList(input);
	for (i = 0; i < list.length; i++) {
		if(File.isDirectory(input + list[i]))
			processFolder("" + input + list[i]);
		if(endsWith(list[i], suffix))
			processFile(input, output, list[i]);
        /// OPTION A
	saveAs("Results", output+ "/All_Results.xls"); //saves all results for all images in excel file (as long as you didn't clear the table within your processFile function below)

function processFile(input, output, file) {
	open(input + "/" + file);
	save(output + "/Binary_OUTPUT_" + file); // saves the binary image
        // OPTION B : if you want to save your results - you can do so here... and just make sure to clear the table too
        // OPTION C : i also recommend saving your ROI files ... so you can call the code below if you choose
        roiManager("Save", output+ "/" + file + ".zip"); // saves Rois for each image

Hope this helps you a bit!


1 Like

I have to disagree: counting pixels is not the same as measuring length! The length of a diagonal line (with single pixel width) is 1.4x the length of a horizontal line containing the same number of pixels.

To measure the length of lines in a binary image (e.g. after running Plugins > Skeleton > Skeletonize (2D/3D)), use Analyze > Skeleton > Analyze Skeleton (2D/3D), which will give you the lengths of each segment and optionally the longest shortest path

Also, the Morphology update site by @gabriel provides a Lines8_ command that provides more accurate length measurements for lines (see documentation)

Instead of using Stack to Images as suggested by @etadobson, you can also simply save your stack as image sequence: File > Save As > Image Sequence…

I agree that for setting up batch processing macro, this code is the best starting point. You can always find it in the script editor menu at Templates > ImageJ 1.x > Examples > Process Folder (IJ1 Macro) as well as on the source code repository.


@imagejan thanks !!! i’m learning as i go as well… :wink:

1 Like

@etadobson @imagejan

Thank you for the possible solutions. Well I wrote a macro for that which can analyze particles for images and save their results in form of an excel file. But, as @imagejan pointed out that this method is not that accurate, I will try to use analyze skeleton tool. Since, my images are binary so I don’t think it will be any problem.

Well, whatever the result comes, I will update here.

@imagejan Which command I should use for determining length using Morphological operator?


I use EDM_16bit plugin in Morphology library. But it’s giving a distance map as an output. I want the information of distance of objects, having value 255, in numbers like Analyze particle does. Do you have any idea what to do next after EDM_16 bits.


I am not able to find Lines8_.class to install in imagej. Where can I find it?


It is solved now. I found Lines8_.class and successfully ran it too. The results of length measurement from Lines8_.class and analyze particles have quite a difference. I wish this is the final step to be executed for length determination.

Thanks @imagejan and @etadobson for all the help.

Glad that you solved it. Actually, you don’t have to fiddle around with .class files at all. As I mentioned in my post above, just activate the update site called “Morphology”, then all the commands are available in the Plugins > Morphology submenu.

Also, instead of posting four times in sequence, you can also just edit your previous posts by clicking on the small pencil icon below the post.

With respect to

I have to disagree: counting pixels is not the same as measuring length! The length of a diagonal line (with single pixel width) is 1.4x the length of a horizontal line containing the same number of pixels.

I should like to point out an ingenious approach proposed by Michael Schmid on the ImageJ-list ( Feb 25, 2016):

Of course the macro must be adapted to the case in question.