How to export annotations as a binary mask?

1,687 views
Skip to first unread message

pamf...@gmail.com

unread,
Sep 13, 2017, 3:43:19 PM9/13/17
to QuPath users
I'm using QuPath to create annotations to train a classifier. I was wondering if there is a way to export my annotated areas in the form of a binary mask. I've been trying to do this using groovy scripts but I've had no luck so far. I'd really appreciate any help! Thanks!

Pete

unread,
Sep 13, 2017, 4:00:37 PM9/13/17
to QuPath users
Here's a script that should help:

import static qupath.lib.roi.PathROIToolsAwt.getShape;
import java.awt.image.BufferedImage
import java.awt.Color
import javax.imageio.ImageIO

// Get java.awt.Shape objects for each annotation
def shapes = getAnnotationObjects().collect({getShape(it.getROI())})

// Create a grayscale image, here it's 10% of the full image size
double downsample = 10.0
def server = getCurrentImageData().getServer()
int w = (server.getWidth() / downsample) as int
int h = (server.getHeight() / downsample) as int
def img = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY)

// Paint the shapes (this is just 'standard' Java - you might want to modify)
def g2d = img.createGraphics()
g2d.scale(1.0/downsample, 1.0/downsample)
g2d.setColor(Color.WHITE)
for (shape in shapes)
    g2d.fill(shape)
g2d.dispose()

// Save the result
def outputFile = getQuPath().getDialogHelper().promptToSaveFile("Save binary image", null, null, "PNG", ".png")
ImageIO.write(img, 'PNG', outputFile)


There isn't very much that is QuPath-specific in there - just a few key lines to extract the parts that you need, and then it turns into a Java problem.  For maximum accuracy, you might want to experiment a bit with the painting (e.g. shifting things by half a pixel, or drawing outlines of the shapes in addition to filling them) - in case the default doesn't quite interpret coordinates in the way that you want.

pamf...@gmail.com

unread,
Sep 14, 2017, 7:14:01 AM9/14/17
to QuPath users
This is brilliant, thanks!

Kevin Smith

unread,
Jan 29, 2018, 7:00:02 AM1/29/18
to QuPath users
A small newbie question - could you give an example how this script be modified to get annotations only for a certain class?

Cheers!

Pete

unread,
Jan 29, 2018, 7:05:41 AM1/29/18
to QuPath users
Sure, here 's how you would get annotations classified as 'Tumor' into a separate list:

def tumor = getPathClass('Tumor')
def annotations = getAnnotationObjects()
def tumorAnnotations = annotations.findAll {it.getPathClass() == tumor}

If you prefer to be a bit more explicit and a bit less Groovy (using 'it' instead of giving a variable name, skipping parentheses), the final line could also be

def tumorAnnotations = annotations.findAll({annotation -> annotation.getPathClass() == tumor})

You can then call collect on that list to get the shapes

def shapes = tumorAnnotations.collect {getShape(it.getROI())}


Kevin Smith

unread,
Jan 29, 2018, 2:41:42 PM1/29/18
to QuPath users
Thanks, that's perfect!
Reply all
Reply to author
Forward
0 new messages