Automatic detection of tissue sections using rectangular ROIs (fixed-size/orientation)

I’m interested in selecting tissue sections automatically using a pre-set rectangular ROI (ie. fixed size)… Would this be possible using QuPath or Orbit? I’m new to these platforms and haven’t come across a solution thus far… or is there another platform that might do the trick?

I have slides with 30+ tissue sections that all need to be automatically selected/cropped/saved-individually to then later register as a stack. So ideally - the rectangular ROI placed over them would be the same size for all tissue sections and the same orientation - facilitating registration later on.

Any help in this would be much appreciated!

Dear @etadobson,

for Orbit:

Fixed size ROIs can be defined as follows:
In the annotation tool (right side) first select Options -> Set Fixed Rectangle Size (1) and then draw a rectangle (2) which then will have the fixed size (size is in pixels):

Then you have to select the annotation and click on the pencil button to define it as ROI.

To extract images per ROI you would have to write a script, see examples here.

You also might have a look in the TMA/Grid ROI annotator tool (ROI -> TMA/Grid).



The corresponding QuPath command is Objects → Annotations… → Specify annotation. You can then double-click on the rectangle and shift it into position if needed.

However, this won’t include automatic detection of the tissue. To do that, you’d need to apply thresholding, pixel classification, or use a custom ImageJ method:

Choose whichever method you prefer to create the annotation

You can then export the region as described at

For example, if you have a single annotation you might use a script like this:

def roi = getAnnotationObjects()[0].getROI()
double downsample = 1.0
def requestROI = RegionRequest.createInstance(server.getPath(), downsample, roi)
writeImageRegion(server, requestROI, '/path/to/export/region.ome.tif')

where downsample determines the export resolution.

This doesn’t enforce the fixed size… although that’s certainly possible too, if really needed. I haven’t tested the following script, but it should at least show roughly the idea:

int width = 10000
int height = 5000
double downsample = 1.0
def roi = getSelectedROI()
def requestROI = RegionRequest.createInstance(server.getPath(), downsample,
    roi.getCentroidX()-width/2 as int, roi.getCentroidY()-height/2 as int, width, height, roi.getZ(), roi.getT())
writeImageRegion(server, requestROI, '/path/to/export/region.tif')

However, I suspect that cropping after export might be a better way to go than enforcing the size in the script.


Thank you both @petebankhead and @mstritt for your replies!!! You’ve given me a lot to start with… I will check back if I have more specific questions.

Seriously - thank you! :slight_smile:

1 Like