Skip to content

Upgrade OpenSfM and fix pixi-build integration#2053

Open
spwoodcock wants to merge 24 commits into
pixifrom
build/pixi-plus-opensfm
Open

Upgrade OpenSfM and fix pixi-build integration#2053
spwoodcock wants to merge 24 commits into
pixifrom
build/pixi-plus-opensfm

Conversation

@spwoodcock

@spwoodcock spwoodcock commented Jul 17, 2026

Copy link
Copy Markdown
Member

Fixes #2009
Fixes #1745
Fixes OpenDroneMap/OpenSfM#45

This PR

  • I was messing around testing the new pixi branch and thought I would try to pull in the latest changes by Yann to OpenSfM
  • Probably not the wisest decision to bundle these two big changes together, but I plan to run oats with the final image, to see where we get to.
  • I had to make one small tweak to the OpenSfM PR: Small fix for PR #46 OpenSfM#49
  • There were a couple of issues that I think could be cherry-picked into the pixi branch: 1b3f572 2038f0d and 6c47d7f as they seemed more general fixes for the build.
  • The remaining commits were related to integrating the new OpenSfM code into ODM.

I want to make it very clear that this PR is mostly for fun, to see what is possible with the latest OpenSfM, and what breaks. A more thorough attempt should be made to actually integrate this properly. Hopefully the debugging here helps inform that future attemp

Details

  • After the upgrade, the OpenSfM patch was obsolete, deleted.
  • I had to modify osfm.py slightly to make it work with latest OpenSfM.
  • An additional dependency rerun-sdk was required by OpenSfM.
  • I separated out gperftools to be prod-only (not build), else ODM crashed.
  • I had to modify the library paths a bit in pixi.toml to correctly pick up all the built libs at runtime.
  • FPCFilter was pinned to a commit from 3yrs ago - I updated to the latest on https://github.com/OpenDroneMap/FPCFilter (thankfully it had all the fixes to handle PLY headers, made mandatory by the OpenSfM upgrade!)
  • I ran into an error with PoissonRecon's Makefile trying to create a dir at the same time as SuperBuild - an ENOENT from what seemed to be a race condition.

The resulting build

docker build \
  --build-arg IMAGE_VERSION=2026-07-17-latest-opensfm \
  --build-arg GIT_COMMIT="$(git rev-parse HEAD)" \
  --build-arg BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  -t ghcr.io/opendronemap/odm:2026-07-17-latest-opensfm \
  -f Dockerfile .

I have pushed ghcr.io/opendronemap/odm:2026-07-17-latest-opensfm for anyone to test out 🙏

EDIT: damn, I just realised https://github.com/orgs/OpenDroneMap/packages/container/odm/settings is private. If anyone with repo access could make it public, it would be a big help!
EDIT2: I made the image available here for now: ghcr.io/spwoodcock/odm:2026-07-17-latest-opensfm

Testing

A small test to check all the outputs.

I plan to set up a server and run the image through oats next.

I only tested on Linux, via containerd (docker).

As far as I see, everything looks cross platform. The only uncertainty is FPCFilter, which should be test compiled on Windows / Mac to be sure.

Test Data

13 photos captured by a DJI Mini 4 Pro:
https://drive.google.com/drive/folders/1HhH4n2f0qnZJRSrzfM9VdtABhGttCB7a?usp=sharing

Test Command

docker run -it --rm \
-v ./odm-test-full:/datasets \
-v ./odm-test-images:/datasets/project/images \
ghcr.io/opendronemap/odm:2026-07-17-latest-opensfm \
--project-path /datasets project \
--dsm --dtm --pc-quality low --dem-resolution 5 --orthophoto-resolution 5

This ran in about 7 mins or so on my machine - much quicker than I ever remember ODM running!

Outcome

See outputs / logs below for full details.

The numbers all confirm:

  • The offset fix is definitely working. LAZ headers show the exact UTF offsets, with scale 0.001mm precision.
  • All 3 products have the same extent - georeferencing is consistent.
  • Colours are correct: bands are labelled RGB with ColorInterp set right (not swapped).

Outputs / Logs

Ortho

Ortho looks great, correctly georeferenced, accurate colours.

