Getting line selection from longest skeleton path

Tags: #<Tag:0x00007fd69c845678> #<Tag:0x00007fd69c8451c8> #<Tag:0x00007fd69c844c78>


I was trying to plot a profile (or, alternatively, get a straightened image) of the longest shortest path of a skeleton, but I’m having difficulties getting a poly-line selection from the skeleton.

@iarganda Is there a way to get the polygon of the longest path from AnalyzeSkeleton_ via scripting the API? I was quickly browsing the source, but didn’t find a good entry point.

I tried to get the ROI of the longest path by

  • thresholding the Longest shortest paths and the Tagged skeleton images,

  • combining the longest-path segments with the neighboring junction voxels to create a pixel line of the path, and then

  • using something like the following script to transform the area selection to a polyline selection:

    // @ImagePlus imp
    import ij.gui.PolygonRoi
    import java.awt.Polygon
    roi = imp.getRoi()
    points = roi.getContainedPoints()
    poly = new Polygon()
    for (p in points) {
        poly.addPoint((int)p.x, (int)p.y)    
    pRoi = new PolygonRoi(poly, PolygonRoi.POLYLINE)

… but this of course horribly fails because the Point array returned by getContainedPoints is ordered pixel row-wise and not by nearest distance.

I also tried Edit > Selection > Area to Line, but this gives a closed polygon surrounding the pixel line, resulting in a wrong profile of double the length (you can also see how this is wrong by doing Edit > Selection > Fit Spline).

Or maybe there is a solution to do that in Ops already? I’d be grateful for any hints.

Analyzing cell layer thickness
Analyzing cell layer thickness
Analyzing cell layer thickness
Re-using ImageJ scripts in KNIME

What about getting the points using getShortestPathPoints() and then plotting their intensity values?


Hm, yes, I must have somehow overlooked this. Thanks a lot! :slight_smile:


Unfortunately, this doesn’t work well for plotting a profile along the whole length of the path, because the path segments don’t seem to be ordered in way that allows a continuous sampling of the path. This Groovy script illustrates the issue with a little animation:

import ij.IJ
import ij.gui.PolygonRoi
import java.awt.Polygon
import sc.fiji.analyzeSkeleton.AnalyzeSkeleton_

// Load Sample image, skeletonize, and zoom for illustration purposes
imp = IJ.openImage(""), "Skeletonize (2D/3D)", "")"Set... ", "zoom=400 x=60 y=77")

// Initialize AnalyzeSkeleton_
skel = new AnalyzeSkeleton_()
skel.calculateShortestPath = true
skel.setup("", imp)
// Perform analysis in silent mode
skelResult =, false, true, null, true, false)

// Read the results
shortestPaths = skelResult.getShortestPathList().toArray()
sppoints = skel.getShortestPathPoints()

poly = new Polygon()
for (p in sppoints[0]) {
    poly.addPoint((int)p.x, (int)p.y)
    imp.setRoi(new PolygonRoi(poly, PolygonRoi.POLYLINE))

pRoi = new PolygonRoi(poly, PolygonRoi.POLYLINE)

Any idea how to get the segments into the correct order to avoid any “jumps”?

Edit: here’s a simpler, 2D example animation illustrating the issue:

(created using this script)


I see. That part of the code was written by Huub Hovens but I’ll dig into it to see if I find a solution. So far you can simply start from the first point and check iteratively the neighbor that is in the list, so you visit the path in order. I can actually add that as a post-processing of the shortest path method…

Nice animation by the way :wink:


OK, I think I have fixed it with this commit.

@imagejan can you please test it? If you are happy with it, I’ll make a new release.


Wow, you’re fast! I just built (mvn -Djavadoc.skip because maven-javadoc-plugin complains) and tested it, and it works great:

Thank you so much, @iarganda!