Exporting while preserving resolution?

Thank you for all your helps in the past, we’re able to export corresponding pathology image and the classification map within a specified region of interest.

I’ve been manually guessing the resolution value for “requestedPixelSize” in the code below. Sometimes 0.3 seems to work, sometimes 0.2 seems to work, and it doesn’t work at 0.1.

Is there an automatic way to detect the value for “requestedPixelSize” so that our exported image does not lose resolution?

Code below:

/**
 * Script to export binary masks corresponding to all annotations of an image,
 * optionally along with extracted image regions.
 *
 * Note: Pay attention to the 'downsample' value to control the export resolution!
 *
 * @author Pete Bankhead
 */

import qupath.lib.images.servers.ImageServer
import qupath.lib.objects.PathObject
import qupath.lib.images.servers.LabeledImageServer

import javax.imageio.ImageIO
import java.awt.Color
import java.awt.image.BufferedImage

// Get the main QuPath data structures
def imageData = getCurrentImageData()
def hierarchy = imageData.getHierarchy()
def server = imageData.getServer()

// Request all objects from the hierarchy & filter only the annotations
def annotations = hierarchy.getAnnotationObjects()

// Define downsample value for export resolution & output directory, creating directory if necessary
// Define output resolution
double requestedPixelSize = 0.3

// Convert to downsample
double downsample = requestedPixelSize / imageData.getServer().getPixelCalibration().getAveragedPixelSize()
def pathOutput = buildFilePath('PATH', 'masks')
mkdirs(pathOutput)

// Define image export type; valid values are JPG, PNG or null (if no image region should be exported with the mask)
// Note: masks will always be exported as PNG
def imageExportType = 'TIF'


// 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
    .addLabel('Region*', 1)      // Choose output labels (the order matters!)
    .addLabel('Fibrotic tumor', 2)
    .addLabel('Inflamed tumor', 3)
    .addLabel('Epidermal tumor', 4)
    .addLabel('Uncertain Tumor', 5)
    .addLabel('Tumor', 6)
//    .lineThickness(0)          // Optionally export annotation boundaries with another label
//    .setBoundaryLabel('Boundary*', 7) // Define annotation boundary label
    .multichannelOutput(false) // If true, each label refers to the channel of a multichannel binary image (required for multiclass probability)
    .build()


// Export each region
int i = 0
for (annotation in getAnnotationObjects().findAll {it.getPathClass() == getPathClass("Region*")}) {
    def region = RegionRequest.createInstance(
        labelServer.getPath(), downsample, annotation.getROI())
        // Create a name
    def name = 'path img'
    def img = server.readBufferedImage(region)    
    i++
    def outputPath = buildFilePath(pathOutput, 'annotation.tif')
    writeImageRegion(labelServer, region, outputPath)
    if (imageExportType != null) {
        def fileImage = new File(pathOutput, name + '.' + imageExportType.toLowerCase())
        ImageIO.write(img, imageExportType, fileImage)
    }
}

Thank you for your help

Hi @Mike1, if you want to export at the full resolution then just replace

// Define downsample value for export resolution & output directory, creating directory if necessary
// Define output resolution
double requestedPixelSize = 0.3

// Convert to downsample
double downsample = requestedPixelSize / imageData.getServer().getPixelCalibration().getAveragedPixelSize()

with

// Export at full resolution
double downsample = 1.0
1 Like

Thank you very much!

Mike