docker run --rm -v /home/sam/odm-test-full:/datasets \
ghcr.io/opendronemap/odm:2026-07-17-latest-opensfm \
gdalinfo -stats /datasets/project/odm_orthophoto/odm_orthophoto.tif
Driver: GTiff/GeoTIFF
Files: /datasets/project/odm_orthophoto/odm_orthophoto.tif
Size is 4689, 2807
Coordinate System is:
PROJCRS["WGS 84 / UTM zone 50S",
    BASEGEOGCRS["WGS 84",
        DATUM["World Geodetic System 1984",
            ELLIPSOID["WGS 84",6378137,298.257223563,
                LENGTHUNIT["metre",1]]],
        PRIMEM["Greenwich",0,
            ANGLEUNIT["degree",0.0174532925199433]],
        ID["EPSG",4326]],
    CONVERSION["UTM zone 50S",
        METHOD["Transverse Mercator",
            ID["EPSG",9807]],
        PARAMETER["Latitude of natural origin",0,
            ANGLEUNIT["degree",0.0174532925199433],
            ID["EPSG",8801]],
        PARAMETER["Longitude of natural origin",117,
            ANGLEUNIT["degree",0.0174532925199433],
            ID["EPSG",8802]],
        PARAMETER["Scale factor at natural origin",0.9996,
            SCALEUNIT["unity",1],
            ID["EPSG",8805]],
        PARAMETER["False easting",500000,
            LENGTHUNIT["metre",1],
            ID["EPSG",8806]],
        PARAMETER["False northing",10000000,
            LENGTHUNIT["metre",1],
            ID["EPSG",8807]]],
    CS[Cartesian,2],
        AXIS["(E)",east,
            ORDER[1],
            LENGTHUNIT["metre",1]],
        AXIS["(N)",north,
            ORDER[2],
            LENGTHUNIT["metre",1]],
    USAGE[
        SCOPE["Navigation and medium accuracy spatial referencing."],
        AREA["Between 114°E and 120°E, southern hemisphere between 80°S and equator, onshore and offshore. Australia. Indonesia."],
        BBOX[-80,114,0,120]],
    ID["EPSG",32750]]
Data axis to CRS axis mapping: 1,2
Origin = (344028.917097095691133,9066480.246484663337469)
Pixel Size = (0.049991640334379,-0.049986134835668)
Metadata:
  TIFFTAG_SOFTWARE=ODM 3.6.0
  TIFFTAG_DATETIME=2024:07:16 09:41:28+00:00
  AREA_OR_POINT=Area
Image Structure Metadata:
  COMPRESSION=DEFLATE
  INTERLEAVE=PIXEL
  PREDICTOR=2
