Transform one stack's ROIs onto another stack's ROIs


I’m wondering if this is possible in imagej? I have two stacks of images: a stack with images of a big organism and a stack with images of a small organism. I’ve already marked cells of interest throughout the stack as multipoint ROIs, different in each slice, in both organisms and now I want to use an affine transform to map the smaller organism onto the bigger organism.

Using BigWarp and the question here I can take one slice from each stack and map, via an affine transform, the smaller organism onto the bigger organism. (I’m having trouble exporting the image though).

I’m not really interested in the image of the organism itself though, only the ROIs.

So I have two questions:

  1. Is there a way of just loading a stack of ROIs without the original image?
  2. Is there a way of transforming one image stack (ideally this would be a stack of just ROIs) onto another image stack?

Thank you for any help, it’s really appreciated!

1 Like

Hi @est,

I’m going to have more questions than answers for you at the moment - just making sure I understand what you’d like to do.

It sounds like you’re doing a 2d transformation here - one slice to another slice. Am I understanding correctly? You can transform 2d roi’s using transformations you created with bigwarp with some scripts that are explained here. But I think that’s not quite what you want

What’s the problem?

…maaaybe. How are you saving your ROIs? ROI Manager?

Possibly a useful answer

What’s relatively easy to do right now would be the following.

  1. Create a stack from your ROI’s that is the same size as your image, but with a different “color” for each ROI, something like the image below.
  2. Transform that image with the affine you got (this will let you overlay the “rois” / masks from the smaller organism on the bigger one).
  3. If you want, it would be easy to get a “traditional” roi from that transformed image with the want tool.

I’m happy to help you get that working if it sounds like it would be an acceptable solution.


Below - an image with two rois that we’ve turned into differently colored “masks”

1 Like

Thank you so much for your detailed explanation.

I think your “possibly useful answer” is exactly what I want, thank you. I can add more detail to make sure though?

These are corresponding slices from stack one (smaller organism) and stack two (bigger organism). (I know that they have different number of slices at the moment but soon I’ll get stacks which have equal numbers of slices)

I’ve stored my ROIs as both .roi files from the ROI manager and then via Ctrl + M so that I have a csv with column headings: Area, Mean, Min, Max, X , Y, Slice.

Via the ROI manager I can load my .roi file and apply it to my organism as below.

I basically want to fit one worm/organism inside the other, so that their outside boundary/cuticle matches. Then, after that transformation, I can compare the locations of each of these ROIs/yellow dots from one organism to the other and see which ROIs/yellow dots are stable across worms and which are more variable.

Does that make anything any clearer?

I think that corresponds to everything you said in your “possible useful answer”. The only part I’m unsure about is what you mean by point 2 “with the affine you got”. I’m not sure where I would have previously calculated the affine following those 3 points.

Thank you so much for your offer of help and taking the time to look at this. I’m really grateful - I’ve been stuck for a while trying to figure it out.

1 Like

Right on,

Actually, yea, this makes a lot of sense, and it should be easier than I thought actually.

If you used bigwarp to align you images, then all you’ll need is the file where containing the landmarks you clicked.

Am I remembering correctly that you used bigwarp to align the two worm images? If so, did you set the “Transform type” option to affine?

More complete answer

Since you saved your roi to csv (!) you can use this script, without having to deal with step (1) of in the previous post. That script takes a csv file as input and writes a new csv file.

Caveat - if you changed the transform type in bigwarp, the script won’t quite work right now, but I’ll fix that problem today.

The steps to take:

  1. Make a new csv file from the one you have: the script needs the csv file’s columns to be x,y,z and without a “header” row at the top. You may also have to change “slice” to “z”, where z = (voxel depth) * slice and voxel depth is given in Image properties (Ctrl -Shift -P)
  2. Run the script above giving it the csv you made - this will give you a new csv with transformed points. I think the only tricky part here is you need to tell the script which “direction” you want the transformation to go.
  3. Import the csv as an roi - I don’t know how to do this right now, but it should be straightforward. If its not, please post back and we’ll figure it out.

Okay that was alot, but I think we’re almost there,


Helper on running scripts

I like to make a folder in my fiji installation where I put scripts like the one above - this way there’s a biwarp menu in my fiji that lets me run these quickly.

What I’m going to do to make your and others’ lives easier

  1. Modify that script so it works with different transformation types
  2. Modify that script so it can work with column headers
  3. Modify that script so it can deal with “Slice” instead of “Z”
1 Like

Thank you so much for this.

I’ve never run a script in Fiji before or written in java. I’m currently using the script interpreter using Plugins-> Scripting -> Script Interpreter and then changing the language to java. I tried saving to a bigwarp folder but can’t find a bigwarp menu. Is this correct?

Would you be able to advise where in the script to change the file name to give your script the csv I’ve made with the roi’s? Then, do I also need to tell it the path to my landmarks file from bigwarp, which I’ve saved. I’ve currently just kept all windows open from the bigwarp transformation.

Apologies for all the question, your explanation is clear I’m just very new to ImageJ. Thanks again for all the help.

Hi @est,

Not a problem. That script is written in groovy a language that is related to java. Thanks for bearing with me, and learning this new way to run scripts

You won’t have to do this. If you just run the script as is, a window will pop-up that looks like this:

where you can put the locations of all the files.

You can read lots of details about scripts in fiji here, but info relevant parts are below. There are two ways I usually run script like this in Fiji:

1) From a “fiji menu” (I recommend)

This is what I described above:

  • Make a folder in that has a useful name - I use
  • Save a copy of a script into the folder you created
  • Restart fiji
  • You should now see a new menu in the fiji main window with an item corresponding to the script you put there.


2) From the script editor

  • Open the script in the script editor.
    • You can drag and drop the script into the main fiji window or:
    • (Press [, or File > New > Script..) to open the script editor then:
    • File > Open in the script editor window to choose the script
  • Click the Run button

If you’re still having trouble please post back,

1 Like

Thank you so much! This works so well!

Using the script, gives the transformed X, Y points with a Z column which consists of only zero. Substituting that Z column for that in the original moving image gives the points I need though.

I’ve plotted the points using python’s plotly.

Thank you so much for all your help, this is fantastic!

1 Like


Glad to hear it’ll do the job for you!

This worries me though, and has me wondering if there’s a bug somewhere. :-/
If its possible / not too much trouble, would it be possible for you to share a file with your point roi’s and the landmarks so I can try this out and see if it really is a bug?

Another thing - I updated the script a little while ago.
Meaning if you re-download it following the same link from before you’ll get the new version. It has new options that I promised in a post above, namely:

Thanks again for trying this out for me!



Yes of course - it’s quite likely I’ve made a mistake somewhere.
These are my landmarks:
landmarksworm3.csv (378 Bytes)

These are the ROIs of my moving target:
nuclei_clusters_bigwarp.csv (8.8 KB)

I’ve just tried with the new version of the script but that raises an error for me with no output.


error_message_bigwarp.txt (3.6 KB)

If I used the old script, again using an empty csv file as my output, it works as before. This is the result I get prior to changing anything.

results_bigwarp.csv (22.2 KB)

Hope that’s useful?

1 Like