Turn a segmented line or freehand line into x/y coordinates

Hello everyone. I’m a medical student with no programming knowledge. For my research project I need to analyze a small number of regions in the tumor margins. To reduce selection bias we thought it would be best I randomly select points on a hand drawn line. I found a different blog post that describes an almost similar problem only here the solution was made with straight lines in mind. There is an edit below for different lines but I get no results…
https://forum.image.sc/t/placing-a-point-at-divided-lengths-of-a-line/5820/2

So basically I want to achieve the same as the initial answer. Segment the line into points and extract their x/y coordinates. I would like to do this using a freehand or segment line so I can more accurately follow the tumor margins. I would then randomly select a number of points on that line.

I’m putting the code Rob Lees made for the straight line here:

saveDir = getDirectory("Choose directory for saving things..."); //user chooses folder to store ROIs in 
fileName = getTitle();						//takes the image name to name the ROI file at the end

getSelectionCoordinates(x, y); 				//returns array of x and y coordinates for selection (in this case a straight line has only two points and four coords)

ylength = y[0] - y[1]; 						//finds the length of the line in the y axis by taking the first y coordinate from the second
xlength = x[0] - x[1];						//finds the length in the x axis	the same way
n = getNumber("How many segments?", 10); 	//asks how many segments to break the line in to (points are plotted in between each segment and the ends of the line)	
yinc = (ylength/n); 						//the increment in the y axis between each point's y coordinate
xinc = (xlength/n); 						//the increment in the x axis between each point's x coordinate
for (j=0; j<=n; j++) { 						//a for loop to plot points, repeats for the total number of segments + 1 (as 0 is counted)
	xcoord = x[0] - (xinc*j); 				//calculates the x coordinate of the point to be plotted by subtracting the increment value (multiplied by the current segment number defined by 'j') from the first x coord of the line
	ycoord = y[0] - (yinc*j); 				//calculates the y coordinate as above from the top-most point on the line
	makePoint(xcoord, ycoord); 				//makes a point selection at the x and y coords calculated above
	Roi.setName("point" + j);				//renames the selection to something that can be distinguished from the rest
	roiManager("Add");						//add the point to the roi manager
}

roiManager("save", saveDir + fileName + "_ROIs.zip"); //saves all the point ROIs for this line to a .zip file in the folder specified at the start

exit("Macro finished"); //the ROIs can be reloaded by dragging the .zip in to imagej

You have this marked as QuPath, but that is not QuPath code. I am not sure how the FIJI code fits into your project if it is in fact a QuPath based analysis.

I use qupath to create regions that I then send to imageJ for further analysis. I tried doing it within qupath but I couldn’t find a way to do so. There seem to be more resources for imageJ.

@Walid_El_Baouchi Here’s a QuPath script that does something similar to what you describe:

// Define max distance between points (change this as required).
// Note: Some points may be closer!
// See https://locationtech.github.io/jts/javadoc/org/locationtech/jts/densify/Densifier.html for more info
double distance = 100

// Density the currently selected ROI
def roi = getSelectedROI()
if (roi == null) {
    println 'No ROI selected!'
    return
}
def geom = roi.getGeometry()
geom2 = org.locationtech.jts.densify.Densifier.densify(geom, distance)

// Create an annotation corresponding to the densified points
def points = geom2.getFactory().createMultiPointFromCoords(geom2.getCoordinates())
def pointsROI = GeometryTools.geometryToROI(points, roi.getImagePlane())
def pointsAnnotation = PathObjects.createAnnotationObject(pointsROI)

// Add, then select, the points annotation
addObject(pointsAnnotation)
selectObjects(pointsAnnotation)

// Print the coordinates
def coords = pointsROI.getAllPoints().collect { it.x + ", " + it.y}
println String.join("\n", coords)

It wasn’t clear to me what exactly you meant with ‘extract their x/y coordinates’, so the script will both print them and also generate a new points annotation (which you can also use to save coords with the ‘Points’ tool in the toolbar).

2 Likes

This works just as I had hoped! Even better because I can stay within Qupath. Thank you so much @petebankhead !

2 Likes