Corner Coordinates:
Upper Left  (  344028.917, 9066480.246) (115d34'59.57"E,  8d26'33.62"S)
Lower Left  (  344028.917, 9066339.935) (115d34'59.55"E,  8d26'38.19"S)
Upper Right (  344263.328, 9066480.246) (115d35' 7.23"E,  8d26'33.65"S)
Lower Right (  344263.328, 9066339.935) (115d35' 7.21"E,  8d26'38.22"S)
Center      (  344146.122, 9066410.091) (115d35' 3.39"E,  8d26'35.92"S)
Band 1 Block=512x512 Type=Byte, ColorInterp=Red
  Description = red
  Minimum=0.000, Maximum=255.000, Mean=113.447, StdDev=47.830
  Mask Flags: PER_DATASET ALPHA
  Metadata:
    STATISTICS_MINIMUM=0
    STATISTICS_MAXIMUM=255
    STATISTICS_MEAN=113.44722580801
    STATISTICS_STDDEV=47.829787482985
    STATISTICS_VALID_PERCENT=95.05
Band 2 Block=512x512 Type=Byte, ColorInterp=Green
  Description = green
  Minimum=0.000, Maximum=255.000, Mean=123.207, StdDev=42.127
  Mask Flags: PER_DATASET ALPHA
  Metadata:
    STATISTICS_MINIMUM=0
    STATISTICS_MAXIMUM=255
    STATISTICS_MEAN=123.20742795254
    STATISTICS_STDDEV=42.12670283853
    STATISTICS_VALID_PERCENT=95.05
Band 3 Block=512x512 Type=Byte, ColorInterp=Blue
  Description = blue
  Minimum=0.000, Maximum=255.000, Mean=81.027, StdDev=48.188
  Mask Flags: PER_DATASET ALPHA
  Metadata:
    STATISTICS_MINIMUM=0
    STATISTICS_MAXIMUM=255
    STATISTICS_MEAN=81.026992890173
    STATISTICS_STDDEV=48.188346416843
    STATISTICS_VALID_PERCENT=95.05
Band 4 Block=512x512 Type=Byte, ColorInterp=Alpha
  Minimum=0.000, Maximum=255.000, Mean=242.384, StdDev=55.298
  Metadata:
    STATISTICS_MINIMUM=0
    STATISTICS_MAXIMUM=255
    STATISTICS_MEAN=242.38422543404
    STATISTICS_STDDEV=55.29796331169
    STATISTICS_VALID_PERCENT=100

DSM

docker run --rm -v /home/sam/odm-test-full:/datasets \
ghcr.io/opendronemap/odm:2026-07-17-latest-opensfm \
gdalinfo -stats /datasets/project/odm_dem/dsm.tif
Driver: GTiff/GeoTIFF
Files: /datasets/project/odm_dem/dsm.tif
Size is 4689, 2806
Coordinate System is:
PROJCRS["WGS 84 / UTM zone 50S",
    BASEGEOGCRS["WGS 84",
        DATUM["World Geodetic System 1984",
            ELLIPSOID["WGS 84",6378137,298.257223563,
                LENGTHUNIT["metre",1]]],
        PRIMEM["Greenwich",0,
            ANGLEUNIT["degree",0.0174532925199433]],
        ID["EPSG",4326]],
    CONVERSION["UTM zone 50S",
        METHOD["Transverse Mercator",
            ID["EPSG",9807]],
        PARAMETER["Latitude of natural origin",0,
            ANGLEUNIT["degree",0.0174532925199433],
            ID["EPSG",8801]],
        PARAMETER["Longitude of natural origin",117,
            ANGLEUNIT["degree",0.0174532925199433],
            ID["EPSG",8802]],
        PARAMETER["Scale factor at natural origin",0.9996,
            SCALEUNIT["unity",1],
            ID["EPSG",8805]],
        PARAMETER["False easting",500000,
            LENGTHUNIT["metre",1],
            ID["EPSG",8806]],
        PARAMETER["False northing",10000000,
            LENGTHUNIT["metre",1],
            ID["EPSG",8807]]],
    CS[Cartesian,2],
        AXIS["(E)",east,
            ORDER[1],
            LENGTHUNIT["metre",1]],
        AXIS["(N)",north,
            ORDER[2],
            LENGTHUNIT["metre",1]],
    USAGE[
        SCOPE["Navigation and medium accuracy spatial referencing."],
        AREA["Between 114°E and 120°E, southern hemisphere between 80°S and equator, onshore and offshore. Australia. Indonesia."],
        BBOX[-80,114,0,120]],
    ID["EPSG",32750]]
Data axis to CRS axis mapping: 1,2
Origin = (344028.916999999957625,9066480.246000001206994)
Pixel Size = (0.050000000000002,-0.050000000000266)
Metadata:
  TIFFTAG_SOFTWARE=ODM 3.6.0
  TIFFTAG_DATETIME=2024:07:16 09:41:28+00:00
  AREA_OR_POINT=Area
Image Structure Metadata:
  COMPRESSION=DEFLATE
  INTERLEAVE=BAND
Corner Coordinates:
Upper Left  (  344028.917, 9066480.246) (115d34'59.57"E,  8d26'33.62"S)
Lower Left  (  344028.917, 9066339.946) (115d34'59.55"E,  8d26'38.19"S)
Upper Right (  344263.367, 9066480.246) (115d35' 7.23"E,  8d26'33.65"S)
Lower Right (  344263.367, 9066339.946) (115d35' 7.21"E,  8d26'38.22"S)
Center      (  344146.142, 9066410.096) (115d35' 3.39"E,  8d26'35.92"S)
Band 1 Block=512x512 Type=Float32, ColorInterp=Gray
  Minimum=213.282, Maximum=246.028, Mean=221.699, StdDev=5.148
  NoData Value=-9999
  Metadata:
    STATISTICS_MINIMUM=213.28199768066
    STATISTICS_MAXIMUM=246.02827453613
    STATISTICS_MEAN=221.69924171436
    STATISTICS_STDDEV=5.1475444897934
    STATISTICS_VALID_PERCENT=95.23

Point Cloud

docker run --rm -v /home/sam/odm-test-full:/datasets \
ghcr.io/opendronemap/odm:2026-07-17-latest-opensfm \
pdal info --summary /datasets/project/odm_georeferencing/odm_georeferenced_model.laz
{
  "file_size": 1798202,
  "filename": "/datasets/project/odm_georeferencing/odm_georeferenced_model.laz",
  "now": "2026-07-17T22:09:54+0000",
  "pdal_version": "2.8.4 (git-version: 156082)",
  "reader": "readers.las",
  "summary":
  {
    "bounds":
    {
      "maxx": 344265.919,
      "maxy": 9066482.425,
      "maxz": 246.034,
      "minx": 344026.567,
      "miny": 9066338.196,
      "minz": 213.271
    },
    "dimensions": "X, Y, Z, Intensity, ReturnNumber, NumberOfReturns, ScanDirectionFlag, EdgeOfFlightLine, Classification, Synthetic, KeyPoint, Withheld, Overlap, ScanAngleRank, UserData, PointSourceId, GpsTime, ScanChannel, Red, Green, Blue",
    "metadata":
    {
      "comp_spatialreference": "PROJCS[\"unknown\",GEOGCS[\"unknown\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",117],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",10000000],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]",
      "compressed": true,
      "copc": false,
      "count": 394446,
      "creation_doy": 198,
      "creation_year": 2026,
      "dataformat_id": 7,
      "dataoffset": 1667,
      "filesource_id": 0,
      "global_encoding": 16,
      "global_encoding_base64": "EAA=",
      "header_size": 375,
      "major_version": 1,
      "maxx": 344265.919,
      "maxy": 9066482.425,
      "maxz": 246.034,
      "minor_version": 4,
      "minx": 344026.567,
      "miny": 9066338.196,
      "minz": 213.271,
      "offset_x": 344148,
      "offset_y": 9066413,
      "offset_z": 0,
      "point_length": 36,
      "project_id": "00000000-0000-0000-0000-000000000000",
      "scale_x": 0.001,
      "scale_y": 0.001,
      "scale_z": 0.001,
      "software_id": "PDAL 2.8.4 (156082)",
      "spatialreference": "PROJCS[\"unknown\",GEOGCS[\"unknown\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",117],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",10000000],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]",
      "srs":
      {
        "compoundwkt": "PROJCS[\"unknown\",GEOGCS[\"unknown\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",117],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",10000000],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]",
        "horizontal": "PROJCS[\"unknown\",GEOGCS[\"unknown\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",117],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",10000000],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]",
        "isgeocentric": false,
        "isgeographic": false,
        "json": {
  "type": "ProjectedCRS",
  "name": "unknown",
  "base_crs": {
    "type": "GeographicCRS",
    "name": "unknown",
    "datum": {
      "type": "GeodeticReferenceFrame",
      "name": "World Geodetic System 1984",
      "ellipsoid": {
        "name": "WGS 84",
        "semi_major_axis": 6378137,
        "inverse_flattening": 298.257223563
      },
      "id": {
        "authority": "EPSG",
        "code": 6326
      }
    },
    "coordinate_system": {
      "subtype": "ellipsoidal",
      "axis": [
        {
          "name": "Longitude",
          "abbreviation": "lon",
          "direction": "east",
          "unit": "degree"
        },
        {
          "name": "Latitude",
          "abbreviation": "lat",
          "direction": "north",
          "unit": "degree"
        }
      ]
    }
  },
  "conversion": {
    "name": "UTM zone 50S",
    "method": {
      "name": "Transverse Mercator",
      "id": {
        "authority": "EPSG",
        "code": 9807
      }
    },
    "parameters": [
      {
        "name": "Latitude of natural origin",
        "value": 0,
        "unit": "degree",
        "id": {
          "authority": "EPSG",
          "code": 8801
        }
      },
      {
        "name": "Longitude of natural origin",
        "value": 117,
        "unit": "degree",
        "id": {
          "authority": "EPSG",
          "code": 8802
        }
      },
      {
        "name": "Scale factor at natural origin",
        "value": 0.9996,
        "unit": "unity",
        "id": {
          "authority": "EPSG",
          "code": 8805
        }
      },
      {
        "name": "False easting",
        "value": 500000,
        "unit": "metre",
        "id": {
          "authority": "EPSG",
          "code": 8806
        }
      },
      {
        "name": "False northing",
        "value": 10000000,
        "unit": "metre",
        "id": {
          "authority": "EPSG",
          "code": 8807
        }
      }
    ],
    "id": {
      "authority": "EPSG",
      "code": 16150
    }
  },
  "coordinate_system": {
    "subtype": "Cartesian",
    "axis": [
      {
        "name": "Easting",
        "abbreviation": "",
        "direction": "east",
        "unit": "metre"
      },
      {
        "name": "Northing",
        "abbreviation": "",
        "direction": "north",
        "unit": "metre"
      }
    ]
  }
},
        "prettycompoundwkt": "PROJCS[\"unknown\",\n    GEOGCS[\"unknown\",\n        DATUM[\"WGS_1984\",\n            SPHEROID[\"WGS 84\",6378137,298.257223563,\n                AUTHORITY[\"EPSG\",\"7030\"]],\n            AUTHORITY[\"EPSG\",\"6326\"]],\n        PRIMEM[\"Greenwich\",0,\n            AUTHORITY[\"EPSG\",\"8901\"]],\n        UNIT[\"degree\",0.0174532925199433,\n            AUTHORITY[\"EPSG\",\"9122\"]]],\n    PROJECTION[\"Transverse_Mercator\"],\n    PARAMETER[\"latitude_of_origin\",0],\n    PARAMETER[\"central_meridian\",117],\n    PARAMETER[\"scale_factor\",0.9996],\n    PARAMETER[\"false_easting\",500000],\n    PARAMETER[\"false_northing\",10000000],\n    UNIT[\"metre\",1,\n        AUTHORITY[\"EPSG\",\"9001\"]],\n    AXIS[\"Easting\",EAST],\n    AXIS[\"Northing\",NORTH]]",
        "prettywkt": "PROJCS[\"unknown\",\n    GEOGCS[\"unknown\",\n        DATUM[\"WGS_1984\",\n            SPHEROID[\"WGS 84\",6378137,298.257223563,\n                AUTHORITY[\"EPSG\",\"7030\"]],\n            AUTHORITY[\"EPSG\",\"6326\"]],\n        PRIMEM[\"Greenwich\",0,\n            AUTHORITY[\"EPSG\",\"8901\"]],\n        UNIT[\"degree\",0.0174532925199433,\n            AUTHORITY[\"EPSG\",\"9122\"]]],\n    PROJECTION[\"Transverse_Mercator\"],\n    PARAMETER[\"latitude_of_origin\",0],\n    PARAMETER[\"central_meridian\",117],\n    PARAMETER[\"scale_factor\",0.9996],\n    PARAMETER[\"false_easting\",500000],\n    PARAMETER[\"false_northing\",10000000],\n    UNIT[\"metre\",1,\n        AUTHORITY[\"EPSG\",\"9001\"]],\n    AXIS[\"Easting\",EAST],\n    AXIS[\"Northing\",NORTH]]",
        "proj4": "+proj=utm +zone=50 +south +datum=WGS84 +units=m +no_defs",
        "units":
        {
          "horizontal": "metre",
          "vertical": ""
        },
        "vertical": "",
        "wkt": "PROJCS[\"unknown\",GEOGCS[\"unknown\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",117],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",10000000],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]"
      },
      "system_id": "PDAL",
      "vlr_0":
      {
        "data": "UFJPSkNTWyJ1bmtub3duIixHRU9HQ1NbInVua25vd24iLERBVFVNWyJXR1NfMTk4NCIsU1BIRVJPSURbIldHUyA4NCIsNjM3ODEzNywyOTguMjU3MjIzNTYzLEFVVEhPUklUWVsiRVBTRyIsIjcwMzAiXV0sQVVUSE9SSVRZWyJFUFNHIiwiNjMyNiJdXSxQUklNRU1bIkdyZWVud2ljaCIsMCxBVVRIT1JJVFlbIkVQU0ciLCI4OTAxIl1dLFVOSVRbImRlZ3JlZSIsMC4wMTc0NTMyOTI1MTk5NDMzLEFVVEhPUklUWVsiRVBTRyIsIjkxMjIiXV1dLFBST0pFQ1RJT05bIlRyYW5zdmVyc2VfTWVyY2F0b3IiXSxQQVJBTUVURVJbImxhdGl0dWRlX29mX29yaWdpbiIsMF0sUEFSQU1FVEVSWyJjZW50cmFsX21lcmlkaWFuIiwxMTddLFBBUkFNRVRFUlsic2NhbGVfZmFjdG9yIiwwLjk5OTZdLFBBUkFNRVRFUlsiZmFsc2VfZWFzdGluZyIsNTAwMDAwXSxQQVJBTUVURVJbImZhbHNlX25vcnRoaW5nIiwxMDAwMDAwMF0sVU5JVFsibWV0cmUiLDEsQVVUSE9SSVRZWyJFUFNHIiwiOTAwMSJdXSxBWElTWyJFYXN0aW5nIixFQVNUXSxBWElTWyJOb3J0aGluZyIsTk9SVEhdXQA=",
        "description": "OGC Transformation Record",
        "record_id": 2112,
        "user_id": "LASF_Projection"
      },
      "vlr_1":
      {
        "data": "UFJPSkNTWyJ1bmtub3duIixHRU9HQ1NbInVua25vd24iLERBVFVNWyJXR1NfMTk4NCIsU1BIRVJPSURbIldHUyA4NCIsNjM3ODEzNywyOTguMjU3MjIzNTYzLEFVVEhPUklUWVsiRVBTRyIsIjcwMzAiXV0sQVVUSE9SSVRZWyJFUFNHIiwiNjMyNiJdXSxQUklNRU1bIkdyZWVud2ljaCIsMCxBVVRIT1JJVFlbIkVQU0ciLCI4OTAxIl1dLFVOSVRbImRlZ3JlZSIsMC4wMTc0NTMyOTI1MTk5NDMzLEFVVEhPUklUWVsiRVBTRyIsIjkxMjIiXV1dLFBST0pFQ1RJT05bIlRyYW5zdmVyc2VfTWVyY2F0b3IiXSxQQVJBTUVURVJbImxhdGl0dWRlX29mX29yaWdpbiIsMF0sUEFSQU1FVEVSWyJjZW50cmFsX21lcmlkaWFuIiwxMTddLFBBUkFNRVRFUlsic2NhbGVfZmFjdG9yIiwwLjk5OTZdLFBBUkFNRVRFUlsiZmFsc2VfZWFzdGluZyIsNTAwMDAwXSxQQVJBTUVURVJbImZhbHNlX25vcnRoaW5nIiwxMDAwMDAwMF0sVU5JVFsibWV0cmUiLDEsQVVUSE9SSVRZWyJFUFNHIiwiOTAwMSJdXSxBWElTWyJFYXN0aW5nIixFQVNUXSxBWElTWyJOb3J0aGluZyIsTk9SVEhdXQA=",
        "description": "OGR variant of OpenGIS WKT SRS",
        "record_id": 2112,
        "user_id": "liblas"
      },
      "vlr_2":
      {
        "data": "AwAAAAMEAwAAAAAAUMMAAP////////////////////8CAAoAHgADAAsABgADAA==",
        "description": "http://laszip.org",
        "record_id": 22204,
        "user_id": "laszip encoded"
      }
    },
    "num_points": 394446,
    "srs":
    {
      "compoundwkt": "PROJCS[\"unknown\",GEOGCS[\"unknown\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",117],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",10000000],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]",
      "horizontal": "PROJCS[\"unknown\",GEOGCS[\"unknown\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",117],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",10000000],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]",
      "isgeocentric": false,
      "isgeographic": false,
      "json": {
  "type": "ProjectedCRS",
  "name": "unknown",
  "base_crs": {
    "type": "GeographicCRS",
    "name": "unknown",
    "datum": {
      "type": "GeodeticReferenceFrame",
      "name": "World Geodetic System 1984",
      "ellipsoid": {
        "name": "WGS 84",
        "semi_major_axis": 6378137,
        "inverse_flattening": 298.257223563
      },
      "id": {
        "authority": "EPSG",
        "code": 6326
      }
    },
    "coordinate_system": {
      "subtype": "ellipsoidal",
      "axis": [
        {
          "name": "Longitude",
          "abbreviation": "lon",
          "direction": "east",
          "unit": "degree"
        },
        {
          "name": "Latitude",
          "abbreviation": "lat",
          "direction": "north",
          "unit": "degree"
        }
      ]
    }
  },
  "conversion": {
    "name": "UTM zone 50S",
    "method": {
      "name": "Transverse Mercator",
      "id": {
        "authority": "EPSG",
        "code": 9807
      }
    },
    "parameters": [
      {
        "name": "Latitude of natural origin",
        "value": 0,
        "unit": "degree",
        "id": {
          "authority": "EPSG",
          "code": 8801
        }
      },
      {
        "name": "Longitude of natural origin",
        "value": 117,
        "unit": "degree",
        "id": {
          "authority": "EPSG",
          "code": 8802
        }
      },
      {
        "name": "Scale factor at natural origin",
        "value": 0.9996,
        "unit": "unity",
        "id": {
          "authority": "EPSG",
          "code": 8805
        }
      },
      {
        "name": "False easting",
        "value": 500000,
        "unit": "metre",
        "id": {
          "authority": "EPSG",
          "code": 8806
        }
      },
      {
        "name": "False northing",
        "value": 10000000,
        "unit": "metre",
        "id": {
          "authority": "EPSG",
          "code": 8807
        }
      }
    ],
    "id": {
      "authority": "EPSG",
      "code": 16150
    }
  },
  "coordinate_system": {
    "subtype": "Cartesian",
    "axis": [
      {
        "name": "Easting",
        "abbreviation": "",
        "direction": "east",
        "unit": "metre"
      },
      {
        "name": "Northing",
        "abbreviation": "",
        "direction": "north",
        "unit": "metre"
      }
    ]
  }
},
      "prettycompoundwkt": "PROJCS[\"unknown\",\n    GEOGCS[\"unknown\",\n        DATUM[\"WGS_1984\",\n            SPHEROID[\"WGS 84\",6378137,298.257223563,\n                AUTHORITY[\"EPSG\",\"7030\"]],\n            AUTHORITY[\"EPSG\",\"6326\"]],\n        PRIMEM[\"Greenwich\",0,\n            AUTHORITY[\"EPSG\",\"8901\"]],\n        UNIT[\"degree\",0.0174532925199433,\n            AUTHORITY[\"EPSG\",\"9122\"]]],\n    PROJECTION[\"Transverse_Mercator\"],\n    PARAMETER[\"latitude_of_origin\",0],\n    PARAMETER[\"central_meridian\",117],\n    PARAMETER[\"scale_factor\",0.9996],\n    PARAMETER[\"false_easting\",500000],\n    PARAMETER[\"false_northing\",10000000],\n    UNIT[\"metre\",1,\n        AUTHORITY[\"EPSG\",\"9001\"]],\n    AXIS[\"Easting\",EAST],\n    AXIS[\"Northing\",NORTH]]",
      "prettywkt": "PROJCS[\"unknown\",\n    GEOGCS[\"unknown\",\n        DATUM[\"WGS_1984\",\n            SPHEROID[\"WGS 84\",6378137,298.257223563,\n                AUTHORITY[\"EPSG\",\"7030\"]],\n            AUTHORITY[\"EPSG\",\"6326\"]],\n        PRIMEM[\"Greenwich\",0,\n            AUTHORITY[\"EPSG\",\"8901\"]],\n        UNIT[\"degree\",0.0174532925199433,\n            AUTHORITY[\"EPSG\",\"9122\"]]],\n    PROJECTION[\"Transverse_Mercator\"],\n    PARAMETER[\"latitude_of_origin\",0],\n    PARAMETER[\"central_meridian\",117],\n    PARAMETER[\"scale_factor\",0.9996],\n    PARAMETER[\"false_easting\",500000],\n    PARAMETER[\"false_northing\",10000000],\n    UNIT[\"metre\",1,\n        AUTHORITY[\"EPSG\",\"9001\"]],\n    AXIS[\"Easting\",EAST],\n    AXIS[\"Northing\",NORTH]]",
      "proj4": "+proj=utm +zone=50 +south +datum=WGS84 +units=m +no_defs",
      "units":
      {
        "horizontal": "metre",
        "vertical": ""
      },
      "vertical": "",
      "wkt": "PROJCS[\"unknown\",GEOGCS[\"unknown\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",117],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",10000000],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]]"
    }
  }
}

@spwoodcock
spwoodcock requested a review from MJohnson459 July 17, 2026 23:06
@spwoodcock spwoodcock self-assigned this Jul 17, 2026
@spwoodcock

spwoodcock commented Jul 18, 2026

Copy link
Copy Markdown
Member Author

Doh, I didn't see this announcement!

https://community.opendronemap.org/t/opensfm-1-0/26803

I'll update OpenSfM used in this PR and in the image 😅

EDIT: results from the ghcr.io/opendronemap/odm:2026-07-17-latest-opensfm image not based on the latest OpenSfM, but on the PR made by Yann a while back attached.
oats-opensfm-latest.txt
Seems to fail step 6 consistently, and step 3 intermittently. I won't spend time on it though, as moving onto v1 integration.

@spwoodcock

spwoodcock commented Jul 19, 2026

Copy link
Copy Markdown
Member Author
  • I pulled in the changes from the official OpenSfM fork (v1 release).
  • Had to make some tweaks to bundle additional requires dependencies, plus make the ODM code compatible with the latest OpenSfM.

Built a new image:

docker build \
  --build-arg IMAGE_VERSION=2026-07-18-opensfm-v1 \
  --build-arg GIT_COMMIT="$(git rev-parse HEAD)" \
  --build-arg BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  -t ghcr.io/opendronemap/odm:2026-07-18-opensfm-v1 \
  -f Dockerfile .

Now we have these for testing:

ghcr.io/opendronemap/odm:2026-07-18-opensfm-v1
ghcr.io/spwoodcock/odm:2026-07-18-opensfm-v1 (temp, until we decide on gchr or not for ODM)


docker run -it --rm \
-v ./odm-test-full:/datasets \
-v ./odm-test-images:/datasets/project/images \
ghcr.io/opendronemap/odm:2026-07-18-opensfm-v1 \
--project-path /datasets project \
--dsm --dtm --pc-quality low --dem-resolution 5 --orthophoto-resolution 5

Running the oats test suite overnight.

@DodgySpaniard

Copy link
Copy Markdown
Member

@spwoodcock, I am not sure you are fully aware of where you are getting into :)

We hold our own custom copy of OpenSfM; it is not a matter of just "picking the latest" OpenSfM: OpenSfM. The process would be to sync our ODM:OpenSfM fork with OpenSfM:OpenSfM (which is [260 commits ahead of] and [290 commits behind] mapillary/OpenSfM:main)

Now of those 260 commits, I reckon for a quick overview that around 200 are no longer needed (either were patches on OpenSfM, or no longer relevant), that still leaves several dozen commits that need to be evaluated and decided what to do with. Granted that many are glue code, but I see some actual CV features there.

Bringing OpenSfM:OpenSfM-v1.0 is absolutely valuable, apart from those 290 commits on Mapillary, it includes the latest efforts from Yann over the last year.

Knowing all this, please note that there is no shame in handing it over to me; I'll be happy to tackle this beast.

cc @smathermather

@spwoodcock

spwoodcock commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

oats output:
opensfm-v1-latest-oats-log.txt

Logs from tag 3.6.0 vs opensfm-v1-latest:
results.zip

EDIT: I noticed these were clobbered with old old runs & some resumed from previous outputs... rerunning oats with --clean! And with the new build including the commit below for handling filenames with spaces ghcr.io/spwoodcock/odm:2026-07-23-opensfm-v1

@spwoodcock

Copy link
Copy Markdown
Member Author

@spwoodcock, I am not sure you are fully aware of where you are getting into :)

We hold our own custom copy of OpenSfM; it is not a matter of just "picking the latest" OpenSfM: OpenSfM. The process would be to sync our ODM:OpenSfM fork with OpenSfM:OpenSfM (which is [260 commits ahead of] and [290 commits behind] mapillary/OpenSfM:main)

Now of those 260 commits, I reckon for a quick overview that around 200 are no longer needed (either were patches on OpenSfM, or no longer relevant), that still leaves several dozen commits that need to be evaluated and decided what to do with. Granted that many are glue code, but I see some actual CV features there.

Bringing OpenSfM:OpenSfM-v1.0 is absolutely valuable, apart from those 290 commits on Mapillary, it includes the latest efforts from Yann over the last year.

Knowing all this, please note that there is no shame in handing it over to me; I'll be happy to tackle this beast.

cc @smathermather

Thank you!!

You are totally right that this was an underestimation from the start.

I thought I would just have a mess around with the latest OpenSfM, but as you say, there are quite a few more custom patches to be added to play nicely with the existing OpenSfM code =)

Hopefully some of this work is helpful somewhere for the pixi integration or OpenSfM upgrade. But other than that, I'm more that happy for this to be closed and superseded 😁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants