How to delete all pixels (or set to zero) in a ROI which are above a certain value

  • I am imaging nuclear pores in widefield with fluorescent dyes.

  • I acquire a z-stack.

  • Then segment cells using thresholding and morpholibJ, resulting in 1 ROI per cell.

-I want to go through each ROI, and set to zero any pixel which is above a certain intensity value (very bright pixels).

  • This allows me to run some analysis on the z-stack that neglects an artefacts that is coming from the immunostaining of samples.

I try a few ways to do this but dont find an elegant solution.

For example:
I can duplicate my stack, run a threshold on the whole image, setting the threshold= given intensity values… Then run analyze particles, which creates thousands of ROIs
Then go through each of these new ROIs created in my initial image and subtract the given pixel intensity value.

This solution is problematic as it makes me work with way more ROIs than I want.

Any elegant solution to this?

Note: I am preferably using the ImageJ macro language

Hi @dlite-x,

If I read your post correctly, you already have a list of ROIs (or an overlay or something) and you want to find a way to set ‘high’ pixels to zero whilst looping through your existing ROIs, and without creating any unecessary new ROIs.

However, is the threshold the same for all the images in the stack(s) and across all ROIs? If so, perhaps consider ignoring the ROIs for the high-pixel capping/zeroing. In that case, you can cycle through the stack and apply the same operation to all images and with minimal ROI handling. I think this macro follows your precise instructions and is an example of ignoring the ROIs:

//option 1
setBatchMode("hide");
setThreshold(210, 255); //put your thresholds here
for (i = 1; i <= nSlices; i++) {
    setSlice(i);   
	run("Create Selection");
	run("Set...", "value=0");
	run("Select None");
}
resetThreshold;
setBatchMode("exit and display");

I also enclosed the code in a batchmode block, for likely speedup (may or may not be noticeable depending on the size of your images). You can then do your ROI analysis on the already modified images… or just after each slice is changed within the same loop, if you want to cut back on overall loop iterations.

This is another potential solution, which doesn’t do exactly waht you ask, but I feel may still mitigate against high-pixel atefacts:

//option 2
run("Remove Outliers...", "radius=2 threshold=50 which=Bright stack");

It’s also my favourite, as it’s simple and should be very fast. You may also need to play with the settings, to match your needs (although, that goes for all my answers here really).

Finally, if, for whatever reason, you do only want to change the pixels within each ROI, this slightly more convoluted code might work for you:

//option 3
setBatchMode("hide");
originalImageTitle = getTitle();
for (j = 0; j < roiManager("count"); j++) {
	roiManager("select", j);
	run("Duplicate...", "title=temp");
	//option 1 or 2 here... option 1 is used in this example, below
	setThreshold(210, 255); //put your thresholds here
	run("Create Selection");
	run("Set...", "value=0");
	run("Restore Selection");
	resetThreshold;
	run("Copy");
	close("temp");
	selectWindow(originalImageTitle);
	run("Paste");
}
run("Select None");
setBatchMode("exit and display");

Obviously, the thresholds that I chose for all ‘solutions’ above are completely arbitrary. I was also manipulating 8-bit image stacks in my testing. I also assumed that your ROIs are in the ImageJ ROI manager. I didn’t know all the particulars of your workflow, but hopefully the principals I outlined should be easy enough to adapt to your own data.
I also fully acknowledge that there may be an even easier and more complete solution that I do not know of or did not link with your question, that some other clever person in this forum may embarrass me by posting :sweat_smile:. In fact, given your original explanation, you may have already considered any or all of the above and want something more elegant again! Apologies if that is the case.

Kind regards.

Oops, very sorry but I didn’ handle a situation in my last set of answers where no pixels meet the threshold. Unfortunately it’s more convoluted again, but below are the corrected versions:

//option 1
setBatchMode("hide");
setThreshold(210, 255); //your thresholds here
for (i = 1; i <= nSlices; i++) {
    setSlice(i);   
	run("Create Selection");
	if (selectionType() != -1) {
		run("Set...", "value=0");
	}
	run("Select None");
}
resetThreshold;
setBatchMode("exit and display");

//option 2
run("Remove Outliers...", "radius=2 threshold=50 which=Bright stack");

//option 3
setBatchMode("hide");
originalImageTitle = getTitle();
for (j = 0; j < roiManager("count"); j++) {
	roiManager("select", j);
	run("Duplicate...", "title=temp");
	//option 1 or 2 here... option 1 is used in this example, below
	setThreshold(210, 255); //your thresholds here
	run("Create Selection");
	if (selectionType() != -1) {
		run("Set...", "value=0");
		run("Restore Selection");
		resetThreshold;
		run("Copy");
		close("temp");
		selectWindow(originalImageTitle);
		run("Paste");
	} else {
		close("temp");
	}
}
run("Select None");
setBatchMode("exit and display");
1 Like

Hi @antinos
Yes indeed for my purposes, I can remove “hot pixels” from the entire image and dont need to work within the ROIs.

I used option 1.
The solution allows me to remove all pixel above a certain value while precluding use of more ROIs.

Here the final code I used:

HotPix = 150; Stack.getStatistics(voxelCount, mean, min, StackMax, stdDev); setThreshold(HotPix, StackMax); //your thresholds here for (i = 1; i <= nSlices; i++) { setSlice(i); run("Create Selection"); if (selectionType() != -1) { run("Set...", "value=0"); } run("Select None"); } resetThreshold;

1 Like

By the way, I called the artefacts “hot pixels” but really they are more like blobs. thats why filtering doesnt remove them well.