Issues with exporting masks from QuPath

I am trying to apply U-Net multi-class segmentation procedure on whole slide histopathology brightfield images that were annotated in QuPath by several tissue region categories such as tumor, normal, stroma etc.

See example of multi class annotations (showing only a small subset of a slide):
Screen Shot 2020-05-22 at 7.25.29 PM

I need to bring the QuPath annotations into a single whole slide binary multi-channel PNG image where each tissue region category has its mask coded (for all the regions/elements in the slide) in the corresponding channel, in addition to a background channel annotating all the non annotated pixels. Alternatively, I would have a Python Numpy array coding the same annotation, but these two formats are exchangeable. Alternatively, XML output of the annotations should work too.

The problem is that Python access to QuPath project files is not possible, and QuPath groovy scripts focus on tiles or individual ROIs instead of the whole image.

Is there an existing script performing such task or can you advise how to arrive at one that does so?


The reason the Groovy scripts focus on tiles is that a whole slide image is typically just far too big to export as a PNG – at least at full resolution.

This page describes how to export an ImageServer in different ways, at different resolutions:

The exact same scripting approaches can be applied to export the full image for the LabeledImageServer created in exporting annotations section.

But if your image is too large, the export will either fail (because of memory/array length issues) or be totally impractical (because a PNG is not a tiled, pyramidal image).

The only export format that should work for whole slide images in general through QuPath is currently .ome.tif – because it does support writing tiled, pyramidal images.

XML is a bit too vague… the exporting annotations page says why it is not supported. But GeoJSON is well-defined, and you can export as that.

Thanks but I don’t think the resolution is the problem - the output would be just a binary image. Anyway I could use a lower resolution representation if resolution is the only problem. Can you clarify how the exporting tiles script from the link you provided can be used to export the whole image in intermediate resolution? Or how can I export the .ome.tif you mentioned?


I’ve updated the documentation now to provide an example of this:

Thank you, that works well for RGB downsampled image coding the regions with different colors. However, I get the following error when I set .multichannelOutput(true) to get a multi-channel (channel per annotation group) image:

ERROR: IOException at line 28: Unable to write /Users/Assaf/Dropbox/shared_imaging/Tissue_Segmentation/export/Li63NDCLAMP-labels.png!  No compatible writer found.

ERROR: Script error (IOException)
    at qupath.lib.images.writers.ImageWriterTools.writeImage(
    at qupath.lib.scripting.QP.writeImage(
    at qupath.lib.scripting.QP$writeImage$0.callStatic(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(
    at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(
    at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(
    at qupath.lib.gui.scripting.DefaultScriptEditor.executeScript(
    at qupath.lib.gui.scripting.DefaultScriptEditor.executeScript(
    at qupath.lib.gui.scripting.DefaultScriptEditor.executeScript(
    at qupath.lib.gui.scripting.DefaultScriptEditor$
    at java.base/java.util.concurrent.Executors$ Source)
    at java.base/ Source)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.base/java.util.concurrent.ThreadPoolExecutor$ Source)
    at java.base/ Source)

How can I resolve this?


The PNG writer can’t support an arbitrary number of channels.
Change the file extension to either .tif or .ome.tif.