How to normalise or subtract background in QuPath with DAB only stained sections?

Not sure, I did not keep the old images. They were very frequent in the SVS files so I do not think they were worse in the .tif files.

1 Like

It is definitely something you should look for.

1 Like

I’ll try to see if anyone else knows in the facility!

Wow thanks, these are really good, from what I can see it outlines exactly what I want. If there was a way to do the batch analysis with QuPath that would be so much better than cropping and exporting each image to ImageJ. Especially since I cannot analyse the whole section with ImageJ.

The above ImageJ macro is great, it did a really good job detecting only the structures, regardless of the different stain intensities!

Hi @kitcat the script posted in

will probably help you to ‘solve’ the pattern issue.

1 Like

Oh wonderful, thank you so much for doing this @phaub, as well as @Research_Associate and @petebankhead for helping! :slightly_smiling_face:

1 Like

@kitcat Maybe you can try to run the script to make sure that the clij GPU portions are working.
For the test you can select only one small region on one of your slides. No need to convert the whole images.

1 Like

Sorry dumb question, but which script do I use? I can see in the forum that you and the other Peter were adding extra scripts and doing some modifications, so I just wanted to clarify what was the most updated script. I had some troubles understanding the new modifications you guys made since I don’t understand the scripts :sweat_smile:

Use the first script version since this is the base for the next step.

In this script file you can find the information how to install the clupath extension in QuPath:

//    CluPath has to be installed as QuPath extension.
//    More information can be found in
//    and from
//    you get the info:
//    "On Windows and MacOS the installation should work right away in case the computer has a built-in Intel HD or AMD Ryzen GPU.
//    In case dedicated AMD or NVidia GPUs are used, special drivers might have to be installed.
//    Search for more information about drivers on the websites of the GPU vendors."

Here is the info from

Download the following jar file and drag&drop it on QuPath. QuPath will take care of it and install it in the right folder.


Yes it worked for me! :smiley:

1 Like

Hi @kitcat, I have a working version of the second script (creating and adding local threshold channel).
It is not very fast and it takes some time to save the modified image.
I would like to discuss and optimize some details of the code, with the goal of omitting all channels that are not necessary.
The first question is: How many slides/files do you have to process?

1 Like

Hi @phaub, thanks a lot for that!

I have 4 antibodies that would require a similar process, and each antibody has 24 files. So I would be processing 24 files at a time/project.

Hi @kitcat,
sorry for not coming back earlier.

In the meantime we have implemented the local threshold methods into clij. @haesleinhuepf will release a new clupath version in the near future.

With this new clupath version we can go the next step.

My idea was to create a local threshold image (either as a separate file or as an additional channel in the image) - similar to the creation of a smoothed image version (described here).

I have to agree to @petebankshaed objection that this strategy is not very effective -
especially in your case (processing of 4+24 images with 2 sections on each slides).

Maybe we will find a better strategy by using the local threshold methods inside the cell detection directly.

Until then I would like to propose saving only the local threshold channel as an additional image while reducing the resolution of this channel by a factor of 2 to speed up the creation of this additional image.
Then you can detect the cells in this local threshold image and transfer the detection’s to the original image for measurement.

What is your current state?
Have you found a solution for your task in the meantime?


Hi @phaub, don’t be sorry, that’s okay!

That’s great news, thank you!

Yeah if only there was a way to dissect the thresholding methods inside the cell detection, because that seems to have the inbuilt background subtraction. But I can’t use the cell detection feature as my structures aren’t circular.

I’m still struggling and trying to play around. I’m seeing if I can train pixel classification, but it’s not the best so far.

If all fails I might end up having to crop each of my images and send the region to ImageJ and do background subtraction etc from there. Was really hoping I could do everything from QuPath.

Hi @kitcat check this

You can use the script posted there to become familiar with the local Phansalkar threshold, to get used to the parameters and to decide if this threshold method will give meaningful results.

I’m not 100% sure if this threshold method is perfect for your stain variations because the characteristics of the local threshold offset is influnced by the mean intensity. That is exactly what you don’t want.

‘Play’ a bit with the parameters.
Hope you can run the script.

1 Like

Hi @phaub,

Great, I’ll have a play around and fingers crossed it works! Thank you so much for helping out, I really appreciate it! :smiley:

Hi @kitcat,
I made some minor changes in the second script and I described how to use the temporary channel with the local threshold information for cell detection.

1 Like

Hi @kitcat check the updates on


1 Like

Hi @phaub,

Thanks for letting me know! :smiley:

Hi @kitcat,

it seems as if you are close to a solution.

Just to mention two issues regarding the Color Deconvolution.

Color Deconvolution of a single stain

In your case of a single DAB staining it is much better to work with TWO residual vectors instead of an adjusted HTX vector and one residual (as it is done when you adjust the stain vectors in QuPath).

Working with two residual results in a reduced DAB error since both residual are orthogonal to the DAB vector. This approach is somehow similar to PCA (principle component analysis).

To work in this way you can adjust the DAB vector in Analyze>Preprocessing>Estimate stain vectors.
(The HTX vector can be ignored.)

Then you can calculate an arbitrary vector orthogonal to the DAB vectors by the following formula:

DAB = [DAB_r   DAB_g DAB_b]
R1 = [R1_r  R1_g  R1_b]

Calculating the first orthogonal residual
temp = (- R1_g – R1_b) / R1_r
R1_Norm = sqrt(temp*temp + 2)

R1_r = temp/R1_Norm
R1_g = 1/R1_Norm
R1_b = 1/R1_Norm

You can enter this residual vector values by double clicking on Stain 1 in the Image tab of the analysis pane.
The second orthogonal residual will be calculated automatically by QuPath.

Here are my sample values:

DAB = [ 0.243 0.51 0.825 ]
R1 = [ -0.968 0.176 0.176 ]
(R2 = [ 0.0555 0.8419 -0.5368 ])

Influence of the checkerboard pattern on the Color Deconvolution (CD)

The checkerboard patterns in your images are different in the R, G, B channels. Therefore it can be expected that the CD of individual pixel RGB combinations are potentially (strongly) influenced by the checkerboard ‘artifacts’.

To show this I have compared the CD result of the unmodified pixel data (see upper row in the following images) with a smoothed version of this CD result (lower row, left) and a CD result created on data smoothed before calculating the CD (lower row, right).

Overview image

At high zoom levels the influence of the checkerboard pattern onto the CD DAB channel can be seen in the upper row (both, left and right, show CD DAB channel. Data left and right is equivalent but in different formats with different LUT).
In the lower row it can be seen that smoothing the CD data after the Color Deconvolution results in bright spot artifacts (lower left) while smoothing the data before Color Deconvolution help to avoid such artifacts.

Consider to ‘remove’ the checkerboard in your data.


Hey @phaub,

Thank you so much for all your help!