Adaptive thresholding macro question

Hi there,

I have a 1 frame, 2 channels, 50 z slices image file that I want to apply a adaptive threshold to. But I only want to apply the threshold to the 1st channel. So I wrote the following macro:

selectWindow("x");
run("8-bit");
Stack.getDimensions(width, height, channels, slices, frames);
Stack.setChannel(1);
for(z=1; z<slices; z++){
  setSlice(z);
  run("adaptiveThr ", "using=Mean from=127 then=-100 stack");
}

However, I`m getting the first half (the first 25 slices) of both channels analyzed instead of getting the whole 50 slices of channel 1 analyzed. The second half of both channels are left alone. I was wondering what have I done wrong here.

Thanks for any suggestions!

Hi @chny,

According to the Adaptive Threshold webpage,
"It only works on 8-bit grayscale image or stack right now. "

It seems that the plugin is analyzing the first 50 “slices” of the internal representation of the hyperstack, which is (I believe) a 1D stack in cz order, so C1Z1, C2Z1, C1Z2, C2Z2, etc. I think this may be due to the plugin not being aware of the channels.

So you may need to split the channels before doing the threshold.

Hope this helps.

2 Likes

Hi @tswayne,

I’m aware the 8-bit requirement of the plugin. That’s why I convert my image to 8-bit using the run(“8-bit”) line. And I do specify the channel using stack.setchannel command. I suppose it would run the plugin in the order of C1Z1, C1Z2, C1Z3… But it doesn’t seem to be the case. I think it’s likely running the plugin in the order of C1Z1, C2Z1, C1Z2, C2Z2 as you mentioned, but why imagej does so is puzzling me…

I did try to separate those two channels and run my macro to only one channel. And it worked fine. All 50 slices were thresholded. But I still want to avoid separating two channels.

Thanks for the answer though.

I share your puzzlement, but I’ve encountered similar behavior before with other plugins or commands not parsing hyperstacks correctly.

Conceivably, you could update the macro to split the channels first and then re-merge them at the end.

Or you could poke around in the Adaptive Threshold source code and try to make it more channel-savvy.

Dear @chny,

you might have mixed up setSlice() and Stack.setSlice(). The former sets a slice in the stack representation that @tswayne has brought up, the latter sets the position of a hyperstack in Z direction (which I am assuming is what you are trying to achieve).

Also, is there a specific reason you are using the adaptiveThr plugin instead of Image > Adjust > Auto Local Threshold?

Best,
Stefan

1 Like

Hi @stelfrich,

Thanks very much for the advice. It worked after changing setSlice to Stack.setSlice.

I’m using this adaptiveThr because it offers the preview feature that I can see what’s being selected if I change the parameters in real-time manner. Although I’m not sure whether the source code of adaptiveThr is the same as one of the methods that already exists in Auto local threshold. I didn’t try extensively with the default Auto Local Threshold, will it work better? Thanks!

Not necessarily. The Auto Local Threshold is a Java implementation of the different algorithms, while adaptiveThr uses the implementations from OpenCV under the hood. The only significant difference that I can think of is that Adaptive Local Threshold comes bundled with Fiji, so you don’t have to do an additional installation step to get everything up and running.

That said: if it’s working then everything is fine and you shouldn’t really bother about that :thumbsup: