From eb6ab9a802a2ca0414aff8953c22c9b8744f730b Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Thu, 9 Apr 2026 16:13:16 -0400 Subject: [PATCH 01/29] Cleanup, sync repos, bring latest changes, fix incorrect merges --- ...ild_vcpkg_env.yaml => build-vcpkg-env.yml} | 0 ...docker-gpu.yaml => publish-docker-gpu.yml} | 0 .github/workflows/publish-docker.yaml | 53 ---- .github/workflows/publish-docker.yml | 108 ++++++++ .github/workflows/publish-windows.yml | 15 +- ...test-build-prs.yaml => test-build-prs.yml} | 24 -- SuperBuild/CMakeLists.txt | 38 ++- SuperBuild/cmake/External-Ceres.cmake | 2 +- SuperBuild/cmake/External-Entwine.cmake | 4 +- SuperBuild/cmake/External-ExifTool.cmake | 2 +- SuperBuild/cmake/External-FPCFilter.cmake | 5 +- SuperBuild/cmake/External-GDAL.cmake | 31 --- SuperBuild/cmake/External-Hexer.cmake | 27 -- SuperBuild/cmake/External-MvsTexturing.cmake | 4 +- SuperBuild/cmake/External-Obj2Tiles.cmake | 2 +- SuperBuild/cmake/External-OpenCV.cmake | 4 +- SuperBuild/cmake/External-OpenMVS.cmake | 8 +- SuperBuild/cmake/External-OpenSfM.cmake | 4 +- SuperBuild/cmake/External-PDAL.cmake | 2 +- SuperBuild/cmake/External-PyPopsift.cmake | 36 --- SuperBuild/cmake/External-RenderDEM.cmake | 4 +- VERSION | 2 +- configure.sh | 235 ++++++++++-------- licenses/license.md | 9 +- opendm/gpu.py | 12 - requirements.txt | 8 +- run.py | 44 +--- snap/snapcraft.yaml | 215 ---------------- snap/snapcraft21.yaml | 217 ---------------- snap/snapcraft24.yaml | 227 ----------------- stages/odm_app.py | 2 +- 31 files changed, 292 insertions(+), 1052 deletions(-) rename .github/workflows/{build_vcpkg_env.yaml => build-vcpkg-env.yml} (100%) rename .github/workflows/{publish-docker-gpu.yaml => publish-docker-gpu.yml} (100%) delete mode 100644 .github/workflows/publish-docker.yaml create mode 100644 .github/workflows/publish-docker.yml rename .github/workflows/{test-build-prs.yaml => test-build-prs.yml} (70%) delete mode 100644 SuperBuild/cmake/External-GDAL.cmake delete mode 100644 SuperBuild/cmake/External-Hexer.cmake delete mode 100644 SuperBuild/cmake/External-PyPopsift.cmake delete mode 100644 snap/snapcraft.yaml delete mode 100644 snap/snapcraft21.yaml delete mode 100644 snap/snapcraft24.yaml diff --git a/.github/workflows/build_vcpkg_env.yaml b/.github/workflows/build-vcpkg-env.yml similarity index 100% rename from .github/workflows/build_vcpkg_env.yaml rename to .github/workflows/build-vcpkg-env.yml diff --git a/.github/workflows/publish-docker-gpu.yaml b/.github/workflows/publish-docker-gpu.yml similarity index 100% rename from .github/workflows/publish-docker-gpu.yaml rename to .github/workflows/publish-docker-gpu.yml diff --git a/.github/workflows/publish-docker.yaml b/.github/workflows/publish-docker.yaml deleted file mode 100644 index 1b8a8a08..00000000 --- a/.github/workflows/publish-docker.yaml +++ /dev/null @@ -1,53 +0,0 @@ -name: Publish Docker and WSL Images - -on: - push: - branches: - - master - tags: - - v* - -jobs: - build: - runs-on: self-hosted - timeout-minutes: 2880 - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Set up QEMU - uses: docker/setup-qemu-action@v1 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v1 - with: - config-inline: | - [worker.oci] - max-parallelism = 1 - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - # Use the repository information of the checked-out code to format docker tags - - name: Docker meta - id: docker_meta - uses: crazy-max/ghaction-docker-meta@v1 - with: - images: webodm/odm - tag-semver: | - {{version}} - - name: Build and push Docker image - id: docker_build - uses: docker/build-push-action@v2 - with: - file: ./portable.Dockerfile - platforms: linux/amd64,linux/arm64 - push: true - no-cache: true - tags: | - ${{ steps.docker_meta.outputs.tags }} - webodm/odm:latest - # Trigger NodeODM build - - name: Dispatch NodeODM Build Event - id: nodeodm_dispatch - run: | - curl -X POST -u "${{secrets.PAT_USERNAME}}:${{secrets.PAT_TOKEN}}" -H "Accept: application/vnd.github.everest-preview+json" -H "Content-Type: application/json" https://api.github.com/repos/WebODM/NodeODM/actions/workflows/publish-docker.yaml/dispatches --data '{"ref": "master"}' \ No newline at end of file diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml new file mode 100644 index 00000000..d06ce3be --- /dev/null +++ b/.github/workflows/publish-docker.yml @@ -0,0 +1,108 @@ +name: Publish Docker + +on: + push: + branches: + - master + tags: + - v* + workflow_dispatch: +jobs: + build-amd64: + runs-on: ubuntu-latest + timeout-minutes: 1440 + steps: + - name: Checkout + uses: actions/checkout@v5 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + config-inline: | + [worker.oci] + max-parallelism = 1 + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Docker meta + id: docker_meta + uses: crazy-max/ghaction-docker-meta@v1 + with: + images: webodm/odm + tag-semver: | + {{version}} + - name: Set Swap Space + uses: pierotofy/set-swap-space@master + with: + swap-size-gb: 10 + - name: Build and push Docker image (AMD64) + id: docker_build_amd64 + uses: docker/build-push-action@v6 + with: + context: . + file: ./portable.Dockerfile + platforms: linux/amd64 + push: true + no-cache: true + tags: | + webodm/odm:latest-amd64 + provenance: false + build-arm64: + runs-on: ubuntu-24.04-arm + timeout-minutes: 1440 + steps: + - name: Checkout + uses: actions/checkout@v5 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + config-inline: | + [worker.oci] + max-parallelism = 1 + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Set Swap Space + uses: pierotofy/set-swap-space@master + with: + swap-size-gb: 10 + - name: Build and push Docker image (ARM64) + id: docker_build_arm64 + uses: docker/build-push-action@v6 + with: + context: . + file: ./portable.Dockerfile + platforms: linux/arm64 + push: true + no-cache: true + tags: | + webodm/odm:latest-arm64 + provenance: false + + create-manifest: + runs-on: ubuntu-latest + needs: [build-amd64, build-arm64] + steps: + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Create and push multi-platform manifest + run: | + docker pull --platform linux/amd64 webodm/odm:latest-amd64 + docker pull --platform linux/arm64 webodm/odm:latest-arm64 + docker manifest create webodm/odm:latest \ + webodm/odm:latest-amd64 \ + webodm/odm:latest-arm64 + docker manifest push webodm/odm:latest + + # Trigger NodeODM build, OATS test + - name: Dispatch Build Event + id: build_dispatch + run: | + curl -X POST -u "${{secrets.PAT_USERNAME}}:${{secrets.PAT_TOKEN}}" -H "Accept: application/vnd.github.everest-preview+json" -H "Content-Type: application/json" https://api.github.com/repos/WebODM/NodeODM/actions/workflows/publish-docker.yaml/dispatches --data '{"ref": "master"}' + curl -X POST -u "${{secrets.PAT_USERNAME}}:${{secrets.PAT_TOKEN}}" -H "Accept: application/vnd.github.everest-preview+json" -H "Content-Type: application/json" https://api.github.com/repos/WebODM/oats/actions/workflows/test.yaml/dispatches --data '{"ref": "master"}' \ No newline at end of file diff --git a/.github/workflows/publish-windows.yml b/.github/workflows/publish-windows.yml index 02fcd247..1d15d980 100644 --- a/.github/workflows/publish-windows.yml +++ b/.github/workflows/publish-windows.yml @@ -14,7 +14,6 @@ permissions: jobs: build: runs-on: windows-2022 - environment: azuresigning steps: - name: Checkout uses: actions/checkout@v2 @@ -42,21 +41,9 @@ jobs: rmdir SuperBuild\download /s /q rmdir SuperBuild\build /s /q shell: cmd - - name: Retrieve the metadata and decode it to a file - env: - AZURESIGNING_METADATA: ${{ secrets.AZURESIGNING_METADATA }} - run: | - echo $AZURESIGNING_METADATA | base64 --decode > "$RUNNER_TEMP\metadata.json" - shell: bash - - name: Azure login - uses: azure/login@v1 - with: - client-id: ${{ secrets.AZURE_CLIENT_ID }} - tenant-id: ${{ secrets.AZURE_TENANT_ID }} - subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - name: Create setup run: | - python configure.py dist --signtool-path "C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe" --azure-signing-metadata "%RUNNER_TEMP%\metadata.json" + python configure.py dist shell: cmd - name: Upload Setup File uses: actions/upload-artifact@v4 diff --git a/.github/workflows/test-build-prs.yaml b/.github/workflows/test-build-prs.yml similarity index 70% rename from .github/workflows/test-build-prs.yaml rename to .github/workflows/test-build-prs.yml index 1656ba5c..412ac895 100644 --- a/.github/workflows/test-build-prs.yaml +++ b/.github/workflows/test-build-prs.yml @@ -24,30 +24,6 @@ jobs: platforms: linux/amd64 push: false - # snapcraft: - # runs-on: ubuntu-latest - # strategy: - # matrix: - # architecture: - # - amd64 - # steps: - # - name: Checkout - # uses: actions/checkout@v2 - # - name: Set Swap Space - # uses: pierotofy/set-swap-space@master - # with: - # swap-size-gb: 12 - # - name: Build - # id: build - # uses: diddlesnaps/snapcraft-multiarch-action@v1 - # with: - # architecture: ${{ matrix.architecture }} - # - name: Review - # uses: diddlesnaps/snapcraft-review-tools-action@v1 - # with: - # snap: ${{ steps.build.outputs.snap }} - # isClassic: 'false' - windows: runs-on: windows-2022 steps: diff --git a/SuperBuild/CMakeLists.txt b/SuperBuild/CMakeLists.txt index 39a05805..972877ed 100644 --- a/SuperBuild/CMakeLists.txt +++ b/SuperBuild/CMakeLists.txt @@ -190,7 +190,6 @@ set(custom_libs OpenSfM MvsTexturing OpenMVS FPCFilter - PyPopsift Obj2Tiles OpenPointClass ExifTool @@ -198,8 +197,8 @@ set(custom_libs OpenSfM ) externalproject_add(mve - GIT_REPOSITORY https://github.com/OpenDroneMap/mve.git - GIT_TAG 356 + GIT_REPOSITORY https://github.com/WebODM/mve.git + GIT_TAG 066ff646837ef3f95905af45406391f76d4b266d UPDATE_COMMAND "" SOURCE_DIR ${SB_SOURCE_DIR}/mve CMAKE_ARGS ${WIN32_CMAKE_ARGS} ${APPLE_CMAKE_ARGS} @@ -225,8 +224,8 @@ else() endif() endif() externalproject_add(poissonrecon - GIT_REPOSITORY https://github.com/OpenDroneMap/PoissonRecon.git - GIT_TAG 290 + GIT_REPOSITORY https://github.com/pierotofy/PoissonRecon.git + GIT_TAG 3912 PREFIX ${SB_BINARY_DIR}/PoissonRecon SOURCE_DIR ${SB_SOURCE_DIR}/PoissonRecon UPDATE_COMMAND "" @@ -237,9 +236,8 @@ externalproject_add(poissonrecon ) externalproject_add(dem2mesh - DEPENDS gdal - GIT_REPOSITORY https://github.com/OpenDroneMap/dem2mesh.git - GIT_TAG 334 + GIT_REPOSITORY https://github.com/WebODM/dem2mesh.git + GIT_TAG 623c8536941175c630fabe4f1352ddc314d98120 PREFIX ${SB_BINARY_DIR}/dem2mesh SOURCE_DIR ${SB_SOURCE_DIR}/dem2mesh CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${SB_INSTALL_DIR} @@ -248,8 +246,7 @@ externalproject_add(dem2mesh ) externalproject_add(dem2points - DEPENDS gdal - GIT_REPOSITORY https://github.com/OpenDroneMap/dem2points.git + GIT_REPOSITORY https://github.com/WebODM/dem2points.git GIT_TAG master PREFIX ${SB_BINARY_DIR}/dem2points SOURCE_DIR ${SB_SOURCE_DIR}/dem2points @@ -259,9 +256,9 @@ externalproject_add(dem2points ) externalproject_add(odm_orthophoto - DEPENDS opencv gdal - GIT_REPOSITORY https://github.com/OpenDroneMap/odm_orthophoto.git - GIT_TAG 355 + DEPENDS opencv + GIT_REPOSITORY https://github.com/WebODM/odm_orthophoto.git + GIT_TAG 55b66d87cc168b8ab287bf10e81d4da0890f84f1 PREFIX ${SB_BINARY_DIR}/odm_orthophoto SOURCE_DIR ${SB_SOURCE_DIR}/odm_orthophoto CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${SB_INSTALL_DIR} @@ -269,9 +266,8 @@ externalproject_add(odm_orthophoto ) externalproject_add(fastrasterfilter - DEPENDS gdal - GIT_REPOSITORY https://github.com/OpenDroneMap/FastRasterFilter.git - GIT_TAG main + GIT_REPOSITORY https://github.com/WebODM/FastRasterFilter.git + GIT_TAG 2f16676a9b3d05d3b35ab01b6d2380c8f3a42270 PREFIX ${SB_BINARY_DIR}/fastrasterfilter SOURCE_DIR ${SB_SOURCE_DIR}/fastrasterfilter CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${SB_INSTALL_DIR} @@ -279,17 +275,17 @@ externalproject_add(fastrasterfilter ) externalproject_add(lastools - GIT_REPOSITORY https://github.com/OpenDroneMap/LAStools.git - GIT_TAG 250 + GIT_REPOSITORY https://github.com/WebODM/LAStools.git + GIT_TAG 63ef3a4096c7a74173bccfca800b4e655ee00ae4 PREFIX ${SB_BINARY_DIR}/lastools SOURCE_DIR ${SB_SOURCE_DIR}/lastools CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${SB_INSTALL_DIR} ) externalproject_add(draco - GIT_REPOSITORY https://github.com/google/draco - GIT_SHALLOW OFF - GIT_TAG e801aebf9665f6dcf3b6b0a604055a300ff85aa4 + GIT_REPOSITORY https://github.com/pierotofy/draco + GIT_SHALLOW ON + GIT_TAG 396 PREFIX ${SB_BINARY_DIR}/draco SOURCE_DIR ${SB_SOURCE_DIR}/draco CMAKE_ARGS -DDRACO_TRANSCODER_SUPPORTED=ON diff --git a/SuperBuild/cmake/External-Ceres.cmake b/SuperBuild/cmake/External-Ceres.cmake index 323deef1..93c18249 100644 --- a/SuperBuild/cmake/External-Ceres.cmake +++ b/SuperBuild/cmake/External-Ceres.cmake @@ -8,7 +8,7 @@ ExternalProject_Add(${_proj_name} STAMP_DIR ${_SB_BINARY_DIR}/stamp #--Download step-------------- DOWNLOAD_DIR ${SB_DOWNLOAD_DIR} - URL http://ceres-solver.org/ceres-solver-2.0.0.tar.gz + URL http://ceres-solver.org/ceres-solver-2.2.0.tar.gz #--Update/Patch step---------- UPDATE_COMMAND "" PATCH_COMMAND git apply ${CMAKE_MODULE_PATH}/ceres.patch diff --git a/SuperBuild/cmake/External-Entwine.cmake b/SuperBuild/cmake/External-Entwine.cmake index c0e9279c..14be2937 100644 --- a/SuperBuild/cmake/External-Entwine.cmake +++ b/SuperBuild/cmake/External-Entwine.cmake @@ -12,8 +12,8 @@ ExternalProject_Add(${_proj_name} STAMP_DIR ${_SB_BINARY_DIR}/stamp #--Download step-------------- DOWNLOAD_DIR ${SB_DOWNLOAD_DIR} - GIT_REPOSITORY https://github.com/OpenDroneMap/entwine/ - GIT_TAG 0cf957432f291e841ff1385085dadad933dcba8d + GIT_REPOSITORY https://github.com/WebODM/entwine/ + GIT_TAG 370 #--Update/Patch step---------- UPDATE_COMMAND "" #--Configure step------------- diff --git a/SuperBuild/cmake/External-ExifTool.cmake b/SuperBuild/cmake/External-ExifTool.cmake index 50291203..79a200e3 100644 --- a/SuperBuild/cmake/External-ExifTool.cmake +++ b/SuperBuild/cmake/External-ExifTool.cmake @@ -8,7 +8,7 @@ ExternalProject_Add(${_proj_name} STAMP_DIR ${_SB_BINARY_DIR}/stamp #--Download step-------------- DOWNLOAD_DIR ${SB_DOWNLOAD_DIR} - URL https://github.com/OpenDroneMap/windows-deps/releases/download/2.5.0/exiftool.zip + URL https://github.com/WebODM/windows-deps/releases/download/2.5.0/exiftool.zip SOURCE_DIR ${SB_SOURCE_DIR}/${_proj_name} UPDATE_COMMAND "" CONFIGURE_COMMAND "" diff --git a/SuperBuild/cmake/External-FPCFilter.cmake b/SuperBuild/cmake/External-FPCFilter.cmake index 31d90b0f..0fe2f138 100644 --- a/SuperBuild/cmake/External-FPCFilter.cmake +++ b/SuperBuild/cmake/External-FPCFilter.cmake @@ -2,14 +2,13 @@ set(_proj_name fpcfilter) set(_SB_BINARY_DIR "${SB_BINARY_DIR}/${_proj_name}") ExternalProject_Add(${_proj_name} - DEPENDS gdal PREFIX ${_SB_BINARY_DIR} TMP_DIR ${_SB_BINARY_DIR}/tmp STAMP_DIR ${_SB_BINARY_DIR}/stamp #--Download step-------------- DOWNLOAD_DIR ${SB_DOWNLOAD_DIR} - GIT_REPOSITORY https://github.com/OpenDroneMap/FPCFilter - GIT_TAG 331 + GIT_REPOSITORY https://github.com/WebODM/FPCFilter + GIT_TAG bbac1be23832a51a5d23a4f896a4ef43b55eb306 #--Update/Patch step---------- UPDATE_COMMAND "" #--Configure step------------- diff --git a/SuperBuild/cmake/External-GDAL.cmake b/SuperBuild/cmake/External-GDAL.cmake deleted file mode 100644 index a5c216ea..00000000 --- a/SuperBuild/cmake/External-GDAL.cmake +++ /dev/null @@ -1,31 +0,0 @@ -set(_proj_name gdal) -set(_SB_BINARY_DIR "${SB_BINARY_DIR}/${_proj_name}") - -ExternalProject_Add(${_proj_name} - PREFIX ${_SB_BINARY_DIR} - TMP_DIR ${_SB_BINARY_DIR}/tmp - STAMP_DIR ${_SB_BINARY_DIR}/stamp - #--Download step-------------- - DOWNLOAD_DIR ${SB_DOWNLOAD_DIR} - GIT_REPOSITORY https://github.com/OSGeo/gdal.git - GIT_TAG cf7cef2f1eec2a80c46b0ec0227d8d0cb32e2657 - #--Update/Patch step---------- - UPDATE_COMMAND "" - #--Configure step------------- - SOURCE_DIR ${SB_SOURCE_DIR}/${_proj_name} - CMAKE_ARGS - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -DCMAKE_INSTALL_PREFIX:PATH=${SB_INSTALL_DIR} - -DGDAL_PYTHON_INSTALL_PREFIX=${SB_INSTALL_DIR} - -DBUILD_PYTHON_BINDINGS=ON - ${WIN32_CMAKE_ARGS} - #--Build step----------------- - BINARY_DIR ${_SB_BINARY_DIR} - #--Install step--------------- - INSTALL_DIR ${SB_INSTALL_DIR} - INSTALL_COMMAND "${CMAKE_COMMAND}" --build . --target install - #--Output logging------------- - LOG_DOWNLOAD OFF - LOG_CONFIGURE OFF - LOG_BUILD OFF -) diff --git a/SuperBuild/cmake/External-Hexer.cmake b/SuperBuild/cmake/External-Hexer.cmake deleted file mode 100644 index c3f1d85e..00000000 --- a/SuperBuild/cmake/External-Hexer.cmake +++ /dev/null @@ -1,27 +0,0 @@ -set(_proj_name hexer) -set(_SB_BINARY_DIR "${SB_BINARY_DIR}/${_proj_name}") - -ExternalProject_Add(${_proj_name} - DEPENDS gdal - PREFIX ${_SB_BINARY_DIR} - TMP_DIR ${_SB_BINARY_DIR}/tmp - STAMP_DIR ${_SB_BINARY_DIR}/stamp - #--Download step-------------- - DOWNLOAD_DIR ${SB_DOWNLOAD_DIR} - URL https://github.com/hobuinc/hexer/archive/5876a5ab1d5b504cf1ea985d66ae359287eef31e.tar.gz - #--Update/Patch step---------- - UPDATE_COMMAND "" - #--Configure step------------- - SOURCE_DIR ${SB_SOURCE_DIR}/${_proj_name} - CMAKE_ARGS - -DCMAKE_INSTALL_PREFIX:PATH=${SB_INSTALL_DIR} - ${WIN32_GDAL_ARGS} - #--Build step----------------- - BINARY_DIR ${_SB_BINARY_DIR} - #--Install step--------------- - INSTALL_DIR ${SB_INSTALL_DIR} - #--Output logging------------- - LOG_DOWNLOAD OFF - LOG_CONFIGURE OFF - LOG_BUILD OFF -) diff --git a/SuperBuild/cmake/External-MvsTexturing.cmake b/SuperBuild/cmake/External-MvsTexturing.cmake index 872439f3..b3c5b4a7 100644 --- a/SuperBuild/cmake/External-MvsTexturing.cmake +++ b/SuperBuild/cmake/External-MvsTexturing.cmake @@ -8,8 +8,8 @@ ExternalProject_Add(${_proj_name} STAMP_DIR ${_SB_BINARY_DIR}/stamp #--Download step-------------- DOWNLOAD_DIR ${SB_DOWNLOAD_DIR}/${_proj_name} - GIT_REPOSITORY https://github.com/OpenDroneMap/mvs-texturing - GIT_TAG c5a4d0c9a434553533c6e39d426e349fcfa5f48d + GIT_REPOSITORY https://github.com/WebODM/mvs-texturing + GIT_TAG a56b5e7f95f0bb1dd1e1eb89ce5da202349c0e01 #--Update/Patch step---------- UPDATE_COMMAND "" #--Configure step------------- diff --git a/SuperBuild/cmake/External-Obj2Tiles.cmake b/SuperBuild/cmake/External-Obj2Tiles.cmake index 024a129c..7c578ec1 100644 --- a/SuperBuild/cmake/External-Obj2Tiles.cmake +++ b/SuperBuild/cmake/External-Obj2Tiles.cmake @@ -1,7 +1,7 @@ set(_proj_name obj2tiles) set(_SB_BINARY_DIR "${SB_BINARY_DIR}/${_proj_name}") -set(OBJ2TILES_VERSION v1.0.13) +set(OBJ2TILES_VERSION v1.4.0) set(OBJ2TILES_EXT "") set(OBJ2TILES_ARCH "Linux64") diff --git a/SuperBuild/cmake/External-OpenCV.cmake b/SuperBuild/cmake/External-OpenCV.cmake index b6099631..1a130810 100644 --- a/SuperBuild/cmake/External-OpenCV.cmake +++ b/SuperBuild/cmake/External-OpenCV.cmake @@ -29,8 +29,8 @@ elseif(APPLE) -DOPENCV_LIB_INSTALL_PATH=${SB_INSTALL_DIR}/lib -DOPENCV_BIN_INSTALL_PATH=${SB_INSTALL_DIR}/bin) else() - set(OCV_CMAKE_EXTRA_ARGS -DPYTHON3_NUMPY_INCLUDE_DIRS=${PYTHON_HOME}/lib/python3.12/site-packages/numpy/_core/include - -DPYTHON3_PACKAGES_PATH=${PYTHON_HOME}/lib/python3.12/site-packages + set(OCV_CMAKE_EXTRA_ARGS -DPYTHON3_NUMPY_INCLUDE_DIRS=${PYTHON_HOME}/lib/python3.12/dist-packages/numpy/_core/include + -DPYTHON3_PACKAGES_PATH=${PYTHON_HOME}/lib/python3.12/dist-packages -DPYTHON3_EXECUTABLE=${PYTHON_EXE_PATH}) endif() diff --git a/SuperBuild/cmake/External-OpenMVS.cmake b/SuperBuild/cmake/External-OpenMVS.cmake index 188dbfbc..badc8fbb 100644 --- a/SuperBuild/cmake/External-OpenMVS.cmake +++ b/SuperBuild/cmake/External-OpenMVS.cmake @@ -2,8 +2,8 @@ set(_proj_name openmvs) set(_SB_BINARY_DIR "${SB_BINARY_DIR}/${_proj_name}") externalproject_add(vcg - GIT_REPOSITORY https://github.com/OpenDroneMap/VCG.git - GIT_TAG 285 + GIT_REPOSITORY https://github.com/WebODM/VCG.git + GIT_TAG 3fe55c6fa48ca111dab31eaa594ecab33913a8f1 UPDATE_COMMAND "" SOURCE_DIR ${SB_SOURCE_DIR}/vcg CONFIGURE_COMMAND "" @@ -42,7 +42,7 @@ if(WIN32) # generated with https://github.com/ykhwong/dummy-dll-generator that is # loaded UNLESS the real CUDA DLL is available, since it will # be loaded before our dummy DLL. - file(DOWNLOAD "https://github.com/OpenDroneMap/windows-deps/releases/download/2.5.0/nvcuda_dummy.dll" "${SB_INSTALL_DIR}/bin/nvcuda.dll") + file(DOWNLOAD "https://github.com/WebODM/windows-deps/releases/download/2.5.0/nvcuda_dummy.dll" "${SB_INSTALL_DIR}/bin/nvcuda.dll") endif() ExternalProject_Add(${_proj_name} @@ -52,7 +52,7 @@ ExternalProject_Add(${_proj_name} STAMP_DIR ${_SB_BINARY_DIR}/stamp #--Download step-------------- DOWNLOAD_DIR ${SB_DOWNLOAD_DIR} - GIT_REPOSITORY https://github.com/OpenDroneMap/openMVS + GIT_REPOSITORY https://github.com/WebODM/openMVS GIT_TAG 355 #--Update/Patch step---------- UPDATE_COMMAND "" diff --git a/SuperBuild/cmake/External-OpenSfM.cmake b/SuperBuild/cmake/External-OpenSfM.cmake index 09cc328c..c78b586a 100644 --- a/SuperBuild/cmake/External-OpenSfM.cmake +++ b/SuperBuild/cmake/External-OpenSfM.cmake @@ -24,8 +24,8 @@ ExternalProject_Add(${_proj_name} STAMP_DIR ${_SB_BINARY_DIR}/stamp #--Download step-------------- DOWNLOAD_DIR ${SB_DOWNLOAD_DIR} - GIT_REPOSITORY https://github.com/OpenDroneMap/OpenSfM/ - GIT_TAG c5328439465e6ace011f39077d1077d7b1cdd65d + GIT_REPOSITORY https://github.com/WebODM/OpenSfM/ + GIT_TAG b0f0f6df946a4e3697208f224d43f30242f75dfc #--Update/Patch step---------- UPDATE_COMMAND git submodule update --init --recursive #--Configure step------------- diff --git a/SuperBuild/cmake/External-PDAL.cmake b/SuperBuild/cmake/External-PDAL.cmake index 0a510954..9047b09a 100644 --- a/SuperBuild/cmake/External-PDAL.cmake +++ b/SuperBuild/cmake/External-PDAL.cmake @@ -10,7 +10,7 @@ set(LASZIP_LIB "${SB_INSTALL_DIR}/lib/liblaszip.so") endif() ExternalProject_Add(${_proj_name} - DEPENDS gdal hexer laszip + DEPENDS laszip PREFIX ${_SB_BINARY_DIR} TMP_DIR ${_SB_BINARY_DIR}/tmp STAMP_DIR ${_SB_BINARY_DIR}/stamp diff --git a/SuperBuild/cmake/External-PyPopsift.cmake b/SuperBuild/cmake/External-PyPopsift.cmake deleted file mode 100644 index c37b69e2..00000000 --- a/SuperBuild/cmake/External-PyPopsift.cmake +++ /dev/null @@ -1,36 +0,0 @@ -set(_SB_BINARY_DIR "${SB_BINARY_DIR}/pypopsift") - -# Pypopsift -find_package(CUDA 7.0) - -if(CUDA_FOUND) - ExternalProject_Add(pypopsift - DEPENDS - PREFIX ${_SB_BINARY_DIR} - TMP_DIR ${_SB_BINARY_DIR}/tmp - STAMP_DIR ${_SB_BINARY_DIR}/stamp - #--Download step-------------- - DOWNLOAD_DIR ${SB_DOWNLOAD_DIR} - GIT_REPOSITORY https://github.com/OpenDroneMap/pypopsift - GIT_TAG fe2d1ccc63877ba315e65f34d2adeadd838b3ac3 - #--Update/Patch step---------- - UPDATE_COMMAND "" - #--Configure step------------- - SOURCE_DIR ${SB_SOURCE_DIR}/pypopsift - CMAKE_ARGS - -DOUTPUT_DIR=${SB_INSTALL_DIR}/bin/opensfm/opensfm - -DCMAKE_INSTALL_PREFIX=${SB_INSTALL_DIR} - ${WIN32_CMAKE_ARGS} - ${ARM64_CMAKE_ARGS} - #--Build step----------------- - BINARY_DIR ${_SB_BINARY_DIR} - #--Install step--------------- - INSTALL_DIR ${SB_INSTALL_DIR} - #--Output logging------------- - LOG_DOWNLOAD OFF - LOG_CONFIGURE OFF - LOG_BUILD OFF - ) -else() - message(WARNING "Could not find CUDA >= 7.0") -endif() \ No newline at end of file diff --git a/SuperBuild/cmake/External-RenderDEM.cmake b/SuperBuild/cmake/External-RenderDEM.cmake index d77351a3..47d61145 100644 --- a/SuperBuild/cmake/External-RenderDEM.cmake +++ b/SuperBuild/cmake/External-RenderDEM.cmake @@ -8,8 +8,8 @@ ExternalProject_Add(${_proj_name} STAMP_DIR ${_SB_BINARY_DIR}/stamp #--Download step-------------- DOWNLOAD_DIR ${SB_DOWNLOAD_DIR} - GIT_REPOSITORY https://github.com/OpenDroneMap/RenderDEM - GIT_TAG main + GIT_REPOSITORY https://github.com/WebODM/RenderDEM + GIT_TAG dc5550a3992a164dd6d3a4bb06561f0720d84394 #--Update/Patch step---------- UPDATE_COMMAND "" #--Configure step------------- diff --git a/VERSION b/VERSION index 40c341bd..7c69a55d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.6.0 +3.7.0 diff --git a/configure.sh b/configure.sh index 253e1384..04912f9f 100755 --- a/configure.sh +++ b/configure.sh @@ -6,18 +6,11 @@ APT_GET="env DEBIAN_FRONTEND=noninteractive $(command -v apt-get)" check_version(){ UBUNTU_VERSION=$(lsb_release -r) case "$UBUNTU_VERSION" in - *"20.04"*|*"21.04"*|*"24.04"*) + *"24.04"*) echo "Ubuntu: $UBUNTU_VERSION, good!" ;; - *"18.04"*|*"16.04"*) - echo "ODM 2.1 has upgraded to Ubuntu 21.04, but you're on $UBUNTU_VERSION" - echo "* The last version of ODM that supports Ubuntu 16.04 is v1.0.2." - echo "* The last version of ODM that supports Ubuntu 18.04 is v2.0.0." - echo "We recommend you to upgrade, or better yet, use docker." - exit 1 - ;; *) - echo "You are not on Ubuntu 21.04 (detected: $UBUNTU_VERSION)" + echo "You are not on a supported Ubuntu version (detected: $UBUNTU_VERSION)" echo "It might be possible to run ODM on a newer version of Ubuntu, however, you cannot rely on this script." exit 1 ;; @@ -35,74 +28,145 @@ ensure_prereqs() { if ! command -v sudo &> /dev/null; then echo "Installing sudo" - $APT_GET update - $APT_GET install -y -qq --no-install-recommends sudo + apt-get update + apt-get install -y --no-install-recommends sudo else - sudo $APT_GET update + sudo apt-get update fi if ! command -v lsb_release &> /dev/null; then echo "Installing lsb_release" - sudo $APT_GET install -y -qq --no-install-recommends lsb-release + sudo apt-get install -y --no-install-recommends lsb-release fi if ! command -v pkg-config &> /dev/null; then echo "Installing pkg-config" - sudo $APT_GET install -y -qq --no-install-recommends pkg-config + sudo apt-get install -y --no-install-recommends pkg-config fi echo "Installing tzdata" - sudo $APT_GET install -y -qq tzdata + sudo apt-get install -y tzdata + # UBUNTU_VERSION=$(lsb_release -r) + # if [[ "$UBUNTU_VERSION" == *"24.04"* ]]; then + # echo "Enabling PPA for Ubuntu GIS" + # sudo apt-get install -y --no-install-recommends software-properties-common + # sudo add-apt-repository ppa:ubuntugis/ppa + # sudo apt-get update + # fi echo "Installing Python PIP" - sudo $APT_GET install -y -qq --no-install-recommends \ + sudo apt-get install -y --no-install-recommends \ python3-pip \ - python3-setuptools \ - python3-venv - python3 -m venv venv --system-site-packages - venv/bin/pip3 install -U pip - venv/bin/pip3 install -U shyaml -} - -# Save all dependencies in snapcraft.yaml to maintain a single source of truth. -# Maintaining multiple lists will otherwise be painful. -installdepsfromsnapcraft() { - section="$2" - case "$1" in - build) key=build-packages; ;; - runtime) key=stage-packages; ;; - *) key=build-packages; ;; # shouldn't be needed, but it's here just in case - esac - - UBUNTU_VERSION=$(lsb_release -r) - SNAPCRAFT_FILE="snapcraft.yaml" - if [[ "$UBUNTU_VERSION" == *"21.04"* ]]; then - SNAPCRAFT_FILE="snapcraft21.yaml" - elif [[ "$UBUNTU_VERSION" == *"24.04"* ]]; then - SNAPCRAFT_FILE="snapcraft24.yaml" - fi - - cat snap/$SNAPCRAFT_FILE | \ - venv/bin/shyaml get-values-0 parts.$section.$key | \ - xargs -0 sudo $APT_GET install -y -qq --no-install-recommends + python3-setuptools + sudo pip3 install -U pip } -installruntimedepsonly() { +installruntimedeps() { echo "Installing runtime dependencies" ensure_prereqs check_version - echo "Installing Required Requisites" - installdepsfromsnapcraft runtime prereqs - echo "Installing OpenCV Dependencies" - installdepsfromsnapcraft runtime opencv - echo "Installing OpenSfM Dependencies" - installdepsfromsnapcraft runtime opensfm - echo "Installing OpenMVS Dependencies" - installdepsfromsnapcraft runtime openmvs - echo "Installing GDAL Dependencies" - installdepsfromsnapcraft runtime gdal + for i in {1..20}; do + sudo apt-get install -y --no-install-recommends \ + gdal-bin \ + libgdal34t64 \ + libgeotiff5 \ + libjsoncpp25 \ + libspqr4 \ + libssl3t64 \ + libusb-1.0-0 \ + proj-data \ + procps \ + python3 \ + python3-gdal \ + python3-pkg-resources \ + python3-requests \ + python3-setuptools \ + libavcodec60 \ + libavformat60 \ + libflann1.9 \ + libgtk2.0-0 \ + libjpeg-turbo8 \ + libopenjpip7 \ + liblapack3 \ + libpng16-16 \ + libproj25 \ + libswscale7 \ + libtbb12 \ + libtiff6 \ + libwebpdemux2 \ + libxext6 \ + libamd3 \ + libcamd3 \ + libccolamd3 \ + libcholmod5 \ + libcolamd3 \ + libcxsparse4 \ + libgoogle-glog0v6t64 \ + libsuitesparseconfig7 \ + libboost-program-options1.83.0 \ + libboost-iostreams1.83.0 \ + libboost-serialization1.83.0 \ + libboost-system1.83.0 \ + libgoogle-perftools4t64 + break + echo "Attempt $i failed, sleeping..." + sleep 30 + done +} + +installbuilddeps(){ + echo "Installing build dependencies" + + for i in {1..20}; do + sudo apt-get install -y --no-install-recommends \ + build-essential \ + cmake \ + gdal-bin \ + gfortran \ + git \ + libgdal-dev \ + libgeotiff-dev \ + libjsoncpp-dev \ + libssl-dev \ + libusb-1.0-0-dev \ + ninja-build \ + pkg-config \ + python3-dev \ + python3-gdal \ + python3-pip \ + python3-setuptools \ + python3-wheel \ + rsync \ + swig3.0 \ + libavcodec-dev \ + libavformat-dev \ + libeigen3-dev \ + libflann-dev \ + libgtk2.0-dev \ + libjpeg-dev \ + liblapack-dev \ + libopenjpip7 \ + libpng-dev \ + libproj-dev \ + libswscale-dev \ + libtbb-dev \ + libtiff-dev \ + libxext-dev \ + proj-bin \ + libgoogle-glog-dev \ + libsuitesparse-dev \ + libcgal-dev \ + libboost-program-options-dev \ + libboost-iostreams-dev \ + libboost-serialization-dev \ + libboost-system-dev \ + libgoogle-perftools-dev + break + echo "Attempt $i failed, sleeping..." + sleep 30 + done } installreqs() { @@ -112,38 +176,23 @@ installreqs() { export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$RUNPATH/SuperBuild/install/lib ## Before installing - echo "Updating the system" + echo "Updating" ensure_prereqs check_version - echo "Installing Required Requisites" - installdepsfromsnapcraft build prereqs - echo "Installing OpenCV Dependencies" - installdepsfromsnapcraft build opencv - echo "Installing OpenSfM Dependencies" - installdepsfromsnapcraft build opensfm - echo "Installing OpenMVS Dependencies" - installdepsfromsnapcraft build openmvs - echo "Installing GDAL Dependencies" - installdepsfromsnapcraft build gdal + ensure_prereqs + check_version + installbuilddeps set -e # edt requires numpy to build - venv/bin/pip install numpy==2.3.2 - set +e -} + pip install --ignore-installed numpy==2.3.2 --break-system-packages + pip install --ignore-installed -r requirements.txt --break-system-packages -installpython() { - echo "Installing Python requirements with compiled GDAL" - cd /code - export GDAL_CONFIG=${RUNPATH}/SuperBuild/install/bin/gdal-config - - set -e - venv/bin/pip install -r requirements.txt --ignore-installed set +e } - + install() { installreqs @@ -164,13 +213,7 @@ install() { echo "Compiling SuperBuild" cd ${RUNPATH}/SuperBuild mkdir -p build && cd build - cmake .. \ - -DBUILD_PYTHON_BINDINGS=ON \ - -DPython_ROOT=/code/venv \ - -DPython_FIND_VIRTUALENV=ONLY \ - && make -j$processes - - installpython + cmake .. && make -j$(nproc) echo "Configuration Finished" } @@ -188,7 +231,7 @@ uninstall() { reinstall() { check_version - echo "Reinstalling ODM modules" + echo "Reinstalling" uninstall install } @@ -197,7 +240,9 @@ clean() { rm -rf \ ${RUNPATH}/SuperBuild/build \ ${RUNPATH}/SuperBuild/download \ - ${RUNPATH}/SuperBuild/src + ${RUNPATH}/SuperBuild/src \ + ${RUNPATH}/SuperBuild/install/bin/opensfm/.git \ + ${RUNPATH}/SuperBuild/install/bin/opensfm/opensfm/src/third_party/pybind11/.git # find in /code and delete static libraries and intermediate object files find ${RUNPATH} -type f -name "*.a" -delete -or -type f -name "*.o" -delete @@ -205,25 +250,15 @@ clean() { usage() { echo "Usage:" - echo "bash configure.sh [nproc]" - echo "Subcommands:" + echo "bash configure.sh [nproc]" + echo "Commands:" echo " install" - echo " Installs all dependencies and modules for running ODM" - echo " installruntimedepsonly" - echo " Installs *only* the runtime libraries (used by docker builds). To build from source, use the 'install' command." - echo " installreqs" - echo " Only installs the system requirements and dependencies (does not build SuperBuild or install Python packages)" - echo " installpython" - echo " Installs Python requirements after SuperBuild is compiled" + echo " installruntimedeps" echo " reinstall" - echo " Removes SuperBuild and build modules, then re-installs them. Note this does not update ODM to the latest version. " echo " uninstall" - echo " Removes SuperBuild and build modules. Does not uninstall dependencies" + echo " installreqs" echo " clean" - echo " Cleans the SuperBuild directory by removing temporary files. " echo " help" - echo " Displays this message" - echo "[nproc] is an optional argument that can set the number of processes for the make -j tag. By default it uses $(nproc)" } if [[ $1 =~ ^(install|installruntimedepsonly|reinstall|uninstall|installreqs|installpython|clean)$ ]]; then diff --git a/licenses/license.md b/licenses/license.md index 489a353d..3d8867d2 100644 --- a/licenses/license.md +++ b/licenses/license.md @@ -1,5 +1,4 @@ Licensing for portions of ODM are as follows: -* ImageMagick - Apache 2.0 - http://www.imagemagick.org/script/license.php * Jhead - None - http://www.sentex.net/~mwandel/jhead/ * libjpeg - GPLv2 - http://sourceforge.net/projects/libjpeg/ * Boost - Boost Software License, Version 1.0 - http://www.boost.org/LICENSE_1_0.txt @@ -9,16 +8,14 @@ Licensing for portions of ODM are as follows: * libzip - BSD - http://www.nih.at/libzip/LICENSE.html * libcv - BSD - http://opencv.org/license.html * libcvaux - BSD - http://opencv.org/license.html -* bundler - GPLv3 - http://www.gnu.org/copyleft/gpl.html * parallel - GPLv3 - http://www.gnu.org/copyleft/gpl.html * PoissonRecon - BSD - http://www.cs.jhu.edu/~misha/Code/PoissonRecon/license.txt * vlfeat - BSD - http://www.vlfeat.org/license.html * graclus - GPLv3 - http://www.gnu.org/copyleft/gpl.html * PROJ.4 - MIT - http://trac.osgeo.org/proj/wiki/WikiStart#License -* PCL - BSD - http://pointclouds.org - * Flann - BSD2 - http://opensource.org/licenses/bsd-license.php - * Eigen - MPL2 - http://www.mozilla.org/MPL/2.0 - * Qhull - http://www.qhull.org/COPYING.txt +* Flann - BSD2 - http://opensource.org/licenses/bsd-license.php +* Eigen - MPL2 - http://www.mozilla.org/MPL/2.0 +* Qhull - http://www.qhull.org/COPYING.txt * libext - https://github.com/WebODM/ODM/blob/gh-pages/licenses/libext_copyright.txt * libx11 - https://github.com/WebODM/ODM/blob/gh-pages/licenses/libx11_copyright.txt * MVS Texturing - BSD - https://github.com/nmoehrle/mvs-texturing/blob/master/LICENSE.txt diff --git a/opendm/gpu.py b/opendm/gpu.py index 12f171a8..f701c3a9 100644 --- a/opendm/gpu.py +++ b/opendm/gpu.py @@ -22,18 +22,6 @@ def has_popsift_and_can_handle_texsize(width, height): log.ODM_WARNING(str(e)) return False - try: - from opensfm import pypopsift - if pypopsift.fits_texture(int(width * 1.02), int(height * 1.02)): - log.ODM_INFO("popsift can handle texture size %dx%d" % (width, height)) - return True - else: - log.ODM_INFO("popsift cannot handle texture size %dx%d" % (width, height)) - return False - except Exception as e: - log.ODM_WARNING(str(e)) - return False - @lru_cache(maxsize=None) def get_cuda_compute_version(device_id = 0): cuda_lib = "libcuda.so" diff --git a/requirements.txt b/requirements.txt index 2eb06d3f..41ad5069 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ edt==3.0.0 ExifRead==3.5.1 Fiona==1.10.1 ; sys_platform == 'linux' Fiona==1.10.1 ; sys_platform == 'darwin' -https://github.com/OpenDroneMap/windows-deps/releases/download/2.6.0/fiona-1.10.1-cp312-cp312-win_amd64.whl ; sys_platform == 'win32' +https://github.com/WebODM/windows-deps/releases/download/2.6.0/fiona-1.10.1-cp312-cp312-win_amd64.whl ; sys_platform == 'win32' numpy==2.3.2 Pillow==11.3.0 pillow-jxl-plugin==1.3.4 @@ -14,8 +14,9 @@ Pysolar==0.13 PyYAML==6.0.2 rasterio==1.4.3 ; sys_platform == 'linux' rasterio==1.4.3 ; sys_platform == 'darwin' -https://github.com/OpenDroneMap/windows-deps/releases/download/2.6.0/rasterio-1.4.3-cp312-cp312-win_amd64.whl ; sys_platform == 'win32' -https://github.com/OpenDroneMap/windows-deps/releases/download/2.6.0/gdal-3.11.1-cp312-cp312-win_amd64.whl ; sys_platform == 'win32' +https://github.com/WebODM/windows-deps/releases/download/2.6.0/rasterio-1.4.3-cp312-cp312-win_amd64.whl ; sys_platform == 'win32' +https://github.com/WebODM/windows-deps/releases/download/2.6.0/gdal-3.11.1-cp312-cp312-win_amd64.whl ; sys_platform == 'win32' +gdal[numpy]==3.8.4 scikit-learn==1.7.1 scikit-image==0.25.2 scipy==1.16.1 @@ -26,7 +27,6 @@ onnxruntime==1.22.1 pygltflib==1.16.5 packaging==25.0 codem==0.26.1 -# matplotlib subdep required by codem (remove once we impl dep solver) matplotlib==3.10.3 trimesh==4.7.1 piexif==1.1.3 diff --git a/run.py b/run.py index 087dae3e..b6b787d1 100755 --- a/run.py +++ b/run.py @@ -65,49 +65,9 @@ def odm_version(): if retcode == 0: save_opts(opts_json, args) - # Do not show ASCII art for local submodels runs + # Do not show end message for local submodels runs if retcode == 0 and not "submodels" in args.project_path: - log.ODM_INFO('MMMMMMMMMMMNNNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNNNMMMMMMMMMMM') - log.ODM_INFO('MMMMMMdo:..---../sNMMMMMMMMMMMMMMMMMMMMMMMMMMNs/..---..:odMMMMMM') - log.ODM_INFO('MMMMy-.odNMMMMMNy/`/mMMMMMMMMMMMMMMMMMMMMMMm/`/hNMMMMMNdo.-yMMMM') - log.ODM_INFO('MMN/`sMMMMMMMMMNNMm/`yMMMMMMMMMMMMMMMMMMMMy`/mMNNMMMMMMMMNs`/MMM') - log.ODM_INFO('MM/ hMMMMMMMMNs.+MMM/ dMMMMMMMMMMMMMMMMMMh +MMM+.sNMMMMMMMMh +MM') - log.ODM_INFO('MN /MMMMMMNo/./mMMMMN :MMMMMMMMMMMMMMMMMM: NMMMMm/./oNMMMMMM: NM') - log.ODM_INFO('Mm +MMMMMN+ `/MMMMMMM`-MMMMMMMMMMMMMMMMMM-`MMMMMMM:` oNMMMMM+ mM') - log.ODM_INFO('MM..NMMNs./mNMMMMMMMy sMMMMMMMMMMMMMMMMMMo hMMMMMMMNm/.sNMMN`-MM') - log.ODM_INFO('MMd`:mMNomMMMMMMMMMy`:MMMMMMMNmmmmNMMMMMMN:`hMMMMMMMMMdoNMm-`dMM') - log.ODM_INFO('MMMm:.omMMMMMMMMNh/ sdmmho/.`..`-``-/sddh+ /hNMMMMMMMMdo.:mMMM') - log.ODM_INFO('MMMMMd+--/osss+:-:/` ```:- .ym+ hmo``:-` `+:-:ossso/-:+dMMMMM') - log.ODM_INFO('MMMMMMMNmhysosydmNMo /ds`/NMM+ hMMd..dh. sMNmdysosyhmNMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMMMMMMMMMs .:-:``hmmN+ yNmds -:.:`-NMMMMMMMMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMMMMMMMMN.-mNm- //:::. -:://: +mMd`-NMMMMMMMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMMMMMMMM+ dMMN -MMNNN+ yNNNMN :MMMs sMMMMMMMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMMMMMMMM`.mmmy /mmmmm/ smmmmm``mmmh :MMMMMMMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMMMMMMMM``:::- ./////. -:::::` :::: -MMMMMMMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMMMMMMMM:`mNNd /NNNNN+ hNNNNN .NNNy +MMMMMMMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMMMMMMMMd`/MMM.`ys+//. -/+oso +MMN.`mMMMMMMMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMMMMMMMMMy /o:- `oyhd/ shys+ `-:s-`hMMMMMMMMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMNmdhhhdmNMMM` +d+ sMMM+ hMMN:`hh- sMMNmdhhhdmNMMMMMMMM') - log.ODM_INFO('MMMMMms:::/++//::+ho .+- /dM+ hNh- +/` -h+:://++/::/smMMMMM') - log.ODM_INFO('MMMN+./hmMMMMMMNds- ./oso:.``:. :-``.:os+- -sdNMMMMMMmy:.oNMMM') - log.ODM_INFO('MMm-.hMNhNMMMMMMMMNo`/MMMMMNdhyyyyhhdNMMMM+`oNMMMMMMMMNhNMh.-mMM') - log.ODM_INFO('MM:`mMMN/-sNNMMMMMMMo yMMMMMMMMMMMMMMMMMMy sMMMMMMMNNs-/NMMm`:MM') - log.ODM_INFO('Mm /MMMMMd/.-oMMMMMMN :MMMMMMMMMMMMMMMMMM-`MMMMMMMo-./dMMMMM/ NM') - log.ODM_INFO('Mm /MMMMMMm:-`sNMMMMN :MMMMMMMMMMMMMMMMMM-`MMMMMNs`-/NMMMMMM/ NM') - log.ODM_INFO('MM:`mMMMMMMMMd/-sMMMo yMMMMMMMMMMMMMMMMMMy sMMMs-/dMMMMMMMMd`:MM') - log.ODM_INFO('MMm-.hMMMMMMMMMdhMNo`+MMMMMMMMMMMMMMMMMMMM+`oNMhdMMMMMMMMMh.-mMM') - log.ODM_INFO('MMMNo./hmNMMMMMNms--yMMMMMMMMMMMMMMMMMMMMMMy--smNMMMMMNmy/.oNMMM') - log.ODM_INFO('MMMMMms:-:/+++/:-+hMMMMMMMMMMMMMMMMMMMMMMMMMNh+-:/+++/:-:smMMMMM') - log.ODM_INFO('MMMMMMMMNdhhyhdmMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMmdhyhhmNMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMMMMMNNNNNMMMMMMNNNNNNMMMMMMMMNNMMMMMMMNNMMMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMMMh/-...-+dMMMm......:+hMMMMs../MMMMMo..sMMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMM/ /yhy- sMMm -hhy/ :NMM+ oMMMy /MMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMy /MMMMN` NMm /MMMMo +MM: .` yMd``` :MMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMM+ sMMMMM: hMm /MMMMd -MM- /s `h.`d- -MMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMs +MMMMM. mMm /MMMMy /MM. +M/ yM: `MMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMN- smNm/ +MMm :NNdo` .mMM` oMM+/yMM/ MMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMMNo- `:yMMMm `:sNMMM` sMMMMMMM+ NMMMMMMMMMMM') - log.ODM_INFO('MMMMMMMMMMMMMMMNmmNMMMMMMMNmmmmNMMMMMMMNNMMMMMMMMMNNMMMMMMMMMMMM') + log.ODM_INFO('Done! d-(^_^)z') log.ODM_INFO('ODM app finished - %s' % system.now()) else: exit(retcode) \ No newline at end of file diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml deleted file mode 100644 index 0de79353..00000000 --- a/snap/snapcraft.yaml +++ /dev/null @@ -1,215 +0,0 @@ -name: opendronemap -adopt-info: odm -grade: stable -confinement: strict -base: core20 - -summary: Command line toolkit for processing aerial drone imagery -description: > - An open source command line toolkit for processing aerial drone imagery. ODM turns simple 2D images into: - - * Classified Point Clouds - * 3D Textured Models - * Georeferenced Orthorectified Imagery - * Georeferenced Digital Elevation Models - - The application is available for Windows, Mac and Linux and it works from the command line, making it ideal for power users, scripts and for integration with other software. - -# The UbuntuGIS PPA only has i386 and amd64 packages so we can't build any -# other architectures. Therefore let's limit to those here. -architectures: - - build-on: i386 - run-on: i386 - - build-on: amd64 - run-on: amd64 - -package-repositories: - - type: apt - ppa: ubuntugis/ubuntugis-unstable - -parts: - prereqs: - source: . - plugin: nil - build-packages: - - build-essential - - cmake - - gfortran # to build scipy - - git - - libopenmpi-dev - - libssl-dev - - libusb-1.0-0-dev - - ninja-build - - pkg-config - - python3-dev - - python3-pip - - python3-setuptools - - python3-wheel - - rsync - - swig3.0 - stage-packages: - - libssl1.1 - - libusb-1.0-0 - - procps - - python3 - - python3-distutils - - python3-pkg-resources # required base package for core20 - - python3-requests # required base package for core20 - - python3-setuptools - stage: - # remove deb-based numpy because it conflicts with our pip-installed version - - -usr/lib/python3/dist-packages/numpy - - opencv: - source: . - plugin: nil - build-packages: - - libavcodec-dev - - libavformat-dev - - libeigen3-dev - - libflann-dev - - libgtk2.0-dev - - libjpeg-dev - - liblapack-dev - - libopenjpip7 - - libpng-dev - - libproj-dev - - libswscale-dev - - libtbb-dev - - libtiff-dev - - libxext-dev - - proj-bin - stage-packages: - - libavcodec58 - - libavformat58 - - libflann1.9 - - libgtk2.0-0 - - libjpeg-turbo8 - - libopenjpip7 - - liblapack3 - - libpng16-16 - - libproj19 - - libswscale5 - - libtbb2 - - libtiff5 - - libwebpdemux2 - - libxext6 - - openmvs: - source: . - plugin: nil - build-packages: - - libcgal-dev - - libboost-program-options-dev - - libboost-iostreams-dev - - libboost-serialization-dev - - libboost-system-dev - stage-packages: - - libboost-program-options1.71.0 - - libboost-iostreams1.71.0 - - libboost-serialization1.71.0 - - libboost-system1.71.0 - - opensfm: - source: . - plugin: nil - build-packages: - - libgoogle-glog-dev - - libsuitesparse-dev - stage-packages: - - libamd2 - - libcamd2 - - libccolamd2 - - libcholmod3 - - libcolamd2 - - libcxsparse3 - - libgoogle-glog0v5 - - libsuitesparseconfig5 - - gdal: - source: . - plugin: nil - build-packages: - - libgeotiff-dev - - libhdf5-serial-dev - - libopenmpi-dev - - pybind11-dev - - python3-dev - - python3-numpy - - python3-setuptools - - swig - stage-packages: - - libcurl3t64-gnutls - - libgeotiff5 - - libjsoncpp1 - - libspqr2 - - proj-data - - odm: - after: - - prereqs - - opencv - - opensfm - - openmvs - - gdal - source: . - plugin: nil # We will script everything ourselves - build-environment: - # Set Python location to build host's system so that we can - # use system libraries while building the Snap Package - - PYTHONHOME: /usr - # Set the location for pip to install requirements into inside - # the Snap package - - PYTHONUSERBASE: $SNAPCRAFT_PART_INSTALL - override-build: | - snapcraftctl set-version $(cat VERSION) - - # Portable build - test -f /usr/bin/gcc_real || mv -v /usr/bin/gcc /usr/bin/gcc_real - test -f /usr/bin/gcc || cp -v ./docker/gcc /usr/bin/gcc - test -f /usr/bin/g++_real || mv -v /usr/bin/g++ /usr/bin/g++_real - test -f /usr/bin/g++ || cp -v ./docker/g++ /usr/bin/g++ - - pip3 install --user -r requirements.txt - - # Build the SuperBuild libraries - mkdir -p SuperBuild/build - cd SuperBuild/build - cmake -G Ninja .. - cmake --build . --parallel 1 - - rsync -av --exclude .git \ - $SNAPCRAFT_PART_BUILD/ $SNAPCRAFT_PART_INSTALL/odm/ - chmod -R u=rwX,go=rX $PYTHONUSERBASE/lib/python* - stage: - # strip the temporary build files and sources - - -odm/SuperBuild/build - - -odm/SuperBuild/download - - -odm/SuperBuild/src - prime: - # remove any static-libraries - - -**/*.a - # remove any header files - - -**/*.h - # remove any left-over temporary compiled 'object' files - - -**/*.o - build-snaps: - - cmake - -plugs: - shared-memory: - private: true - -apps: - opendronemap: - command: odm/run.sh - environment: - # Ensure libraries are found - LD_LIBRARY_PATH: $SNAP/odm/SuperBuild/install/lib:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/blas:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/lapack - PYTHONPATH: $SNAP/odm/SuperBuild/install/lib/python3.8/site-packages:$SNAP/lib/python3.8/site-packages:$SNAP/usr/lib/python3/dist-packages/:$SNAP/usr/lib/python3.8:$SNAP/odm/SuperBuild/install/bin/opensfm - PROJ_LIB: $SNAP/usr/share/proj - plugs: - - home - - network - - network-bind - - removable-media diff --git a/snap/snapcraft21.yaml b/snap/snapcraft21.yaml deleted file mode 100644 index 565c2760..00000000 --- a/snap/snapcraft21.yaml +++ /dev/null @@ -1,217 +0,0 @@ -name: opendronemap -adopt-info: odm -grade: stable -confinement: strict -base: core21 - -summary: Command line toolkit for processing aerial drone imagery -description: > - An open source command line toolkit for processing aerial drone imagery. ODM turns simple 2D images into: - - * Classified Point Clouds - * 3D Textured Models - * Georeferenced Orthorectified Imagery - * Georeferenced Digital Elevation Models - - The application is available for Windows, Mac and Linux and it works from the command line, making it ideal for power users, scripts and for integration with other software. - -# The UbuntuGIS PPA only has i386 and amd64 packages so we can't build any -# other architectures. Therefore let's limit to those here. -architectures: - - build-on: i386 - run-on: i386 - - build-on: amd64 - run-on: amd64 - -package-repositories: - - type: apt - ppa: ubuntugis/ubuntugis-unstable - -parts: - prereqs: - source: . - plugin: nil - build-packages: - - build-essential - - cmake - - gfortran # to build scipy - - git - - libopenmpi-dev - - libssl-dev - - libusb-1.0-0-dev - - ninja-build - - pkg-config - - python3-dev - - python3-pip - - python3-setuptools - - python3-wheel - - rsync - - swig3.0 - stage-packages: - - libssl1.1 - - libusb-1.0-0 - - procps - - python3 - - python3-distutils - - python3-pkg-resources # required base package for core20 - - python3-requests # required base package for core20 - - python3-setuptools - stage: - # remove deb-based numpy because it conflicts with our pip-installed version - - -usr/lib/python3/dist-packages/numpy - - opencv: - source: . - plugin: nil - build-packages: - - libavcodec-dev - - libavformat-dev - - libeigen3-dev - - libflann-dev - - libgtk2.0-dev - - libjpeg-dev - - liblapack-dev - - libopenjpip7 - - libpng-dev - - libproj-dev - - libswscale-dev - - libtbb-dev - - libtiff-dev - - libxext-dev - - proj-bin - stage-packages: - - libavcodec58 - - libavformat58 - - libflann1.9 - - libgtk2.0-0 - - libjpeg-turbo8 - - libopenjpip7 - - liblapack3 - - libpng16-16 - - libproj19 - - libswscale5 - - libtbb2 - - libtiff5 - - libwebpdemux2 - - libxext6 - - openmvs: - source: . - plugin: nil - build-packages: - - libcgal-dev - - libboost-program-options-dev - - libboost-iostreams-dev - - libboost-serialization-dev - - libboost-system-dev - stage-packages: - - libboost-program-options1.74.0 - - libboost-iostreams1.74.0 - - libboost-serialization1.74.0 - - libboost-system1.74.0 - - opensfm: - source: . - plugin: nil - build-packages: - - libgoogle-glog-dev - - libsuitesparse-dev - stage-packages: - - libamd2 - - libcamd2 - - libccolamd2 - - libcholmod3 - - libcolamd2 - - libcxsparse3 - - libgoogle-glog0v5 - - libsuitesparseconfig5 - - gdal: - source: . - plugin: nil - build-packages: - - libgeotiff-dev - - libhdf5-serial-dev - - libopenmpi-dev - - pybind11-dev - - python3-dev - - python3-numpy - - python3-setuptools - - swig - stage-packages: - - libcurl3-gnutls - - libcurl4 - - libjsoncpp24 - - libspqr2 - - proj-data - - odm: - after: - - prereqs - - opencv - - opensfm - - openmvs - - gdal - source: . - plugin: nil # We will script everything ourselves - build-environment: - # Set Python location to build host's system so that we can - # use system libraries while building the Snap Package - - PYTHONHOME: /usr - # Set the location for pip to install requirements into inside - # the Snap package - - PYTHONUSERBASE: $SNAPCRAFT_PART_INSTALL - override-build: | - snapcraftctl set-version $(cat VERSION) - - # Portable build - test -f /usr/bin/gcc_real || mv -v /usr/bin/gcc /usr/bin/gcc_real - test -f /usr/bin/gcc || cp -v ./docker/gcc /usr/bin/gcc - test -f /usr/bin/g++_real || mv -v /usr/bin/g++ /usr/bin/g++_real - test -f /usr/bin/g++ || cp -v ./docker/g++ /usr/bin/g++ - - pip3 install --user -r requirements.txt - - # Build the SuperBuild libraries - mkdir -p SuperBuild/build - cd SuperBuild/build - cmake -G Ninja .. - cmake --build . --parallel 1 - - rsync -av --exclude .git \ - $SNAPCRAFT_PART_BUILD/ $SNAPCRAFT_PART_INSTALL/odm/ - chmod -R u=rwX,go=rX $PYTHONUSERBASE/lib/python* - stage: - # strip the temporary build files and sources - - -odm/SuperBuild/build - - -odm/SuperBuild/download - - -odm/SuperBuild/src - prime: - # remove any static-libraries - - -**/*.a - # remove any header files - - -**/*.h - # remove any left-over temporary compiled 'object' files - - -**/*.o - build-snaps: - - cmake - -plugs: - shared-memory: - private: true - -apps: - opendronemap: - command: odm/run.sh - command-chain: - - bin/snapcraft-preload # Fixes multiprocessing python module - environment: - # Ensure libraries are found - LD_LIBRARY_PATH: $SNAP/odm/SuperBuild/install/lib:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/blas:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/lapack - PYTHONPATH: $SNAP/odm/SuperBuild/install/lib/python3.8/site-packages:$SNAP/lib/python3.8/site-packages:$SNAP/usr/lib/python3/dist-packages/:$SNAP/usr/lib/python3.8:$SNAP/odm/SuperBuild/install/bin/opensfm - PROJ_LIB: $SNAP/usr/share/proj - plugs: - - home - - network - - network-bind - - removable-media diff --git a/snap/snapcraft24.yaml b/snap/snapcraft24.yaml deleted file mode 100644 index 66f38d6a..00000000 --- a/snap/snapcraft24.yaml +++ /dev/null @@ -1,227 +0,0 @@ -name: opendronemap -adopt-info: odm -grade: stable -confinement: strict -base: core24 - -summary: Command line toolkit for processing aerial drone imagery -description: > - An open source command line toolkit for processing aerial drone imagery. ODM turns simple 2D images into: - - * Classified Point Clouds - * 3D Textured Models - * Georeferenced Orthorectified Imagery - * Georeferenced Digital Elevation Models - - The application is available for Windows, Mac and Linux and it works from the command line, making it ideal for power users, scripts and for integration with other software. - -# The UbuntuGIS PPA only has i386 and amd64 packages so we can't build any -# other architectures. Therefore let's limit to those here. -architectures: - - build-on: i386 - run-on: i386 - - build-on: amd64 - run-on: amd64 - -package-repositories: - - type: apt - ppa: ubuntugis/ubuntugis-unstable - # Ensure prioritised above standard repo for GDAL version 3.11.1 - priority: 1001 - -parts: - prereqs: - source: . - plugin: nil - build-packages: - - build-essential - - cmake - - gfortran # to build scipy - - git - - libopenmpi-dev - - libssl-dev - - libusb-1.0-0-dev - - ninja-build - - pkg-config - - python3-dev - - python3-pip - - python3-setuptools - - python3-wheel - - rsync - - swig3.0 - stage-packages: - - libssl3t64 - - libusb-1.0-0 - - procps - - python3 - - python3-pkg-resources # required base package for core20 - - python3-requests # required base package for core20 - - python3-setuptools - stage: - # remove deb-based numpy because it conflicts with our pip-installed version - - -usr/lib/python3/dist-packages/numpy - - opencv: - source: . - plugin: nil - build-packages: - - libavcodec-dev - - libavformat-dev - - libeigen3-dev - - libflann-dev - - libgtk2.0-dev - - libjpeg-dev - - libjxl-dev - - liblapack-dev - - libopenjpip7 - - libpng-dev - - libproj-dev - - libswscale-dev - - libtbb-dev - - libtiff-dev - - libxext-dev - - proj-bin - stage-packages: - - libavcodec60 - - libavformat60 - - libflann1.9 - - libgtk2.0-0 - - libjpeg-turbo8 - - libjxl0.7 - - libopenjpip7 - - liblapack3 - - libpng16-16 - - libproj25 - - libswscale7 - - libtbb12 - - libtiff6 - - libwebpdemux2 - - libxext6 - - openmvs: - source: . - plugin: nil - build-packages: - - libcgal-dev - - libboost-program-options-dev - - libboost-iostreams-dev - - libboost-serialization-dev - - libboost-system-dev - stage-packages: - - libboost-program-options1.83.0 - - libboost-iostreams1.83.0 - - libboost-serialization1.83.0 - - libboost-system1.83.0 - - opensfm: - source: . - plugin: nil - build-packages: - - libgoogle-glog-dev - - libsuitesparse-dev - stage-packages: - - libamd3 - - libcamd3 - - libccolamd3 - - libcholmod5 - - libcolamd3 - - libcxsparse4 - - libgoogle-glog0v6t64 - - libsuitesparseconfig7 - - gdal: - source: . - plugin: nil - build-packages: - - libexpat-dev - - libgeos-dev - - libgeotiff-dev - - libhdf5-serial-dev - - libopenmpi-dev - - pybind11-dev - - python3-dev - - python3-numpy - - python3-setuptools - - swig - stage-packages: - - libaec0 - - libcurl3t64-gnutls - - libcurl4t64 - - libexpat1 - - libgeotiff5 - - libgeos-c1t64 - - libhdf5-103-1t64 - - libjsoncpp25 - - libspqr4 - - proj-data - - odm: - after: - - prereqs - - opencv - - opensfm - - openmvs - - gdal - source: . - plugin: nil # We will script everything ourselves - build-environment: - # Set Python location to build host's system so that we can - # use system libraries while building the Snap Package - - PYTHONHOME: /usr - # Set the location for pip to install requirements into inside - # the Snap package - - PYTHONUSERBASE: $SNAPCRAFT_PART_INSTALL - override-build: | - snapcraftctl set-version $(cat VERSION) - - # Portable build - test -f /usr/bin/gcc_real || mv -v /usr/bin/gcc /usr/bin/gcc_real - test -f /usr/bin/gcc || cp -v ./docker/gcc /usr/bin/gcc - test -f /usr/bin/g++_real || mv -v /usr/bin/g++ /usr/bin/g++_real - test -f /usr/bin/g++ || cp -v ./docker/g++ /usr/bin/g++ - - pip3 install --user -r requirements.txt - - # Build the SuperBuild libraries - mkdir -p SuperBuild/build - cd SuperBuild/build - cmake -G Ninja .. - cmake --build . --parallel 1 - - rsync -av --exclude .git \ - $SNAPCRAFT_PART_BUILD/ $SNAPCRAFT_PART_INSTALL/odm/ - chmod -R u=rwX,go=rX $PYTHONUSERBASE/lib/python* - stage: - # strip the temporary build files and sources - - -odm/SuperBuild/build - - -odm/SuperBuild/download - - -odm/SuperBuild/src - prime: - # remove any static-libraries - - -**/*.a - # remove any header files - - -**/*.h - # remove any left-over temporary compiled 'object' files - - -**/*.o - build-snaps: - - cmake - -plugs: - shared-memory: - private: true - -apps: - opendronemap: - command: odm/run.sh - command-chain: - - bin/snapcraft-preload # Fixes multiprocessing python module - environment: - # Ensure libraries are found - LD_LIBRARY_PATH: $SNAP/odm/SuperBuild/install/lib:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/blas:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/lapack - PYTHONPATH: $SNAP/odm/SuperBuild/install/lib/python3.12/site-packages:$SNAP/lib/python3.12/site-packages:$SNAP/usr/lib/python3/dist-packages/:$SNAP/usr/lib/python3.12:$SNAP/odm/SuperBuild/install/bin/opensfm - PROJ_LIB: $SNAP/usr/share/proj - plugs: - - home - - network - - network-bind - - removable-media diff --git a/stages/odm_app.py b/stages/odm_app.py index 27e08635..10206df5 100644 --- a/stages/odm_app.py +++ b/stages/odm_app.py @@ -104,7 +104,7 @@ def execute(self): elif code == 3: log.ODM_ERROR("ODM can't find a program that is required for processing to run! Did you do a custom build of ODM? (cool!) Make sure that all programs required by ODM are in the right place and are built correctly.") else: - log.ODM_ERROR("The program exited with a strange error code. Please report it at https://community.opendronemap.org") + log.ODM_ERROR("The program exited with a strange error code. Please report it") # TODO: more? From a5ca435d47c40bf850fa8f9957acc6af94ff3f0d Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Thu, 9 Apr 2026 16:27:39 -0400 Subject: [PATCH 02/29] What tests --- Dockerfile | 4 ---- gpu.Dockerfile | 4 ---- portable.Dockerfile | 4 ---- 3 files changed, 12 deletions(-) diff --git a/Dockerfile b/Dockerfile index 70ae94ac..4efd88ce 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,10 +14,6 @@ COPY . ./ # Run the build RUN bash configure.sh install -# Run the tests -ENV PATH="/code/venv/bin:$PATH" -RUN bash test.sh - # Clean Superbuild RUN bash configure.sh clean diff --git a/gpu.Dockerfile b/gpu.Dockerfile index 437d780f..5de0b880 100644 --- a/gpu.Dockerfile +++ b/gpu.Dockerfile @@ -14,10 +14,6 @@ COPY . ./ # Run the build RUN PORTABLE_INSTALL=YES GPU_INSTALL=YES bash configure.sh install -# Run the tests -ENV PATH="/code/venv/bin:$PATH" -RUN bash test.sh - # Clean Superbuild RUN bash configure.sh clean diff --git a/portable.Dockerfile b/portable.Dockerfile index 27c459a0..eeedfe2b 100644 --- a/portable.Dockerfile +++ b/portable.Dockerfile @@ -14,10 +14,6 @@ COPY . ./ # Run the build RUN PORTABLE_INSTALL=YES bash configure.sh install -# Run the tests -ENV PATH="/code/venv/bin:$PATH" -RUN bash test.sh - # Clean Superbuild RUN bash configure.sh clean From 32f7330c4607274f7c221404374196dc2d198a1c Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Thu, 9 Apr 2026 23:41:58 -0400 Subject: [PATCH 03/29] Command invokation fix, Dockerfile changes without venv --- Dockerfile | 13 +++++++------ configure.sh | 2 +- configure_macos.sh | 2 +- gpu.Dockerfile | 9 +++++---- portable.Dockerfile | 9 +++++---- 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/Dockerfile b/Dockerfile index 4efd88ce..2d2d9222 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,8 +2,8 @@ FROM ubuntu:24.04 AS builder # Env variables ENV DEBIAN_FRONTEND=noninteractive \ - PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/local/lib/python3.12/dist-packages:/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ - LD_LIBRARY_PATH="/code/SuperBuild/install/lib" + PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ + LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/code/SuperBuild/install/lib" # Prepare directories WORKDIR /code @@ -25,8 +25,8 @@ FROM ubuntu:24.04 # Env variables ENV DEBIAN_FRONTEND=noninteractive \ - PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/local/lib/python3.12/dist-packages:/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ - LD_LIBRARY_PATH="/code/SuperBuild/install/lib" \ + PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/lib/python3.12:/code/SuperBuild/install/bin/opensfm" \ + LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/code/SuperBuild/install/lib" \ PDAL_DRIVER_PATH="/code/SuperBuild/install/bin" WORKDIR /code @@ -34,12 +34,13 @@ WORKDIR /code # Copy everything we built from the builder COPY --from=builder /code /code -ENV PATH="/code/venv/bin:$PATH" +# Copy the Python libraries installed via pip from the builder +COPY --from=builder /usr/local /usr/local # Install shared libraries that we depend on via APT, but *not* # the -dev packages to save space! # Also run a smoke test on ODM and OpenSfM -RUN bash configure.sh installruntimedepsonly \ +RUN bash configure.sh installruntimedeps \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \ && bash run.sh --help \ diff --git a/configure.sh b/configure.sh index 04912f9f..635c4511 100755 --- a/configure.sh +++ b/configure.sh @@ -261,7 +261,7 @@ usage() { echo " help" } -if [[ $1 =~ ^(install|installruntimedepsonly|reinstall|uninstall|installreqs|installpython|clean)$ ]]; then +if [[ $1 =~ ^(install|reinstall|uninstall|installreqs|installpython|clean)$ ]]; then RUNPATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" "$1" else diff --git a/configure_macos.sh b/configure_macos.sh index 6918de59..9f6dd994 100755 --- a/configure_macos.sh +++ b/configure_macos.sh @@ -116,7 +116,7 @@ usage() { echo "[nproc] is an optional argument that can set the number of processes for the make -j tag. By default it uses $(nproc)" } -if [[ $1 =~ ^(install|installruntimedepsonly|reinstall|uninstall|installreqs|clean)$ ]]; then +if [[ $1 =~ ^(install|reinstall|uninstall|installreqs|clean)$ ]]; then RUNPATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" "$1" else diff --git a/gpu.Dockerfile b/gpu.Dockerfile index 5de0b880..2428fe0d 100644 --- a/gpu.Dockerfile +++ b/gpu.Dockerfile @@ -2,7 +2,7 @@ FROM nvidia/cuda:12.9.1-devel-ubuntu24.04 AS builder # Env variables ENV DEBIAN_FRONTEND=noninteractive \ - PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/local/lib/python3.12/dist-packages:/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ + PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/code/SuperBuild/install/lib" # Prepare directories @@ -25,7 +25,7 @@ FROM nvidia/cuda:12.9.1-runtime-ubuntu24.04 # Env variables ENV DEBIAN_FRONTEND=noninteractive \ - PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/local/lib/python3.12/dist-packages:/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ + PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/lib/python3.12:/code/SuperBuild/install/bin/opensfm" \ LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/code/SuperBuild/install/lib" \ PDAL_DRIVER_PATH="/code/SuperBuild/install/bin" @@ -34,14 +34,15 @@ WORKDIR /code # Copy everything we built from the builder COPY --from=builder /code /code -ENV PATH="/code/venv/bin:$PATH" +# Copy the Python libraries installed via pip from the builder +COPY --from=builder /usr/local /usr/local RUN apt-get update -y \ && apt-get install -y ffmpeg libtbbmalloc2 # Install shared libraries that we depend on via APT, but *not* # the -dev packages to save space! # Also run a smoke test on ODM and OpenSfM -RUN bash configure.sh installruntimedepsonly \ +RUN bash configure.sh installruntimedeps \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \ && bash run.sh --help \ diff --git a/portable.Dockerfile b/portable.Dockerfile index eeedfe2b..91c6be20 100644 --- a/portable.Dockerfile +++ b/portable.Dockerfile @@ -2,7 +2,7 @@ FROM ubuntu:24.04 AS builder # Env variables ENV DEBIAN_FRONTEND=noninteractive \ - PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/local/lib/python3.12/dist-packages:/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ + PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/code/SuperBuild/install/lib" # Prepare directories @@ -25,7 +25,7 @@ FROM ubuntu:24.04 # Env variables ENV DEBIAN_FRONTEND=noninteractive \ - PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/local/lib/python3.12/dist-packages:/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ + PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/lib/python3.12:/code/SuperBuild/install/bin/opensfm" \ LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/code/SuperBuild/install/lib" \ PDAL_DRIVER_PATH="/code/SuperBuild/install/bin" @@ -34,12 +34,13 @@ WORKDIR /code # Copy everything we built from the builder COPY --from=builder /code /code -ENV PATH="/code/venv/bin:$PATH" +# Copy the Python libraries installed via pip from the builder +COPY --from=builder /usr/local /usr/local # Install shared libraries that we depend on via APT, but *not* # the -dev packages to save space! # Also run a smoke test on ODM and OpenSfM -RUN bash configure.sh installruntimedepsonly \ +RUN bash configure.sh installruntimedeps \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \ && bash run.sh --help \ From adb2bb2478a2fe837b7b0194619fb39747f91f20 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Thu, 9 Apr 2026 23:51:03 -0400 Subject: [PATCH 04/29] Revert "feat: add flag --merge-skip-blending to skip expensive blending in splitmerge (#1934)" This reverts commit 0080422a8258b99f8214dd43d8cf6af720df2596. --- contrib/mergepreview/mergepreview.py | 2 +- opendm/config.py | 12 ------------ opendm/orthophoto.py | 11 +---------- stages/splitmerge.py | 2 +- 4 files changed, 3 insertions(+), 24 deletions(-) diff --git a/contrib/mergepreview/mergepreview.py b/contrib/mergepreview/mergepreview.py index 1be75630..1e05e98c 100644 --- a/contrib/mergepreview/mergepreview.py +++ b/contrib/mergepreview/mergepreview.py @@ -116,7 +116,7 @@ 'BIGTIFF': 'IF_SAFER', 'BLOCKXSIZE': 512, 'BLOCKYSIZE': 512 - }, args.merge_skip_blending) + }) log.ODM_INFO("Wrote %s" % output_file) diff --git a/opendm/config.py b/opendm/config.py index 388108d6..05543d49 100755 --- a/opendm/config.py +++ b/opendm/config.py @@ -840,18 +840,6 @@ def config(argv=None, parser=None): 'Options: %(choices)s. Default: ' '%(default)s')) - # TODO ideally the blending should be optimised so we don't need this param to skip it, e.g. - # 1. Only blend in a buffer zone around cutline edges (e.g., 100-200 pixels) - # 2. Skip blending for interior regions that are far from edges - # 3. This would require detecting which blocks intersect cutline boundaries - # We have block-based processing already in place in orthophoto.py, so need logic to determine - # if a block needs blending based on its proximity to cutlines - parser.add_argument('--merge-skip-blending', - action=StoreTrue, - nargs=0, - default=False, - help='During the orthophoto merging, skip expensive blending operation: %(default)s') - parser.add_argument('--force-gps', action=StoreTrue, nargs=0, diff --git a/opendm/orthophoto.py b/opendm/orthophoto.py index 27f42b81..b78a4f5c 100644 --- a/opendm/orthophoto.py +++ b/opendm/orthophoto.py @@ -265,7 +265,7 @@ def feather_raster(input_raster, output_raster, blend_distance=20): return output_raster -def merge(input_ortho_and_ortho_cuts, output_orthophoto, orthophoto_vars={}, merge_skip_blending=False): +def merge(input_ortho_and_ortho_cuts, output_orthophoto, orthophoto_vars={}): """ Based on https://github.com/mapbox/rio-merge-rgba/ Merge orthophotos around cutlines using a blend buffer. @@ -334,10 +334,6 @@ def merge(input_ortho_and_ortho_cuts, output_orthophoto, orthophoto_vars={}, mer profile["bigtiff"] = orthophoto_vars.get('BIGTIFF', 'IF_SAFER') profile.update() - # Log here to avoid logging in each block processed - if merge_skip_blending: - log.ODM_INFO("Skipping second and third pass orthophoto blending, as --merge-skip-blending passed") - # create destination file with rasterio.open(output_orthophoto, "w", **profile) as dstrast: dstrast.colorinterp = colorinterp @@ -376,11 +372,6 @@ def merge(input_ortho_and_ortho_cuts, output_orthophoto, orthophoto_vars={}, mer if np.count_nonzero(dstarr[-1]) == blocksize: break - # Skip expensive blending operations if flag passed - if merge_skip_blending: - dstrast.write(dstarr, window=dst_window) - continue - # Second pass, write all feathered rasters # blending the edges for src, _ in sources: diff --git a/stages/splitmerge.py b/stages/splitmerge.py index 1b69c3f8..625a5f1a 100644 --- a/stages/splitmerge.py +++ b/stages/splitmerge.py @@ -265,7 +265,7 @@ def process(self, args, outputs): os.remove(tree.odm_orthophoto_tif) orthophoto_vars = orthophoto.get_orthophoto_vars(args) - orthophoto.merge(all_orthos_and_ortho_cuts, tree.odm_orthophoto_tif, orthophoto_vars, args.merge_skip_blending) + orthophoto.merge(all_orthos_and_ortho_cuts, tree.odm_orthophoto_tif, orthophoto_vars) orthophoto.post_orthophoto_steps(args, merged_bounds_file, tree.odm_orthophoto_tif, tree.orthophoto_tiles, args.orthophoto_resolution, reconstruction, tree, False) elif len(all_orthos_and_ortho_cuts) == 1: From 8f7b8de186960dc3c5e86fddb2c641600105449c Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 00:02:17 -0400 Subject: [PATCH 05/29] Fix requirements, configure.sh, pdal VLR forwarding --- configure.sh | 5 +++-- opendm/dem/pdal.py | 2 +- requirements.txt | 10 ++++++---- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/configure.sh b/configure.sh index 635c4511..8bf1bd33 100755 --- a/configure.sh +++ b/configure.sh @@ -248,6 +248,7 @@ clean() { find ${RUNPATH} -type f -name "*.a" -delete -or -type f -name "*.o" -delete } + usage() { echo "Usage:" echo "bash configure.sh [nproc]" @@ -261,11 +262,11 @@ usage() { echo " help" } -if [[ $1 =~ ^(install|reinstall|uninstall|installreqs|installpython|clean)$ ]]; then +if [[ $1 =~ ^(install|installruntimedeps|reinstall|uninstall|installreqs|clean)$ ]]; then RUNPATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" "$1" else - echo "Invalid instructions." >&2 + echo "Invalid command" usage exit 1 fi diff --git a/opendm/dem/pdal.py b/opendm/dem/pdal.py index a43ab3b8..35a33de4 100644 --- a/opendm/dem/pdal.py +++ b/opendm/dem/pdal.py @@ -165,7 +165,7 @@ def run_pdaltranslate_smrf(fin, fout, scalar, slope, threshold, window): '--filters.smrf.slope=%s' % slope, '--filters.smrf.threshold=%s' % threshold, '--filters.smrf.window=%s' % window, - '--writers.las.forward=scale,offset' + '--writers.las.forward=scale,offset,vlr' ] system.run(' '.join(cmd)) diff --git a/requirements.txt b/requirements.txt index 41ad5069..63771716 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ edt==3.0.0 ExifRead==3.5.1 Fiona==1.10.1 ; sys_platform == 'linux' Fiona==1.10.1 ; sys_platform == 'darwin' -https://github.com/WebODM/windows-deps/releases/download/2.6.0/fiona-1.10.1-cp312-cp312-win_amd64.whl ; sys_platform == 'win32' +https://github.com/WebODM/windows-deps/releases/download/v3.7.0/fiona-1.10.1-cp312-cp312-win_amd64.whl ; sys_platform == 'win32' numpy==2.3.2 Pillow==11.3.0 pillow-jxl-plugin==1.3.4 @@ -14,9 +14,11 @@ Pysolar==0.13 PyYAML==6.0.2 rasterio==1.4.3 ; sys_platform == 'linux' rasterio==1.4.3 ; sys_platform == 'darwin' -https://github.com/WebODM/windows-deps/releases/download/2.6.0/rasterio-1.4.3-cp312-cp312-win_amd64.whl ; sys_platform == 'win32' -https://github.com/WebODM/windows-deps/releases/download/2.6.0/gdal-3.11.1-cp312-cp312-win_amd64.whl ; sys_platform == 'win32' -gdal[numpy]==3.8.4 +https://github.com/WebODM/windows-deps/releases/download/v3.7.0/rasterio-1.4.3-cp312-cp312-win_amd64.whl ; sys_platform == 'win32' +https://github.com/WebODM/windows-deps/releases/download/v3.7.0/gdal-3.11.1-cp312-cp312-win_amd64.whl ; sys_platform == 'win32' +gdal[numpy]==3.8.4 ; sys_platform == 'linux' +gdal[numpy]==3.8.4 ; sys_platform == 'darwin' +https://github.com/WebODM/windows-deps/releases/download/v3.7.0/GDAL-3.8.4-cp312-cp312-win_amd64.whl ; sys_platform == 'win32' scikit-learn==1.7.1 scikit-image==0.25.2 scipy==1.16.1 From f4e52bd47d2e2db90522c4cb609baf18462f9474 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 00:07:20 -0400 Subject: [PATCH 06/29] Readd shebang --- run.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/run.py b/run.py index b6b787d1..9ca1e75b 100755 --- a/run.py +++ b/run.py @@ -1,3 +1,5 @@ +#!/usr/bin/python3 + # Basic check import sys if sys.version_info.major < 3: From 754492db6e7a8d285016f5f5987ed35f0649d9d6 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 00:07:47 -0400 Subject: [PATCH 07/29] Revert "fix(odm): invoke secondary invokation of odm cli is prepended with 'python3'" This reverts commit 4c61d3b4beff2fe9b74b2742bbd220b9d76fbff0. --- opendm/remote.py | 5 +---- stages/splitmerge.py | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/opendm/remote.py b/opendm/remote.py index d5b93a6e..9eed0e98 100644 --- a/opendm/remote.py +++ b/opendm/remote.py @@ -476,11 +476,8 @@ def process_local(self): submodels_path = os.path.abspath(self.path("..")) argv = get_submodel_argv(config.config(), submodels_path, submodel_name) - # Always invoke run.py through venv python - cmd = ["python3"] + argv - # Re-run the ODM toolchain on the submodel - system.run(" ".join(map(double_quote, cmd)), env_vars=os.environ.copy()) + system.run(" ".join(map(double_quote, map(str, argv))), env_vars=os.environ.copy()) # This will only get executed if the command above succeeds self.touch(completed_file) diff --git a/stages/splitmerge.py b/stages/splitmerge.py index 625a5f1a..62d12b93 100644 --- a/stages/splitmerge.py +++ b/stages/splitmerge.py @@ -185,11 +185,8 @@ def process(self, args, outputs): argv = get_submodel_argv(args, tree.submodels_path, sp_octx.name()) - # Always invoke run.py through venv python - cmd = ["python3"] + argv - # Re-run the ODM toolchain on the submodel - system.run(" ".join(map(double_quote, cmd)), env_vars=os.environ.copy()) + system.run(" ".join(map(double_quote, map(str, argv))), env_vars=os.environ.copy()) else: lre.set_projects([os.path.abspath(os.path.join(p, "..")) for p in submodel_paths]) lre.run_toolchain() From 5f00e52248ebe9d43bd22c07176c7ff0c6408c0f Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 00:09:52 -0400 Subject: [PATCH 08/29] Revert "fix(odm): use MultiPolygon for cutline fiona usage, remove unused imports" This reverts commit 75a1e1f1503f99719daafa9a1ddb57680c7475f4. --- opendm/cutline.py | 4 +++- opendm/remote.py | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/opendm/cutline.py b/opendm/cutline.py index 692bbebd..e3f8bf8b 100644 --- a/opendm/cutline.py +++ b/opendm/cutline.py @@ -1,4 +1,5 @@ import os +import shutil import rasterio import fiona import numpy as np @@ -7,6 +8,7 @@ from opendm import log from opendm import io from opendm import concurrency +from opendm import get_image_size from opendm import system from skimage.feature import canny @@ -163,7 +165,7 @@ def compute_linestrings(direction): 'driver': 'GPKG', 'schema': { 'properties': {}, - 'geometry': 'MultiPolygon' + 'geometry': 'Polygon' } } diff --git a/opendm/remote.py b/opendm/remote.py index 9eed0e98..8e26f7de 100644 --- a/opendm/remote.py +++ b/opendm/remote.py @@ -1,7 +1,9 @@ import time import datetime import os +import sys import threading +import signal import zipfile import glob from opendm import log From c7dbb901a681563a4e29fedc824f8995deb23f2a Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 00:11:17 -0400 Subject: [PATCH 09/29] Fix cutline computation --- opendm/cutline.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/opendm/cutline.py b/opendm/cutline.py index e3f8bf8b..f077e34e 100644 --- a/opendm/cutline.py +++ b/opendm/cutline.py @@ -148,20 +148,22 @@ def compute_linestrings(direction): log.ODM_INFO("Merging polygons") cutline_polygons = unary_union(polygons) - if not hasattr(cutline_polygons, '__getitem__'): - cutline_polygons = [cutline_polygons] - - largest_cutline = cutline_polygons[0] - max_area = largest_cutline.area - for p in cutline_polygons: - if p.area > max_area: - max_area = p.area - largest_cutline = p + + if not hasattr(cutline_polygons, 'geoms'): + largest_cutline = cutline_polygons + max_area = largest_cutline.area + else: + largest_cutline = cutline_polygons.geoms[0] + max_area = largest_cutline.area + for p in cutline_polygons.geoms: + if p.area > max_area: + max_area = p.area + largest_cutline = p log.ODM_INFO("Largest cutline found: %s m^2" % max_area) meta = { - 'crs': {'init': str(f.crs).lower() }, + 'crs': fiona.crs.CRS.from_wkt(f.crs.to_wkt()), 'driver': 'GPKG', 'schema': { 'properties': {}, From 10e985a02fc806c416ffba2dcf0297659b726259 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 00:12:15 -0400 Subject: [PATCH 10/29] Remove unused imports --- opendm/cutline.py | 2 -- opendm/remote.py | 2 -- 2 files changed, 4 deletions(-) diff --git a/opendm/cutline.py b/opendm/cutline.py index f077e34e..bdfdf2fd 100644 --- a/opendm/cutline.py +++ b/opendm/cutline.py @@ -1,5 +1,4 @@ import os -import shutil import rasterio import fiona import numpy as np @@ -8,7 +7,6 @@ from opendm import log from opendm import io from opendm import concurrency -from opendm import get_image_size from opendm import system from skimage.feature import canny diff --git a/opendm/remote.py b/opendm/remote.py index 8e26f7de..9eed0e98 100644 --- a/opendm/remote.py +++ b/opendm/remote.py @@ -1,9 +1,7 @@ import time import datetime import os -import sys import threading -import signal import zipfile import glob from opendm import log From 9b67c29faa4b5f310d8624c2e9aaa4cd92ee2d98 Mon Sep 17 00:00:00 2001 From: Kemal Uzel Date: Fri, 6 Feb 2026 15:30:50 +0300 Subject: [PATCH 11/29] Fix SRT parsing and GPS altitude handling --- opendm/video/srtparser.py | 31 ++++++++++++++++++------------- opendm/video/video2dataset.py | 2 +- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/opendm/video/srtparser.py b/opendm/video/srtparser.py index cfe87121..75e82513 100644 --- a/opendm/video/srtparser.py +++ b/opendm/video/srtparser.py @@ -3,6 +3,11 @@ import re +def float_or_none_if_zero(v): + fv = float(v) + return fv if fv != 0 else None + + def match_single(regexes, line, dtype=int): if isinstance(regexes, str): regexes = [(regexes, dtype)] @@ -207,7 +212,7 @@ def parse(self): ], line) shutter = match_single([ - "shutter : \d+/(\d+\.?\d*)" + "shutter : \d+/(\d+\.?\d*)", "SS (\d+\.?\d*)" ], line) @@ -219,22 +224,22 @@ def parse(self): focal_len = match_single("focal_len : (\d+)", line) latitude = match_single([ - ("latitude: ([\d\.\-]+)", lambda v: float(v) if v != 0 else None), - ("latitude : ([\d\.\-]+)", lambda v: float(v) if v != 0 else None), - ("GPS \([\d\.\-]+,? ([\d\.\-]+),? [\d\.\-]+\)", lambda v: float(v) if v != 0 else None), - ("RTK \([-+]?\d+\.\d+, (-?\d+\.\d+), -?\d+\)", lambda v: float(v) if v != 0 else None), + ("latitude: ([\d\.\-]+)", float_or_none_if_zero), + ("latitude : ([\d\.\-]+)", float_or_none_if_zero), + ("GPS \([\d\.\-]+,? ([\d\.\-]+),? [\d\.\-]+\)", float_or_none_if_zero), + ("RTK \([-+]?\d+\.\d+, (-?\d+\.\d+), -?\d+\)", float_or_none_if_zero), ], line) longitude = match_single([ - ("longitude: ([\d\.\-]+)", lambda v: float(v) if v != 0 else None), - ("longtitude : ([\d\.\-]+)", lambda v: float(v) if v != 0 else None), - ("GPS \(([\d\.\-]+),? [\d\.\-]+,? [\d\.\-]+\)", lambda v: float(v) if v != 0 else None), - ("RTK \((-?\d+\.\d+), [-+]?\d+\.\d+, -?\d+\)", lambda v: float(v) if v != 0 else None), + ("longitude: ([\d\.\-]+)", float_or_none_if_zero), + ("longtitude : ([\d\.\-]+)", float_or_none_if_zero), + ("GPS \(([\d\.\-]+),? [\d\.\-]+,? [\d\.\-]+\)", float_or_none_if_zero), + ("RTK \((-?\d+\.\d+), [-+]?\d+\.\d+, -?\d+\)", float_or_none_if_zero), ], line) altitude = match_single([ - ("altitude: ([\d\.\-]+)", lambda v: float(v) if v != 0 else None), - ("GPS \([\d\.\-]+,? [\d\.\-]+,? ([\d\.\-]+)\)", lambda v: float(v) if v != 0 else None), - ("RTK \([-+]?\d+\.\d+, [-+]?\d+\.\d+, (-?\d+)\)", lambda v: float(v) if v != 0 else None), - ("abs_alt: ([\d\.\-]+)", lambda v: float(v) if v != 0 else None), + ("altitude: ([\d\.\-]+)", float_or_none_if_zero), + ("GPS \([\d\.\-]+,? [\d\.\-]+,? ([\d\.\-]+)\)", float_or_none_if_zero), + ("RTK \([-+]?\d+\.\d+, [-+]?\d+\.\d+, (-?\d+\.?\d*)\)", float_or_none_if_zero), + ("abs_alt: ([\d\.\-]+)", float_or_none_if_zero), ], line) diff --git a/opendm/video/video2dataset.py b/opendm/video/video2dataset.py index 8f977dfa..872877dd 100644 --- a/opendm/video/video2dataset.py +++ b/opendm/video/video2dataset.py @@ -346,6 +346,6 @@ def get_gps_location(elapsed_time, lat, lng, altitude): gps_ifd[piexif.GPSIFD.GPSLongitude] = exiv_lng if altitude is not None: gps_ifd[piexif.GPSIFD.GPSAltitudeRef] = 0 - gps_ifd[piexif.GPSIFD.GPSAltitude] = float_to_rational(round(altitude)) + gps_ifd[piexif.GPSIFD.GPSAltitude] = float_to_rational(altitude) return gps_ifd \ No newline at end of file From 444cfb2c63d75f4c7d63425c28983ae4e6f3ca91 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 00:23:08 -0400 Subject: [PATCH 12/29] Round to 3 decimals --- opendm/video/video2dataset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendm/video/video2dataset.py b/opendm/video/video2dataset.py index 872877dd..48529b3f 100644 --- a/opendm/video/video2dataset.py +++ b/opendm/video/video2dataset.py @@ -346,6 +346,6 @@ def get_gps_location(elapsed_time, lat, lng, altitude): gps_ifd[piexif.GPSIFD.GPSLongitude] = exiv_lng if altitude is not None: gps_ifd[piexif.GPSIFD.GPSAltitudeRef] = 0 - gps_ifd[piexif.GPSIFD.GPSAltitude] = float_to_rational(altitude) + gps_ifd[piexif.GPSIFD.GPSAltitude] = float_to_rational(round(altitude * 1000) / 1000) return gps_ifd \ No newline at end of file From 12aff425ff2502f9b852bb5654fca6a7892305b6 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 00:34:12 -0400 Subject: [PATCH 13/29] GDAL, hexer out --- README.md | 2 ++ SuperBuild/CMakeLists.txt | 18 ------------------ 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 9a0fd05b..8cf3317b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +# ODM + An open source command line toolkit for processing aerial drone imagery. ODM turns simple 2D images into: * Classified Point Clouds diff --git a/SuperBuild/CMakeLists.txt b/SuperBuild/CMakeLists.txt index 972877ed..f92949af 100644 --- a/SuperBuild/CMakeLists.txt +++ b/SuperBuild/CMakeLists.txt @@ -132,19 +132,6 @@ include(ExternalProject-Setup) # Download and install third party libs # ######################################### -# --------------------------------------------------------------------------------------------- -# Geospatial Data Abstraction Library (GDAL) -# -set(ODM_GDAL_Version 3.11.1) -if(WIN32) - message(STATUS "GDAL: Using pip-installed version from ${GDAL_ROOT}") - # Create a dummy target to satisfy dependencies - add_custom_target(gdal) -else() - option(ODM_BUILD_GDAL "Force to build GDAL library" ON) - SETUP_EXTERNAL_PROJECT(GDAL ${ODM_GDAL_Version} ${ODM_BUILD_GDAL}) -endif() - # --------------------------------------------------------------------------------------------- # Open Source Computer Vision (OpenCV) # @@ -172,11 +159,6 @@ option(ODM_BUILD_Ceres "Force to build Ceres library" OFF) SETUP_EXTERNAL_PROJECT(Ceres ${ODM_Ceres_Version} ${ODM_BUILD_Ceres}) -# --------------------------------------------------------------------------------------------- -# Hexer -# -SETUP_EXTERNAL_PROJECT(Hexer 1.5 ON) - # --------------------------------------------------------------------------------------------- # Open Structure from Motion (OpenSfM) # From eb1e339f88085f5a2ee1fea7d8d8b33f5f7b4410 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 00:46:39 -0400 Subject: [PATCH 14/29] Fix create_bounds_gpkg --- SuperBuild/cmake/External-PDAL.cmake | 2 +- opendm/cropper.py | 53 ++++++++++++---------------- 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/SuperBuild/cmake/External-PDAL.cmake b/SuperBuild/cmake/External-PDAL.cmake index 9047b09a..5a0d0d5e 100644 --- a/SuperBuild/cmake/External-PDAL.cmake +++ b/SuperBuild/cmake/External-PDAL.cmake @@ -28,7 +28,7 @@ ExternalProject_Add(${_proj_name} -DBUILD_PLUGIN_PGPOINTCLOUD=OFF -DBUILD_PLUGIN_CPD=OFF -DBUILD_PLUGIN_GREYHOUND=OFF - -DBUILD_PLUGIN_HEXBIN=ON + -DBUILD_PLUGIN_HEXBIN=OFF -DBUILD_PLUGIN_ICEBRIDGE=OFF -DBUILD_PLUGIN_MRSID=OFF -DBUILD_PLUGIN_NITF=OFF diff --git a/opendm/cropper.py b/opendm/cropper.py index 77c69750..29bfa62b 100644 --- a/opendm/cropper.py +++ b/opendm/cropper.py @@ -121,7 +121,7 @@ def merge_bounds(input_bound_files, output_bounds, buffer_distance = 0): # Save and close output data source out_ds = None - def create_bounds_geojson(self, pointcloud_path, buffer_distance = 0, decimation_step=40): + def create_bounds_geojson(self, pointcloud_path, buffer_distance = 0, decimation_step=40, edge_length=1.0, pc_wkt="EPSG:4326"): """ Compute a buffered polygon around the data extents (not just a bounding box) of the given point cloud. @@ -145,30 +145,18 @@ def create_bounds_geojson(self, pointcloud_path, buffer_distance = 0, decimation return '' # Use PDAL to dump boundary information - # then read the information back - - boundary_file_path = self.path('boundary.json') - - run('pdal info --boundary --filters.hexbin.edge_length=1 --filters.hexbin.threshold=1 "{0}" > "{1}"'.format(decimated_pointcloud_path, boundary_file_path)) - - pc_geojson_boundary_feature = None - - with open(boundary_file_path, 'r') as f: - json_f = json.loads(f.read()) - pc_geojson_boundary_feature = json_f['boundary']['boundary_json'] - - if pc_geojson_boundary_feature is None: raise RuntimeError("Could not determine point cloud boundaries") - - # Write bounds to GeoJSON tmp_bounds_geojson_path = self.path('tmp-bounds.geojson') - with open(tmp_bounds_geojson_path, "w") as f: - f.write(json.dumps({ - "type": "FeatureCollection", - "features": [{ - "type": "Feature", - "geometry": pc_geojson_boundary_feature - }] - })) + if os.path.isfile(tmp_bounds_geojson_path): + os.unlink(tmp_bounds_geojson_path) + + run('pdal tindex create --tindex {0} -f GeoJSON --threshold 1 --resolution {1} --t_srs={2} --filespec {3}'.format( + double_quote(tmp_bounds_geojson_path), + edge_length, + double_quote(pc_wkt), + double_quote(decimated_pointcloud_path))) + + if not os.path.isfile(tmp_bounds_geojson_path): + raise RuntimeError("Could not determine point cloud boundaries") # Create a convex hull around the boundary # as to encompass the entire area (no holes) @@ -206,7 +194,9 @@ def create_bounds_geojson(self, pointcloud_path, buffer_distance = 0, decimation os.remove(bounds_geojson_path) out_ds = driver.CreateDataSource(bounds_geojson_path) - layer = out_ds.CreateLayer("convexhull", geom_type=ogr.wkbPolygon) + srs = ogr.osr.SpatialReference() + srs.ImportFromWkt(pc_wkt) + layer = out_ds.CreateLayer("convexhull", srs=srs, geom_type=ogr.wkbPolygon) feature_def = layer.GetLayerDefn() feature = ogr.Feature(feature_def) @@ -239,18 +229,19 @@ def create_bounds_gpkg(self, pointcloud_path, buffer_distance = 0, decimation_st log.ODM_WARNING('Point cloud does not exist, cannot generate GPKG bounds {}'.format(pointcloud_path)) return '' - bounds_geojson_path = self.create_bounds_geojson(pointcloud_path, buffer_distance, decimation_step) summary_file_path = os.path.join(self.storage_dir, '{}.summary.json'.format(self.files_prefix)) export_summary_json(pointcloud_path, summary_file_path) - pc_proj4 = None + pc_wkt = None + edge_length = 1.0 with open(summary_file_path, 'r') as f: json_f = json.loads(f.read()) - pc_proj4 = json_f['summary']['srs']['proj4'] + pc_wkt = json_f['summary']['srs']['wkt'] - if pc_proj4 is None: raise RuntimeError("Could not determine point cloud proj4 declaration") + if pc_wkt is None: raise RuntimeError("Could not determine point cloud WKT declaration") + bounds_geojson_path = self.create_bounds_geojson(pointcloud_path, buffer_distance, decimation_step, edge_length=edge_length, pc_wkt=pc_wkt) bounds_gpkg_path = os.path.join(self.storage_dir, '{}.bounds.gpkg'.format(self.files_prefix)) if os.path.isfile(bounds_gpkg_path): @@ -260,10 +251,10 @@ def create_bounds_gpkg(self, pointcloud_path, buffer_distance = 0, decimation_st kwargs = { 'input': double_quote(bounds_geojson_path), 'output': double_quote(bounds_gpkg_path), - 'proj4': pc_proj4 + 'wkt': pc_wkt } - run('ogr2ogr -overwrite -f GPKG -a_srs "{proj4}" {output} {input}'.format(**kwargs)) + run('ogr2ogr -overwrite -f GPKG -a_srs "{pc_wkt}" {output} {input}'.format(**kwargs)) return bounds_gpkg_path From ddd606f9f55c626548a21fc349959937b6a3b781 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 01:04:35 -0400 Subject: [PATCH 15/29] No need for ceres patch --- SuperBuild/cmake/External-Ceres.cmake | 1 - SuperBuild/cmake/ceres.patch | 42 --------------------------- 2 files changed, 43 deletions(-) delete mode 100644 SuperBuild/cmake/ceres.patch diff --git a/SuperBuild/cmake/External-Ceres.cmake b/SuperBuild/cmake/External-Ceres.cmake index 93c18249..3bb8d215 100644 --- a/SuperBuild/cmake/External-Ceres.cmake +++ b/SuperBuild/cmake/External-Ceres.cmake @@ -11,7 +11,6 @@ ExternalProject_Add(${_proj_name} URL http://ceres-solver.org/ceres-solver-2.2.0.tar.gz #--Update/Patch step---------- UPDATE_COMMAND "" - PATCH_COMMAND git apply ${CMAKE_MODULE_PATH}/ceres.patch #--Configure step------------- SOURCE_DIR ${SB_SOURCE_DIR}/${_proj_name} CMAKE_ARGS diff --git a/SuperBuild/cmake/ceres.patch b/SuperBuild/cmake/ceres.patch deleted file mode 100644 index 42248029..00000000 --- a/SuperBuild/cmake/ceres.patch +++ /dev/null @@ -1,42 +0,0 @@ -diff --git a/cmake/FindTBB.cmake b/cmake/FindTBB.cmake -index 5ae7b615..10e540da 100644 ---- a/cmake/FindTBB.cmake -+++ b/cmake/FindTBB.cmake -@@ -429,10 +429,23 @@ findpkg_finish(TBB_MALLOC_PROXY tbbmalloc_proxy) - #============================================================================= - #parse all the version numbers from tbb - if(NOT TBB_VERSION) -+ set(TBB_VERSION_FILE_PRIOR_TO_TBB_2021_1 -+ "${TBB_INCLUDE_DIR}/tbb/tbb_stddef.h") -+ set(TBB_VERSION_FILE_AFTER_TBB_2021_1 -+ "${TBB_INCLUDE_DIR}/oneapi/tbb/version.h") -+ -+ if (EXISTS "${TBB_VERSION_FILE_PRIOR_TO_TBB_2021_1}") -+ set(TBB_VERSION_FILE "${TBB_VERSION_FILE_PRIOR_TO_TBB_2021_1}") -+ elseif (EXISTS "${TBB_VERSION_FILE_AFTER_TBB_2021_1}") -+ set(TBB_VERSION_FILE "${TBB_VERSION_FILE_AFTER_TBB_2021_1}") -+ else() -+ message(FATAL_ERROR "Found TBB installation: ${TBB_INCLUDE_DIR} " -+ "missing version header.") -+ endif() - - #only read the start of the file - file(STRINGS -- "${TBB_INCLUDE_DIR}/tbb/tbb_stddef.h" -+ "${TBB_VERSION_FILE}" - TBB_VERSION_CONTENTS - REGEX "VERSION") - -diff --git a/internal/ceres/covariance_impl.cc b/internal/ceres/covariance_impl.cc -index 1f86707f..25bf9348 100644 ---- a/internal/ceres/covariance_impl.cc -+++ b/internal/ceres/covariance_impl.cc -@@ -634,7 +634,7 @@ bool CovarianceImpl::ComputeCovarianceValuesUsingSuiteSparseQR() { - // separately. - const SuiteSparse_long rank = SuiteSparseQR(SPQR_ORDERING_BESTAMD, - SPQR_DEFAULT_TOL, -- cholmod_jacobian.ncol, -+ static_cast(cholmod_jacobian.ncol), - &cholmod_jacobian, - &R, - &permutation, From a13ed44a8b7aee11559b06e3446765f660b4b604 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 01:28:39 -0400 Subject: [PATCH 16/29] Remove PYTHON_HOME --- SuperBuild/CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/SuperBuild/CMakeLists.txt b/SuperBuild/CMakeLists.txt index f92949af..15925e10 100644 --- a/SuperBuild/CMakeLists.txt +++ b/SuperBuild/CMakeLists.txt @@ -111,15 +111,8 @@ if (WIN32) elseif(APPLE) set(PYTHON_HOME "${SB_ROOT_DIR}/../venv") set(PYTHON_EXE_PATH "${PYTHON_HOME}/bin/python") - set(GDAL_ROOT "${SB_INSTALL_DIR}") - set(GDAL_LIBRARY "${GDAL_ROOT}/lib/libgdal.dylib") - set(GDAL_INCLUDE_DIR "${GDAL_ROOT}/include") else() - set(PYTHON_HOME "${SB_ROOT_DIR}/../venv") set(PYTHON_EXE_PATH "${PYTHON_HOME}/bin/python3") - set(GDAL_ROOT "${SB_INSTALL_DIR}") - set(GDAL_LIBRARY "${GDAL_ROOT}/lib/libgdal.so") - set(GDAL_INCLUDE_DIR "${GDAL_ROOT}/include") endif() # Path to additional CMake modules From ce2275dc761478e6bb21b3207c0eb875b722953a Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 02:03:09 -0400 Subject: [PATCH 17/29] Fix Python path, update README --- README.md | 44 +++++--------------- SuperBuild/CMakeLists.txt | 3 +- SuperBuild/cmake/ExternalProject-Setup.cmake | 1 + 3 files changed, 14 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 8cf3317b..b1bfe7d6 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,28 @@ # ODM -An open source command line toolkit for processing aerial drone imagery. ODM turns simple 2D images into: +A free and open source photogrammetry engine for processing aerial and ground imagery. ODM turns images into: * Classified Point Clouds * 3D Textured Models -* Georeferenced Orthorectified Imagery +* Georeferenced Orthophotos * Georeferenced Digital Elevation Models ![images-diag](https://user-images.githubusercontent.com/1174901/96644651-5b205600-12f7-11eb-827b-8f4a3a6f3b21.png) The application is available for Windows, Mac and Linux and it works from the command line, making it ideal for power users, scripts and for integration with other software. -If you would rather not type commands in a shell and are looking for a friendly user interface, check out [WebODM](https://github.com/WebODM/WebODM). +If you would rather not type commands in a shell and are looking for a friendly user interface, check out [WebODM](https://webodm.org). -## Quickstart - -The easiest way to run ODM is via docker. To install docker, see [docs.docker.com](https://docs.docker.com). Once you have docker installed and [working](https://docs.docker.com/get-started/#test-docker-installation), you can get ODM by running from a Command Prompt / Terminal: -```bash -docker pull webodm/odm -``` +## Quickstart -Run ODM by placing some images (JPEGs, TIFFs or DNGs) in a folder named “images” (for example `C:\Users\youruser\datasets\project\images` or `/home/youruser/datasets/project/images`) and simply run from a Command Prompt / Terminal: +The easiest way to run ODM is via docker. To install docker, see [docs.docker.com](https://docs.docker.com). Once you have docker installed place some images (JPEGs, TIFFs or DNGs) in a folder named “images” (for example `C:\Users\youruser\datasets\project\images` or `/home/youruser/datasets/project/images`) and run from a terminal: ```bash # Windows docker run -ti --rm -v c:/Users/youruser/datasets:/datasets webodm/odm --project-path /datasets project ``` + ```bash # Mac/Linux docker run -ti --rm -v /home/youruser/datasets:/datasets webodm/odm --project-path /datasets project @@ -55,14 +51,13 @@ docker run -ti --rm -v /datasets:/datasets webodm/odm --help When the process finishes, the results will be organized as follows: |-- images/ - |-- img-1234.jpg + |-- DJI_0001.jpg |-- ... |-- opensfm/ |-- see mapillary/opensfm repository for more info |-- odm_meshing/ |-- odm_mesh.ply # A 3D mesh |-- odm_texturing/ - |-- odm_textured_model.obj # Textured mesh |-- odm_textured_model_geo.obj # Georeferenced textured mesh |-- odm_georeferencing/ |-- odm_georeferenced_model.laz # LAZ format point cloud @@ -184,29 +179,12 @@ to ensure all the dependent packages and modules get updated. If you want to rebuild your own docker image (if you have changed the source code, for example), from the ODM folder you can type: ```bash -docker build -t my_odm_image --no-cache . -``` -When building your own Docker image, if image size is of importance to you, you should use the ```--squash``` flag, like so: - -```bash -docker build --squash -t my_odm_image . -``` - -This will clean up intermediate steps in the Docker build process, resulting in a significantly smaller image (about half the size). - -Experimental flags need to be enabled in Docker to use the ```--squash``` flag. To enable this, insert the following into the file `/etc/docker/daemon.json`: - -```json -{ - "experimental": true -} +docker build -t myodm --no-cache . ``` -After this, you must restart docker. - ## Video Support -Starting from version 3.0.4, ODM can automatically extract images from video files (.mp4, .mov, .lrv, .ts). Just place one or more video files into the `images` folder and run the program as usual. Subtitles files (.srt) with GPS information are also supported. Place .srt files in the `images` folder, making sure that the filenames match. For example, `my_video.mp4` ==> `my_video.srt` (case-sensitive). +ODM can automatically extract images from video files (.mp4, .mov, .lrv, .ts). Just place one or more video files into the `images` folder and run the program as usual. Subtitles files (.srt) with GPS information are also supported. Place .srt files in the `images` folder, making sure that the filenames match. For example, `my_video.mp4` ==> `my_video.srt` (case-sensitive). ## Developers @@ -214,6 +192,7 @@ Help improve our software! We welcome contributions from everyone, whether to ad ### Installation and first run + For Linux users, the easiest way to modify the software is to make sure docker is installed, clone the repository and then run from a shell: ```bash @@ -246,7 +225,6 @@ docker exec -ti odmdev bash su your_username ``` - If you have questions, join the #devtalk's channel on discord: https://webodm.org/community 1. Try to keep commits clean and simple @@ -264,7 +242,7 @@ In order to make a clean build, remove `~/.odm-dev-home` and `ODM/.setupdevenv`. ODM makes use of other awesome open source projects to perform its tasks. Among them we'd like to highlight: - - [OpenSfM](https://github.com/mapillary/OpenSfM) + - [OpenSfM](https://github.com/WebODM/OpenSfM) - [OpenMVS](https://github.com/cdcseacave/openMVS/) - [PDAL](https://github.com/PDAL/PDAL) - [Entwine](https://entwine.io/) diff --git a/SuperBuild/CMakeLists.txt b/SuperBuild/CMakeLists.txt index 15925e10..0ee6f441 100644 --- a/SuperBuild/CMakeLists.txt +++ b/SuperBuild/CMakeLists.txt @@ -112,7 +112,8 @@ elseif(APPLE) set(PYTHON_HOME "${SB_ROOT_DIR}/../venv") set(PYTHON_EXE_PATH "${PYTHON_HOME}/bin/python") else() - set(PYTHON_EXE_PATH "${PYTHON_HOME}/bin/python3") + set(PYTHON_EXE_PATH "/usr/bin/python3") + set(PYTHON_HOME "/usr/local/") endif() # Path to additional CMake modules diff --git a/SuperBuild/cmake/ExternalProject-Setup.cmake b/SuperBuild/cmake/ExternalProject-Setup.cmake index eea0b533..55b9cab5 100644 --- a/SuperBuild/cmake/ExternalProject-Setup.cmake +++ b/SuperBuild/cmake/ExternalProject-Setup.cmake @@ -1,5 +1,6 @@ set(ADD_INTERNAL_LIB_MSG "--- Adding internal version") set(FORCE_BUILD_LIB_MSG "force build ${ADD_INTERNAL_LIB_MSG}") +cmake_policy(SET CMP0135 NEW) macro(SETUP_EXTERNAL_PROJECT name version force_build) From b2f59c2506c082d190ea48b5d2f0f2d33180d044 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 02:20:30 -0400 Subject: [PATCH 18/29] Update README --- README.md | 43 ------------------------------------------- 1 file changed, 43 deletions(-) diff --git a/README.md b/README.md index b1bfe7d6..51df4a04 100644 --- a/README.md +++ b/README.md @@ -131,49 +131,6 @@ You're in good shape! See https://github.com/NVIDIA/nvidia-docker and https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker for information on docker/NVIDIA setup. -## Native Install (Ubuntu 24.04) - -You can run ODM natively on Ubuntu 24.04 (although we don't recommend it): - -```bash -git clone https://github.com/WebODM/ODM -cd ODM -bash configure.sh install -``` - -You can then process datasets with `./run.sh /datasets/odm_data_aukerman` - -## Native Install (MacOS) - -> **Warning:** Installation on Mac is currently unmaintained, and may not work out-of-the-box. See this [issue](https://community.opendronemap.org/t/odm-install-on-a-mac-os-14-6-1/25007/3). - -You can run ODM natively on Intel/ARM MacOS. - -First install: - - * Xcode 13 (not 14, there's currently a bug) - * [Homebrew](https://docs.brew.sh/Installation) - -Then Run: - -```bash -git clone https://github.com/WebODM/ODM -cd ODM -bash configure_macos.sh install -``` - -You can then process datasets with `./run.sh /datasets/odm_data_aukerman` - -This could be improved in the future. [Helps us create a Homebrew formula](https://github.com/WebODM/ODM/issues/1531). - -### Updating a native installation - -When updating to a newer version of native ODM, it is recommended that you run: - -`bash configure.sh reinstall` - -to ensure all the dependent packages and modules get updated. - ### Build Docker Images From Source If you want to rebuild your own docker image (if you have changed the source code, for example), from the ODM folder you can type: From dcf245c53f603a7b30ed27c839d69e2d8de7da3e Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 02:25:27 -0400 Subject: [PATCH 19/29] Update README --- README.md | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 51df4a04..befcb229 100644 --- a/README.md +++ b/README.md @@ -93,27 +93,22 @@ run C:\Users\youruser\datasets\project [--additional --parameters --here] ## GPU Acceleration -ODM has support for doing SIFT feature extraction on a GPU, which is about 2x faster than the CPU on a typical consumer laptop. To use this feature, you need to use the `webodm/odm:gpu` docker image instead of `webodm/odm:gpu` and you need to pass the `--gpus all` flag: +ODM has GPU support to speed up certain computations. To enable it, you need to use the `webodm/odm:gpu` docker image and you need to pass the `--gpus all` flag: ``` -docker run -ti --rm -v c:/Users/youruser/datasets:/datasets --gpus all webodm/odm:gpu --project-path /datasets project --feature-type sift +docker run -ti --rm -v c:/Users/youruser/datasets:/datasets --gpus all webodm/odm:gpu --project-path /datasets project ``` When you run ODM, if the GPU is recognized, in the first few lines of output you should see: ``` -[INFO] Writing exif overrides -[INFO] Maximum photo dimensions: 4000px -[INFO] Found GPU device: Intel(R) OpenCL HD Graphics -[INFO] Using GPU for extracting SIFT features +[INFO] nvidia-smi detected ``` -The SIFT GPU implementation is CUDA-based, so should work with most NVIDIA graphics cards of the GTX 9xx Generation or newer. - If you have an NVIDIA card, you can test that docker is recognizing the GPU by running: ``` -docker run --rm --gpus all nvidia/cuda:10.0-base nvidia-smi +docker run --rm --gpus all nvidia/cuda:13.0.0-base-ubuntu24.04 nvidia-smi ``` If you see an output that looks like this: @@ -129,11 +124,11 @@ Fri Jul 24 18:51:55 2020 You're in good shape! -See https://github.com/NVIDIA/nvidia-docker and https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker for information on docker/NVIDIA setup. +See https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html for information on docker/NVIDIA setup. -### Build Docker Images From Source +### Build Docker Images -If you want to rebuild your own docker image (if you have changed the source code, for example), from the ODM folder you can type: +If you want to rebuild your own docker image, from the `ODM` folder you can type: ```bash docker build -t myodm --no-cache . From 5b8a9023335c6dc281a8f86584b6e21c7c91382f Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 02:39:23 -0400 Subject: [PATCH 20/29] Fix PDALPython path --- Dockerfile | 8 ++++---- SuperBuild/cmake/External-PDALPython.cmake | 2 +- gpu.Dockerfile | 4 ++-- portable.Dockerfile | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2d2d9222..a8e2fcbd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,8 +2,8 @@ FROM ubuntu:24.04 AS builder # Env variables ENV DEBIAN_FRONTEND=noninteractive \ - PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ - LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/code/SuperBuild/install/lib" + PYTHONPATH="/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ + LD_LIBRARY_PATH="/code/SuperBuild/install/lib" # Prepare directories WORKDIR /code @@ -25,8 +25,8 @@ FROM ubuntu:24.04 # Env variables ENV DEBIAN_FRONTEND=noninteractive \ - PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/lib/python3.12:/code/SuperBuild/install/bin/opensfm" \ - LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/code/SuperBuild/install/lib" \ + PYTHONPATH="/code/SuperBuild/install/lib/python3.12:/code/SuperBuild/install/bin/opensfm" \ + LD_LIBRARY_PATH="/code/SuperBuild/install/lib" \ PDAL_DRIVER_PATH="/code/SuperBuild/install/bin" WORKDIR /code diff --git a/SuperBuild/cmake/External-PDALPython.cmake b/SuperBuild/cmake/External-PDALPython.cmake index f9108686..6c0970e5 100644 --- a/SuperBuild/cmake/External-PDALPython.cmake +++ b/SuperBuild/cmake/External-PDALPython.cmake @@ -7,7 +7,7 @@ if (WIN32) -DPython3_NumPy_INCLUDE_DIRS=${PYTHON_HOME}/Lib/site-packages/numpy/_core/include) else() set(PP_EXTRA_ARGS -DPython3_EXECUTABLE=${PYTHON_EXE_PATH} - -DPython3_NumPy_INCLUDE_DIRS=${PYTHON_HOME}/lib/python3.12/site-packages/numpy/_core/include) + -DPython3_NumPy_INCLUDE_DIRS=${PYTHON_HOME}/lib/python3.12/dist-packages/numpy/_core/include) endif() ExternalProject_Add(${_proj_name} diff --git a/gpu.Dockerfile b/gpu.Dockerfile index 2428fe0d..776e82f3 100644 --- a/gpu.Dockerfile +++ b/gpu.Dockerfile @@ -2,8 +2,8 @@ FROM nvidia/cuda:12.9.1-devel-ubuntu24.04 AS builder # Env variables ENV DEBIAN_FRONTEND=noninteractive \ - PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ - LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/code/SuperBuild/install/lib" + PYTHONPATH="/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ + LD_LIBRARY_PATH="/code/SuperBuild/install/lib" # Prepare directories WORKDIR /code diff --git a/portable.Dockerfile b/portable.Dockerfile index 91c6be20..0ff63e8e 100644 --- a/portable.Dockerfile +++ b/portable.Dockerfile @@ -2,8 +2,8 @@ FROM ubuntu:24.04 AS builder # Env variables ENV DEBIAN_FRONTEND=noninteractive \ - PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ - LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/code/SuperBuild/install/lib" + PYTHONPATH="/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ + LD_LIBRARY_PATH="/code/SuperBuild/install/lib" # Prepare directories WORKDIR /code @@ -25,8 +25,8 @@ FROM ubuntu:24.04 # Env variables ENV DEBIAN_FRONTEND=noninteractive \ - PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/lib/python3.12:/code/SuperBuild/install/bin/opensfm" \ - LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/code/SuperBuild/install/lib" \ + PYTHONPATH="/code/SuperBuild/install/lib/python3.12:/code/SuperBuild/install/bin/opensfm" \ + LD_LIBRARY_PATH="/code/SuperBuild/install/lib" \ PDAL_DRIVER_PATH="/code/SuperBuild/install/bin" WORKDIR /code From 080b5650435fd478a0307ad948956075b3ecd058 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 09:47:51 -0400 Subject: [PATCH 21/29] Use pierotofy pdal-python --- SuperBuild/cmake/External-PDALPython.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SuperBuild/cmake/External-PDALPython.cmake b/SuperBuild/cmake/External-PDALPython.cmake index 6c0970e5..7580eca6 100644 --- a/SuperBuild/cmake/External-PDALPython.cmake +++ b/SuperBuild/cmake/External-PDALPython.cmake @@ -17,8 +17,8 @@ ExternalProject_Add(${_proj_name} STAMP_DIR ${_SB_BINARY_DIR}/stamp #--Download step-------------- DOWNLOAD_DIR ${SB_DOWNLOAD_DIR} - GIT_REPOSITORY https://github.com/PDAL/python - GIT_TAG 6791a880a87e95f7318e99acfb4a10186379c5dd + GIT_REPOSITORY https://github.com/pierotofy/pdal-python + GIT_TAG 400 #--Update/Patch step---------- UPDATE_COMMAND git submodule update --init --recursive #--Configure step------------- From 6d512307688db02afe55b6fd5b34606b8442f3ec Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 10:41:22 -0400 Subject: [PATCH 22/29] Update OpenSfM, log changes --- SuperBuild/cmake/External-OpenSfM.cmake | 2 +- opendm/log.py | 2 +- opendm/mesh.py | 8 ++++---- opendm/osfm.py | 6 ++++-- opendm/system.py | 2 +- run.py | 10 ++-------- 6 files changed, 13 insertions(+), 17 deletions(-) diff --git a/SuperBuild/cmake/External-OpenSfM.cmake b/SuperBuild/cmake/External-OpenSfM.cmake index c78b586a..76716db1 100644 --- a/SuperBuild/cmake/External-OpenSfM.cmake +++ b/SuperBuild/cmake/External-OpenSfM.cmake @@ -25,7 +25,7 @@ ExternalProject_Add(${_proj_name} #--Download step-------------- DOWNLOAD_DIR ${SB_DOWNLOAD_DIR} GIT_REPOSITORY https://github.com/WebODM/OpenSfM/ - GIT_TAG b0f0f6df946a4e3697208f224d43f30242f75dfc + GIT_TAG 9152c991884eb53b233917cfe3097833f860835c #--Update/Patch step---------- UPDATE_COMMAND git submodule update --init --recursive #--Configure step------------- diff --git a/opendm/log.py b/opendm/log.py index cac8a092..34ea6939 100644 --- a/opendm/log.py +++ b/opendm/log.py @@ -49,7 +49,7 @@ def __init__(self): self.start_time = datetime.datetime.now() def log(self, startc, msg, level_name): - level = ("[" + level_name + "]").ljust(9) + level = "[" + level_name + "]" with lock: print("%s%s %s%s" % (startc, level, msg, ENDC)) sys.stdout.flush() diff --git a/opendm/mesh.py b/opendm/mesh.py index 584458bf..26bc847f 100644 --- a/opendm/mesh.py +++ b/opendm/mesh.py @@ -160,7 +160,7 @@ def screened_poisson_reconstruction(inPointCloud, outMesh, depth = 8, samples = 'depth': depth, 'samples': samples, 'pointWeight': pointWeight, - 'threads': int(threads) + 'parallel': '--parallel 2' if threads <= 1 else '' } # Run PoissonRecon @@ -170,9 +170,9 @@ def screened_poisson_reconstruction(inPointCloud, outMesh, depth = 8, samples = '--depth {depth} ' '--pointWeight {pointWeight} ' '--samplesPerNode {samples} ' - '--threads {threads} ' - '--bType 2 ' - '--linearFit '.format(**poissonReconArgs)) + '--density ' + '{parallel} ' + '--confidence'.format(**poissonReconArgs), env_vars={'OMP_NUM_THREADS': int(threads)}) except Exception as e: log.ODM_WARNING(str(e)) diff --git a/opendm/osfm.py b/opendm/osfm.py index 5db25706..c011704c 100644 --- a/opendm/osfm.py +++ b/opendm/osfm.py @@ -203,11 +203,11 @@ def setup(self, args, images_path, reconstruction, append_config = [], rerun=Fal feature_process_size = 2048 # default feature_quality_scale = { - 'ultra': 1, + 'ultra': 1.0, 'high': 0.5, 'medium': 0.25, 'low': 0.125, - 'lowest': 0.0675, + 'lowest': 0.0625 } max_dims = find_largest_photo_dims(photos) @@ -247,6 +247,8 @@ def setup(self, args, images_path, reconstruction, append_config = [], rerun=Fal matcher_neighbors = 3 config = [ + "report_name: ODM", + "report_version: %s" % log.odm_version(), "use_exif_size: no", "flann_algorithm: KDTREE", # more stable, faster than KMEANS "feature_process_size: %s" % feature_process_size, diff --git a/opendm/system.py b/opendm/system.py index 1ad88a52..18be2129 100644 --- a/opendm/system.py +++ b/opendm/system.py @@ -173,4 +173,4 @@ def delete_files(folder, exclude=()): for f in os.listdir(folder): if os.path.isfile(os.path.join(folder, f)): if not exclude or not f.endswith(exclude): - os.unlink(os.path.join(folder, f)) \ No newline at end of file + os.unlink(os.path.join(folder, f)) diff --git a/run.py b/run.py index 9ca1e75b..61685c8f 100755 --- a/run.py +++ b/run.py @@ -17,17 +17,12 @@ from stages.odm_app import ODMApp -def odm_version(): - try: - with open("VERSION") as f: - return f.read().split("\n")[0].strip() - except: - return "?" + if __name__ == '__main__': args = config.config() - log.ODM_INFO('Initializing ODM %s - %s' % (odm_version(), system.now())) + log.ODM_INFO('Initializing ODM %s - %s' % (log.odm_version(), system.now())) progressbc.set_project_name(args.name) args.project_path = os.path.join(args.project_path, args.name) @@ -69,7 +64,6 @@ def odm_version(): # Do not show end message for local submodels runs if retcode == 0 and not "submodels" in args.project_path: - log.ODM_INFO('Done! d-(^_^)z') log.ODM_INFO('ODM app finished - %s' % system.now()) else: exit(retcode) \ No newline at end of file From ceb0a708af113fda2542c7febba2c5e74bd2166b Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 10:47:31 -0400 Subject: [PATCH 23/29] Test GPU build --- .github/workflows/test-build-prs.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/test-build-prs.yml b/.github/workflows/test-build-prs.yml index 412ac895..259e3de2 100644 --- a/.github/workflows/test-build-prs.yml +++ b/.github/workflows/test-build-prs.yml @@ -24,6 +24,26 @@ jobs: platforms: linux/amd64 push: false + docker_gpu: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Set Swap Space + uses: pierotofy/set-swap-space@master + with: + swap-size-gb: 12 + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Build + uses: docker/build-push-action@v2 + with: + file: ./gpu.Dockerfile + platforms: linux/amd64 + push: false + windows: runs-on: windows-2022 steps: From 26b8bec3772e6790f066d91e943096e16de0cea2 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 11:56:41 -0400 Subject: [PATCH 24/29] Checkpoints support --- SuperBuild/cmake/External-Ceres.cmake | 1 + opendm/gcp.py | 15 ++++++++++++++- stages/dataset.py | 3 +++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/SuperBuild/cmake/External-Ceres.cmake b/SuperBuild/cmake/External-Ceres.cmake index 3bb8d215..e1591e79 100644 --- a/SuperBuild/cmake/External-Ceres.cmake +++ b/SuperBuild/cmake/External-Ceres.cmake @@ -18,6 +18,7 @@ ExternalProject_Add(${_proj_name} -DCMAKE_CXX_FLAGS=-fPIC -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF + -DUSE_CUDA=OFF -DMINIGLOG=ON -DMINIGLOG_MAX_LOG_LEVEL=-100 -DCMAKE_INSTALL_PREFIX:PATH=${SB_INSTALL_DIR} diff --git a/opendm/gcp.py b/opendm/gcp.py index 31f19316..a3f84b9a 100644 --- a/opendm/gcp.py +++ b/opendm/gcp.py @@ -79,7 +79,17 @@ def get_entry(self, n): def entries_count(self): return len(self.entries) - + + def checkpoints_count(self): + c = 0 + for entry in self.iter_entries(): + if entry.is_checkpoint(): + c += 1 + return c + + def only_checkpoints(self): + return self.checkpoints_count() == self.entries_count() + def exists(self): return bool(self.gcp_path and os.path.exists(self.gcp_path)) @@ -237,6 +247,9 @@ def __init__(self, x, y, z, px, py, filename, extras=""): def coords_key(self): return "{} {} {}".format(self.x, self.y, self.z) + def is_checkpoint(self): + return self.extras.upper().startswith("CHK-") + def __str__(self): return "{} {} {} {} {} {} {}".format(self.x, self.y, self.z, self.px, self.py, diff --git a/stages/dataset.py b/stages/dataset.py index 924b8c0a..78ad9d66 100644 --- a/stages/dataset.py +++ b/stages/dataset.py @@ -309,6 +309,9 @@ def parallel_bg_filter(item): tree.odm_georeferencing_gcp_utm, tree.odm_georeferencing_model_txt_geo, rerun=self.rerun()) + if reconstruction.gcp is not None and reconstruction.gcp.only_checkpoints(): + log.ODM_WARNING("Only checkpoints in this GCP file. Enabling --force-gps") + args.force_gps = True else: reconstruction.georeference_with_gps(tree.dataset_raw, tree.odm_georeferencing_coords, From 7c4d2c26fdf0732a5ad1611378f51ea299a92b61 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 13:38:50 -0400 Subject: [PATCH 25/29] Update workflow dispatch URL --- .github/workflows/publish-docker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml index d06ce3be..2d2e5654 100644 --- a/.github/workflows/publish-docker.yml +++ b/.github/workflows/publish-docker.yml @@ -104,5 +104,5 @@ jobs: - name: Dispatch Build Event id: build_dispatch run: | - curl -X POST -u "${{secrets.PAT_USERNAME}}:${{secrets.PAT_TOKEN}}" -H "Accept: application/vnd.github.everest-preview+json" -H "Content-Type: application/json" https://api.github.com/repos/WebODM/NodeODM/actions/workflows/publish-docker.yaml/dispatches --data '{"ref": "master"}' + curl -X POST -u "${{secrets.PAT_USERNAME}}:${{secrets.PAT_TOKEN}}" -H "Accept: application/vnd.github.everest-preview+json" -H "Content-Type: application/json" https://api.github.com/repos/WebODM/NodeODM/actions/workflows/publish-docker.yml/dispatches --data '{"ref": "master"}' curl -X POST -u "${{secrets.PAT_USERNAME}}:${{secrets.PAT_TOKEN}}" -H "Accept: application/vnd.github.everest-preview+json" -H "Content-Type: application/json" https://api.github.com/repos/WebODM/oats/actions/workflows/test.yaml/dispatches --data '{"ref": "master"}' \ No newline at end of file From 3f6d4e7327c649d9dc9258d2be033807a1a490ef Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 14:17:50 -0400 Subject: [PATCH 26/29] Update Badges --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index befcb229..c7377320 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # ODM +![Docker Build](https://img.shields.io/github/actions/workflow/status/WebODM/ODM/publish-docker.yml?branch=master) ![Docker GPU Build](https://img.shields.io/github/actions/workflow/status/WebODM/ODM/publish-docker.yml?branch=master) ![Docker GPU Build](https://img.shields.io/github/actions/workflow/status/WebODM/ODM/publish-windows.yml?branch=master) ![Version](https://img.shields.io/github/v/release/WebODM/ODM) ![License](https://img.shields.io/github/license/WebODM/ODM) ![Contributors](https://img.shields.io/github/contributors/WebODM/ODM) ![Updated](https://img.shields.io/github/last-commit/WebODM/ODM) + A free and open source photogrammetry engine for processing aerial and ground imagery. ODM turns images into: * Classified Point Clouds From cb9975ffb5c61f65de087a75f1202dc3f6a42a10 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 14:24:45 -0400 Subject: [PATCH 27/29] Fix indent --- opendm/gcp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opendm/gcp.py b/opendm/gcp.py index a3f84b9a..78b558ba 100644 --- a/opendm/gcp.py +++ b/opendm/gcp.py @@ -80,7 +80,7 @@ def get_entry(self, n): def entries_count(self): return len(self.entries) - def checkpoints_count(self): + def checkpoints_count(self): c = 0 for entry in self.iter_entries(): if entry.is_checkpoint(): From fef503ca40d4723a8ae0cb2f8c43c1d495d3ddc5 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 14:26:48 -0400 Subject: [PATCH 28/29] Dont fail dev setup if permissions fail --- start-dev-env.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/start-dev-env.sh b/start-dev-env.sh index 13e4f0aa..4e297d0a 100755 --- a/start-dev-env.sh +++ b/start-dev-env.sh @@ -12,8 +12,8 @@ if [ "$1" = "--setup" ]; then touch .setupdevenv apt update && apt install -y vim git - chown -R $3:$4 /code - chown -R $3:$4 /var/www + chown -R $3:$4 /code || true + chown -R $3:$4 /var/www || true fi echo "Adding $2 to /etc/passwd" From e28d9008e51afd5dcd585e5a5d4aef49066f5512 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 10 Apr 2026 14:50:43 -0400 Subject: [PATCH 29/29] Fix cropper --- opendm/cropper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opendm/cropper.py b/opendm/cropper.py index 29bfa62b..c7f75e8c 100644 --- a/opendm/cropper.py +++ b/opendm/cropper.py @@ -251,10 +251,10 @@ def create_bounds_gpkg(self, pointcloud_path, buffer_distance = 0, decimation_st kwargs = { 'input': double_quote(bounds_geojson_path), 'output': double_quote(bounds_gpkg_path), - 'wkt': pc_wkt + 'wkt': double_quote(pc_wkt) } - run('ogr2ogr -overwrite -f GPKG -a_srs "{pc_wkt}" {output} {input}'.format(**kwargs)) + run('ogr2ogr -overwrite -f GPKG -a_srs {wkt} {output} {input}'.format(**kwargs)) return bounds_gpkg_path