Exchanging annotations

Exchanging image annotations

I’m hoping for some advice about exchanging image annotations. Are there any community standards that are currently used in the bio-imaging community?

E.g. if I added a feature to Orbit that allowed for outputting image annotations, is there a format, or set of formats that other tools can then use to import the annotations without the need for overly complex data reshaping?

The most relevant thing that I could find is perhaps some of the formats for working with annotating images for the typical deep learning tools, e.g. Image Labelling Formats Article or Image Labelling Tools

Thanks in advance.


A few discussions, I think, but I am not sure of any conclusions.

Hi @jfkotw, in QuPath we increasingly use GeoJSON – the spec is at https://tools.ietf.org/html/rfc7946

I find this gives us most of what we need, including the ability to add measurements/features as extra properties. There are a few things missing (e.g. support for ellipses) but in general I think it works quite well.

You can generate specific examples from QuPath by running the script here: Exporting annotations — QuPath 0.2.3 documentation
The main thing is that a QuPath object is a GeoJSON Feature and a ROI is a Geometry. We use coordinates in pixel units by default, with (0,0) the top left of the image.

We are planning to add export to GeoJSON as a menu item in a future release and use it even more often. I think it would be great if Orbit had the same approach so we could use it for exchange.


Thanks both for the heads up. I just had a discussion with @mstritt and @bruno and we also figured that we should copy the QuPath export format. It’s great to hear that you’re thinking of adding the GeoJSON export option. In which case we’ll look into adding GeoJSON import/export functionality into Orbit.


Excellent! Let me know if you want to discuss any of the extra properties, in case we can agree on these beyond what the specification dictates. There are probably a few cases where we have chosen something that is too qupath-specific.

For example, there is an optional "id" property that isn’t very clearly defined in the spec. If I export a rectangle in QuPath I see something like this:

    "type": "Feature",
    "id": "PathAnnotationObject",
    "geometry": {
      "type": "Polygon",
      "coordinates": [
          [49495, 22857],
          [49495, 23404],
          [50042, 23404],
          [50042, 22857],
          [49495, 22857]
    "properties": {
      "isLocked": false,
      "measurements": []

I strongly suspect we’re using "id" badly there to store the type of object (an annotation as opposed to a cell, for example), and it should instead be reserved for a unique ID (e.g. UUID) and we include the type information as a property. We should probably revisit that on our side.


Thanks for the information Pete. I had an initial look into things on our side and ran into a few walls when looking at JTS compatibility with Jackson which didn’t give me a warm fuzzy feeling. I noticed that you’re using GSON here, which I’d like to avoid since it’s much more hassle to use together with Spring Boot which we’re likely to use for some internal projects.

Did you also attempt to use Jackson together with JTS/GeoJSON? Or has GSON always been the preferred JSON serialization tool in QuPath?

GSON has always been the preferred option in QuPath, although I’ve seen Jackson can have some advantages over it.

Our serialization code is at qupath/ROITypeAdapters.java at 43aad4ecda893a7eb03c30774e64da5b9547bc86 · qupath/qupath · GitHub

That was easier than using JTS’s GeoJsonWriter, since its dependency on json-simple was causing a lot of trouble. Because a Geometry in JTS is such a close match to a GeoJSON representation already, my guess is that the approach of creating your own writer with Jackson might also be the easier option.

(The much more painful step for us was creating valid JTS Geometry objects in the first place from our previous ROI representation – there’s some more info here…)

1 Like