QuPath: Export individual annotation on entire size image( just like the image size of labeled image)

Export individual annotation on entire size image( just like the image size of labeled image)

Have you looked at the labelserver export options? It sounds like you want the actual pixel size, or downsample set equal to 1.

Sorry I did not tell it very clear. For example in an image there are 30 annotations and I want to export 30 images, and each image has only one single annotation. And each image has same size just like the exported label map. How can it work?

Still not entirely clear, so you may want to explain your end goal, as Pete mentions here:


There are a few other posts in that thread discussing exports.

Or is there any way to export annotation as a full labelled image and each single annotation has its own label? Because now I am doing instance segmentation, so I need each single annotation as single label.

for example, just like 30 annotations in an image, I want the result is a label map with label varying from 0 (background) to 30 ( 30th instance)

You may want to look into StarDist export scripts, in that case. Remember that however you are writing the images out, the file size needs to fit the file type you want to write to. You haven’t stated any kind of image information, so there is not much else I can say specifically.

Alternatively, there are a LOT of posts on the forums, so you may be able to find something that more exactly fits your needs. The labelserver would work if you always have 30 instances, since you could assign numbers to each. When it is a random number of annotations, I am less sure of how the labeledImageServer can handle that situation.

Maybe @petebankhead or @melvingelbard will have an idea.

Oh wait, here we go, maybe this is the most similar to what you wanted.

"the pixel IDs are still unique. "

@yuchi you can use the LabeledImageServer method from


with the .useUniqueLabels() option.

So for example your script might be

def imageData = getCurrentImageData()

// Define output path (relative to project)
def outputDir = buildFilePath(PROJECT_BASE_DIR, 'export')
mkdirs(outputDir)
def name = GeneralTools.getNameWithoutExtension(imageData.getServer().getMetadata().getName())
def path = buildFilePath(outputDir, name + "-labels.ome.tif")

// Define how much to downsample during export (may be required for large images)
double downsample = 1

// Create an ImageServer where the pixels are derived from annotations
def labelServer = new LabeledImageServer.Builder(imageData)
  .backgroundLabel(0, ColorTools.WHITE) // Specify background label (usually 0 or 255)
  .downsample(downsample)    // Choose server resolution; this should match the resolution at which tiles are exported
  .useUniqueLabels()         // Assign labels based on instances, not classifications
  .multichannelOutput(false) // If true, each label refers to the channel of a multichannel binary image (required for multiclass probability)
  .build()

// Write the image
writeImage(labelServer, path)

where I have used .ome.tif as the export format because it handles large images (but .png may be better if your image is small enough).

Note that if your annotations may overlap (and are not too numerous), you might need multichannelOutput(true) instead to preserve this information.

2 Likes

Hi Pete thank you very much! It solved my problem! And now I have a little further question: for example there are 20 Glands, 3 other cells annotated in image, is there any way to export a label map only for Glands, with the label map varying from 0 to 20 (0 background, 1- 20 Gland instance ) ?

3 Likes

Good! And yes – you can include useFilter(Predicate) to restrict the export to specific objects.

For example, if you have classified your gland annotations with the class ‘Gland’, you might use:

// Create an ImageServer where the pixels are derived from annotations
def labelServer = new LabeledImageServer.Builder(imageData)
  .backgroundLabel(0, ColorTools.WHITE) // Specify background label (usually 0 or 255)
  .downsample(downsample)    // Choose server resolution; this should match the resolution at which tiles are exported
  .useUniqueLabels()         // Assign labels based on instances, not classifications
  .multichannelOutput(false) // If true, each label refers to the channel of a multichannel binary image (required for multiclass probability)
  .useFilter({p -> p.getPathClass() == getPathClass('Gland')}) // Accept only objects classified as 'Gland'
  .build()

There are some other built-in filters, such as useCells(). To see a list of options, you can run

def imageData = getCurrentImageData()
def labelServer = new LabeledImageServer.Builder(imageData)
println describe(labelServer)
3 Likes