How to import image segments created in Imagej into QuPath

Hello experts,
I’m using weka trainable segmentation via script to segment glioblastoma images into different segments. An example is like below:

I would like to bring this segmentation as annotation in QuPath. There are 8 different types of segments in this case. The pixel values in the tif image are from 0 to 7 (for 8 classes) and rendered using goldenLUT. I tried using the code in the link https://forum.image.sc/t/qupath-0-2-0m11-updated-import-masks-as-annotations-script/37427 post but am not able to find the right way to use the ThresholdToSelection class.

My assumption was I should use minThreshold=0, maxThreshold=0.5 to get the first segment, minThreshold=1, maxThreshold=1.5 to get the second segment, etc. But with these parameters the roi object comes out null.

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.Graphics;

import ij.plugin.filter.ThresholdToSelection;
import ij.process.ByteProcessor;
import ij.process.ImageProcessor;

import qupath.lib.roi.ROIs;
import static qupath.lib.gui.scripting.QPEx.*

def getProperBufferedImage(img){
    BufferedImage result = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
    Graphics g = result.getGraphics();
    g.drawImage(img, 0, 0, null);
    g.dispose();
    return result;
}


segmented_output_folder = '/media/DSRG4new/Darshat/training/Patient1/Downscale3/Postprocess3/';
File segimg = new File(segmented_output_folder + 'training_sigma5_10_output-0008.tif');

def img = ImageIO.read(segimg);
img = getProperBufferedImage(img);
def bp = new ByteProcessor(img);
bp.setThreshold(0,0.5,ImageProcessor.NO_LUT_UPDATE);
def roiIJ = new ThresholdToSelection().convert(bp);

Looking for some help to get this right…feel like I’m shooting in the dark a bit with LUT and colormodels. Thanks in advance!
Darshat

Indeed color models can be quite painful… I’d suggest first trying to read the tiff to ImageJ directly so as to avoid travelling through BufferedImages in case something is being lost there. You can use IJ.openImage(String) instead.

Something like this (untested…):

def imp = ij.IJ.openImage(segimg.getAbsolutePath())
def bp = imp.getProcessor()

Apart from that ThresholdToSelection looks fine – although you may need to take extra care for any case where this shouldn’t detect anything (I can’t remember if it always returns null in such cases).

There is some ROI-tracing code using ThresholdToSelection within QuPath here, but it’s a bit awkward too (it requires knowing the number of ROIs to trace, and attempts to create a polygon first – only resorting to a more complex shape if needed), so writing your own may still be preferable.

Sidenote: v0.3.0 will have entirely new code for tracing contours to try to avoid these troubles in the future…

2 Likes

That worked fantastic @petebankhead ! Thanks much - I’d never have figured it out otherwise.

1 Like