How can I remove overlapping ROIs from ROI Manager?

Hello,

I have used Stardist to obtain the ROIs for all the nuclei in an image an now I would like to remove the ROIs that overlap from the ROI Manager. Ideally, I would like to be able to keep ROIs that overlap only a few pixels, but keeping only the ones that do not overlap at all could be enough. Any idea on how I can do it?

Thank you!

Hi @jmazario,

I think it would be easier to change you StarDist settings. One of the measurements is:

  • Overlap Threshold - higher values allow segmented objects to overlap substantially.

So if you decrease the value you used for that you should only have slightly overlapping objects left.

3 Likes

Thank you @lmurphy for your suggestion. I have tried that before, but the problem is that when I do it, nuclei that overlap severely (and I have a good bunch of them) get recongniced all together as a single nucelus and that is something I am trying to avoid.

I see I see, well the StarDist team might be able to help you with the parameters on your image.

I can see how it would be possible via scripting to check overlap versus no overlap using the “AND” function. So that you would be left with no overlapping ROIs. The little script below demonstrates how overlapping ROIs can be identified. However, when it comes to deciding which of the two ROIs are to be deleted, I’m not so sure.

(edit: realised my script was slightly wrong before)

for (i = 0; i < roiManager("Count"); i++){ 
	for (j = 0; j < roiManager("Count"); j++){
	   if (i != j){
	   	   	roiManager("Select", newArray(i,j));
	   		roiManager("AND");
	    
			if (selectionType()>-1) {
				print (i,j," do intersect");
	   		}
	   }
	}
}

When it comes to allowing a small overlap, I can only think of incredibly slow ways that it would MAYBE work, involving checking every point of each ROI with every point of each other one to measure overlap then setting a threshold with which to delete or not. But what if one ROI overlaps a little with one ROI but a lot with a third. It think it would be very tough to put in these kinds of decisions in place within the ImageJ macro language.

Perhaps someone will come along with a better idea.

2 Likes

I don’t think this is a StarDist issue. StarDist is working beautifuly recognizing overlapping nuclei (because they are overlapping). It is just that I have to get rid of them for further analysis.

That one is easy: both of them :slight_smile:

I agree. That’s why I am willing to settle for not overlapping at all.

This works beautifuly! I think I should be able to modify it to delete overlapping ROIs from the ROI Manager. I’m not sure yet how, but I will give it a shot. I will post it here when I have it or cry for help if I get stuck.

Thank you very much @lmurphy!

Hello Javier (and Laura) -

I think the following scheme could give you a reasonable balance
between convenience and efficiency:

Use the OR (Combine) command of the ROI Manager to combine
all of your ROIs into one big glob. Save it to the ROI Manager, and
measure its area.

Then loop through your original ROIs (still in the ROI Manager) and,
for each one, use the XOR command to “subtract” it from the glob.
Measure the area of the resulting ROI. The overlap is:
area (glob) - area (subtracted).

If the overlap exceeds your threshold, Delete the ROI from the ROI
Manager. (It might be more convenient to loop through the entries of
the ROI Manager from the end to the beginning, so that the ROI
deletion doesn’t mess up the ROI index that you are looping over.)

Note that this scheme has the following artifact (possibly relevant,
and perhaps desirable): If a given ROI has a small, below-threshold
overlap with several other ROIs, its combined overlap with all of
them could exceed the threshold, leading to its deletion. If you don’t
want this behavior, I believe that you will have to incur the expense
of looping over all pairs of ROIs and delete based on the individual
pair-wise overlaps.

Thanks, mm

OK, I think I have a way of doing it. I start by reducing the size of all the ROIs by a 1-pixel radius, so I can keep the ROIs that are barely overlapping and then remove all the overlapping ones. I don’t restore the original size afterwards because it isn’t that important for me, but it should be easy enough to do it.

So here is what I’ve been able to come up with:


/* This macro reduces the size of all ROIs in ROI Manager by a 1-pixel radius and then removes all averlapping ROIs.
 * The image corresponding to the ROIs must be open for the macro to work.
 */


nROIs = roiManager("Count");
overlappingROIs = newArray();

//setBatchMode(true);

for (k=0; k<nROIs; k++){
	roiManager("select", k);
	run("Enlarge...", "enlarge=-1 pixel");
	roiManager("add");
}

roiManager("deselect");
for (l=0; l<nROIs; l++){
	roiManager("select", 0);
    roiManager("delete");
}

for (i = 0; i < roiManager("Count"); i++){ 
	for (j = 0; j < roiManager("Count"); j++){
	   if (i != j){
	   	   	roiManager("Select", newArray(i,j));
	   		roiManager("AND");
	    
			if (selectionType()>-1) {
				overlappingROIs = Array.concat(overlappingROIs,j);
				j=nROIs;
	   		}
	   }
	}
}

roiManager("Select", overlappingROIs);
roiManager("delete");

print ("Total count: ",nROIs);
print ("Non-overlapping: ",roiManager("Count"));

print ("That's all, folks!");

It may not be the most elegant piece of code, but it does what I need it to do.

Thank you again @lmurphy for pointing me in the right direction.

1 Like

Hello @mountain_man,

This is a very interesting approach. So far, the code I’ve written will do the trick for me, but I will keep your suggestion in mind to work on it if I can find the time.

Thank you very much!