Passing different output projections to ODM, eg a `–proj` flag?

Hello all,

When processing imagery with PyODM (ODM), the resulting orthophoto TIFF file is output with EPSG:32645 by default. However, for web visualization using Maplibre or similar tools, EPSG:3857 is required. While this can be converted manually using GDAL, it would be more efficient if ODM could directly support the option to output the orthophoto in a different projection.

Is it possible to add a --proj flag in ODM that would allow users to specify the desired output projection (e.g., --proj 3857) during processing?

+1

i also have to transform the orthophoto to EPSG:3857 every time to visualize it.
I’m about to create another Docker process that starts after my ODM container and reprojects the result via GDAL.
But it would be nicer if ODM could reproject it to another coordinatesystem itself.

I have been digging around forum posts and Github code to find a good answer to this.

Here is what I believe to be the status of reprojection capabilities in various places, as of Nov 2024 (please correct me if I’m wrong! :pray:):

Input: Processing Imagery

Input: Ground Control Points

Output: Reprojection of the Final Data

  • Output of data (orthomosaic, ±point clouds?) in formats other than UTM was removed a long time ago --proj property removed from recent version (0.9.1)
  • It is still the case for ODM CLI and NodeODM I believe, although it is currently possible to output non web-optimised COG format via the --cog flag (still in UTM).
  • WebODM has some additional capabilities built on top, and allows for output of web-optimised COG, which means the file is reprojected to EPSG:3857 as a result, and the internal tiling is aligned with the web mercator grid (less tile fetching via web maps).
  • So in summary it seems that output in EPSG:3857 is possible via the WebODM app, otherwise UTM is the only option via CLI / NodeODM.

Workflows Using COG

  • We are developing a workflow that uses COG to preview captured imagery, in addition to tagging GCP points on the captured imagery.
  • We need to use NodeODM for processing, so output of web optimised COG is not an option yet.
  • As of now, the only workflow I can think of it:
    • Capture imagery, use gdal_translate to convert to EPSG:3857 web optimised COG.
    • View the imagery via web browser, including tagging of GCP points etc.
    • Once all imagery is captured and ready to process alongside the GCPs, then all images must be gdal_translated back to UTM first.
  • I’m not a huge fan of this approach! Reprojection of data is not a perfect process and does have minor inaccuracies. Ideally we want to keep the source data in the projection it was captured in. We have a tradeoff:
    • Either we keep multiple copies of the imagery in different projections.
    • Or we reproject, visualise and gather the data we need, then reproject back.

Contribution

  • As I said, please correct any mistakes I have made here! (I’m reasonably new to the ODM world).
  • If there are any gaps that could be filled to help improve the workflow for ourselves and the community, then we* would love to contribute them.
  • First we should clarify: (1) what is missing (2) what is desired by the community (3) what we can technically achieve.

*by ‘we’, I mean the teams at HOTOSM + NAXA, as we are hugely grateful for the work done on ODM, which entirely underpins our work on DroneTM.

cc @Ivan_Gayton

You can certainly use NodeODM for generating COGs. Just pass --cog. cog — OpenDroneMap 3.5.4 documentation

I was digging into the code and as far as I can tell it’s not possible to generate web optimised COGs via NodeODM. Am I wrong here?

I think only WebODM supports that?

Ah, no there’s (currently) no way to reproject to 3857. I suspect you might gain some performance improvement for serving web tiles if you did, but it’s difficult to say how much. WebODM serves the tiles from UTM (via rio-tiler) and works reasonably fast, but perhaps your requirements are different.

It was useful for me to go through the docs and write up the post above.

On reflection, it seems this is very use case dependent:

  • For quick processing and visualisation, it might be useful to allow reprojection to web optimised COG in EPSG:3857 via ODM CLI / PyODM / NodeODM.
  • However, for most cases I would argue that generating the final output in anything other than UTM is introducing unnecessary error. Its down to the user if they wish to produce a reprojected copy for another use case. Perhaps it might be nice if ODM gave the option to provide both the original UTM and a reprojected EPSG:3857 COG for visualisation?

So with this in mind:

  1. Adding the --proj flag back in for output might be quite tricky, due to inconsistencies and difficulty projecting to many different CRS, as mentioned in a few places However, some PRs could be made to add web optimised EPSG:3857 output as an option for ODM CLI / PyODM / NodeODM, if the community feels this is worthwhile / needed.

  2. Adding a --proj flag for input has been discussed before, and is a pretty niche use case (e.g. polar mapping). We could pick up where the thread left off off in the future if needed, but it’s not high priority for now.

Also @pierotofy, having a EPSG:3857 COG isn’t so much a matter of performance, but compatibility. Some web libraries like OpenLayers have excellent reprojection support (on-the-fly), while others do not support this (e.g. MapLibre).

Note, when I bring these tifs into QGIS, I get this warning:

Coordinate Reference System (CRS)
Name EPSG:32615 - WGS 84 / UTM zone 15N
Units meters
Type Projected
Method Universal Transverse Mercator (UTM)
Celestial Body Earth
Accuracy Based on World Geodetic System 1984 ensemble (EPSG:6326), which has a limited accuracy of at best 2 meters.
Reference Dynamic (relies on a datum which is not plate-fixed)

I’ve just started building a pipeline and will try and use gdal to do the conversions as follows (https://gdal.org/en/latest/api/python/utilities.html):

  1. Convert from UTM to local County coordinate system via osgeo.gdal.Translate
  2. Scale meters to feet via osgeo.gdal.Warp

Is it advisable to make a separate stage using gdal dependency? It looks li there’s a simple API to hook into. The difficulty with gdal is mostly getting the library to compile and while it’s available in linux, I’ve never used any windows stuff: Download — GDAL documentation

Not sure if this was posted in the wrong thread :sweat_smile: