Automate cropping around point ROIs



Hi all,

I’ve been banging my head (figuratively) trying to figure out how best to do this, and I’d really appreciate some input.

I have a stack of images containing a time-lapse of fluorescent cells travelling around the field of view (where each slice is a time step), which appear as spots of light. I’m able to generate point ROIs for the cells across the entire time-lapse, by using TrackMate extras to export these spots to the ROI manager.

Here’s where I get stuck. I’d like to be able to automatically crop a rectangle centred around these point ROIs for analysis, and save that as a separate image. I found one macro in a thread which does something similar (measuring area instead of cropping), but only on the image that’s currently open.

Here’s the macro in question:

getSelectionCoordinates(xpoints, ypoints);
for (i=0; i<lengthOf(xpoints); i++) {
makeOval(xpoints[i]-radius, ypoints[i]-radius, 2radius, 2radius);
roiManager(“Show All”);
run(“Set Measurements…”, “area redirect=None”);

I’ve not played around with this too much, but my worry is that if I apply a similar macro to the entire stack, it’ll crop everywhere where a cell appears in the stack for each slice (because the ROI manager doesn’t seem to save slice information with a particular ROI, as far as I can tell). Does anyone know of a better way to automatically crop these images? Thanks.


Hi @tm2313,

I’m not sure of the format of the TrackMate ROIs, but the ROI manager can save slice information. Here’s a screenshot of some point ROIs I made on a stack. The first number in each ROI name (0015 and 0058 respectively) shows the slice number.

51 PM

This macro uses the slice info to crop around each point ROI in the ROI manager:

// @Integer(label = "Cropped image width, pixels:") cropWidth
// @Integer(label = "Cropped image height, pixels:") cropHeight
// @File(label = "Output folder:", style = "directory") outputdir

// simple_CropToPoint.ijm
// ImageJ/Fiji macro by Theresa Swayne
// Input: An open image (single plane or stack) and a set of single-point ROIs in the ROI manager.
// Output: For each point, the image is cropped to the specified size, centered on the point, in the same slice as the point ROI
// 		Output images are named with the original filename plus a numerical suffix from 0 to the number of point ROIs.
// Usage: Open an image. Mark points with the Point tool, or otherwise load them into ROI Manager. Run the macro. 

// get file info 
id = getImageID();
title = getTitle();
dotIndex = indexOf(title, ".");
basename = substring(title, 0, dotIndex);

// setup

numROIs = roiManager("count");
for(i=0; i<numROIs;i++) // loop through ROIs
	cropName = basename+"_"+i; // this becomes the name of the cropped image
	roiManager("Select", i); 
	roiSlice = getSliceNumber();
	Roi.getCoordinates(x, y); // x and y are arrays
	run("Specify...", "width=&cropWidth height=&cropHeight x="+x[0]+" y="+y[0]+" slice=&roiSlice centered"); // rectangle ROI centered on the point
	run("Duplicate...", "title=&cropName"); // create the cropped image, relevant slice only
	saveAs("tiff", outputdir + File.separator + getTitle);
run("Select None");

If I’m misunderstanding the issue, or this doesn’t work for you, maybe you could post an example of the ROIset you’re working with, and this will help others figure out the problem.

Hope this helps.


Thanks! I suspected that ROIs came with slice information, however, my ROIs look a little different in that the first number for all of them is the same. Here’s a couple of examples:

0001 - 0295 - 1325
0001 - 0292 - 1323

This is probably the reason why I assumed the ROIs didn’t have slice information, although after reading the TrackMate information panel more carefully, it’s obvious that they should be slice-specific. Verbatim, it says “Generates an IJ multi-point ROI from the visible spots and add them all to the ROI manager. There is one multi-point ROI created by frame”.

I should probably also mention that I’m working with a multi-channel image, which I suspected was causing the first number to remain the same after reading your post. However, when I repeated the spot identification using only my fluorescent channel, I still got the same number for each ROI, so I don’t really know whether TrackMate has a different naming convention or if it’s not picking up the multiple slices I have.

There’s something else that’s just occurred to me; for this example, I’m using a stack with a single cell, but there are other files I have containing multiple cells. Based on the description above, TrackMate creates multi-point ROIs when it sees multiple spots, so do you happen to know if your macro will work with these?

Regardless, I’ll have a play around with your macro to see if it works (although I’m still very much an ImageJ novice, so this might take me a little time!). Thank you for the help.

Addendum: Specifically, I’m using the TrackMate extras extension, because TrackMate didn’t originally have the functionality to export ROIs.


Well, I’ve tried the macro with my current stack of images, and it looks like it’s cropping the first slice only, which TrackMate’s naming is probably behind. There wouldn’t happen to be a way to bulk-rename ROIs in the manager would there? With about 80 slices per stack, I’d prefer not to do it manually, but frankly it still beats doing the cropping and saving on my own by miles.

I still need to check how the macro behaves with multiple spots, but this is definitely a step in the right direction.

EDIT: Okay, so the macro I think skips any slices where there’s more than one cell (I’m still playing around with the thresholding for TrackMate, so occasionally I lose a cell when I’m doing the tracking). Might it be possible to iterate over the selections in a for loop or something? Thanks.


Hi @tm2313,

Thanks for trying it and reporting back.

This is at least part of the issue. My macro works with single point ROIs, where each ROI is a single point. In multi-point ROIs, the points can be in different slices so the “0001” in the name is not necessarily where all the points are.

Off the top of my head, I’m not sure if the Multi-Point ROI has a convenient way to retrieve the individual slice locations, but if you select the ROI in the manager, and then do roiManager("measure")both the slice number and the XY coordinates end up in the Results table.

Then you could loop through the results table (there should be many posts on the forum about how to do this), and use setSlice() to move to the correct timepoint, before cropping around the corresponding xy position.

There would then be 2 nested loops: through the ROIs in the manager, and then for each ROI a loop through the data in the Results table.

I haven’t worked with TrackMate myself, so I’m tagging TrackMate’s lead @tinevez, to see if he has any other suggestions for cropping out your cells.

Hope this helps.

Looping over ROI results table and extracting XY coordinate values