QuPath merge polyline annotations?

Hi,

Is there a way to merge (not-overlapping, not-touching) polyline annotations in qupath, like you can do for area annotations ?
my goal is to transfer the polyline annotations together to another consecutive slide where I need to further rotate them together.

I’m using QuPath 0.2.2 . When I select the line annotations and try to merge them, nothing happen.

Otherwise, is there another way to transfer multiple annotations together from slide to slide ?

Thanks
Ofra

Not exactly what you were asking for, but in case there is not a cleaner solution, we edited one of Pete’s scripts into a pair of scripts to transfer objects from one image to many similar images.

Sara’s script here can be used to estimate the alignment from one base image to all other images using the shape of the tissue, while the other script takes all of the objects in the current image and applies that alignment to the objects and then puts them into each other image in the project.

How useful this is will, of course, depend on how similar your images are. Restaining seem to work great. Sequential slices really depend on the slices being very similar.

Thanks @Mike_Nelson ,

I’ll look at the scripts.
Is there a way to get the transformation matrix if I manually transform and rotate one the annotations ?

Ofra

If you manually adjust the images through the Interactive image alignment command, you can copy the transform matrix out of that window and use it, if that is what you are asking. Depending on how complex your project is, you could either directly copy it into the script, or use another script to save a particular transformation as a file, which could then be accessed later.

The first link in my link above contains @petebankhead’s original version of the script, which uses those values from the alignment command.

I have not tried to free-form rotate an annotation within a single image and try to figure out the affine transform between the original annotation position/size and a new annotation. It is probably possible, but not something I have looked into, as our scripts were primarily to increase automation. I suspect the main trick would be figuring out the rotation values.

If you duplicated your image (Project tab), though, and rotated the image such that in the new image your annotations were rotated the way you wanted, you could use the affine transform listed in the Interactive image alignment for the image to rotate the annotations.

1 Like

If you’re using Rotate annotation, you should be able to find this under View → Show log. Something like

INFO: Applied ROI transform: 
 0.804686, -0.593700, 21589.910154,
0.593700, 0.804686, -8502.944219
2 Likes

Ah, nice, so @Ofra_Golani could potentially duplicate one polyline, rotate it as needed, grab the affine transform, delete the duplicated polyline, and then re-write all of the current polylines to the same image using the transform. Sounds like it should work with your script for transferring objects between images, but using the current image as the source image.

===============

Come to think of it, you could leave the image name blank:
def otherImageName = 'type your image name here'
becomes
def otherImageName = null

so that if you wanted to do the transform within an image, replace the null check with:
entry = project.getImageList().find {it.getImageName() == getProjectEntry().getImageName()}

Farther along, the script could then be changed from

if (otherImageName == null) {
    Dialogs.showErrorNotification("Transform objects", "Please specify an image name in the script!")
    return
}

// Get the project & the requested image name
def project = getProject()
def entry = project.getImageList().find {it.getImageName() == otherImageName}
if (entry == null) {
    print 'Could not find image with name ' + otherImageName
    return
}

to

def project = getProject()
def entry = null
if (otherImageName == null) {
    entry = project.getImageList().find {it.getImageName() == getProjectEntry().getImageName()}
}else{

// Get the project & the requested image name

entry = project.getImageList().find {it.getImageName() == otherImageName}
if (entry == null) {
    print 'Could not find image with name ' + otherImageName
    return
}
}

I have not tested, that, but I think the basic ideas should work?

*Edit for clarity and to reorder script lines.

2 Likes

Thanks @Mike_Nelson,

Indeed combining Interactive image alignment with Pete’s script did the job, except for one slide, for which I used manual rotation and took the transformation parameters from View=>Show Log as @petebankhead explained.

Ofra

1 Like