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..2d2e5654 --- /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.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 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..259e3de2 100644 --- a/.github/workflows/test-build-prs.yaml +++ b/.github/workflows/test-build-prs.yml @@ -24,30 +24,26 @@ 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' - + 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: diff --git a/Dockerfile b/Dockerfile index 70ae94ac..a8e2fcbd 100644 --- a/Dockerfile +++ b/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="/code/SuperBuild/install/lib/python3.12/dist-packages:/code/SuperBuild/install/bin/opensfm" \ LD_LIBRARY_PATH="/code/SuperBuild/install/lib" # Prepare directories @@ -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 @@ -29,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="/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" @@ -38,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/README.md b/README.md index 9a0fd05b..c7377320 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,30 @@ -An open source command line toolkit for processing aerial drone imagery. ODM turns simple 2D images into: +# 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 * 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 @@ -53,14 +53,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 @@ -96,27 +95,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: @@ -132,79 +126,19 @@ 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. - -## 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) +See https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html for information on docker/NVIDIA setup. -Then Run: +### Build Docker Images -```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: +If you want to rebuild your own docker image, from the `ODM` folder you can type: ```bash -docker build -t my_odm_image --no-cache . +docker build -t myodm --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 -} -``` - -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 @@ -212,6 +146,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 @@ -244,7 +179,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 @@ -262,7 +196,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 39a05805..0ee6f441 100644 --- a/SuperBuild/CMakeLists.txt +++ b/SuperBuild/CMakeLists.txt @@ -111,15 +111,9 @@ 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") + set(PYTHON_EXE_PATH "/usr/bin/python3") + set(PYTHON_HOME "/usr/local/") endif() # Path to additional CMake modules @@ -132,19 +126,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 +153,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) # @@ -190,7 +166,6 @@ set(custom_libs OpenSfM MvsTexturing OpenMVS FPCFilter - PyPopsift Obj2Tiles OpenPointClass ExifTool @@ -198,8 +173,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 +200,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 +212,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 +222,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 +232,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 +242,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 +251,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..e1591e79 100644 --- a/SuperBuild/cmake/External-Ceres.cmake +++ b/SuperBuild/cmake/External-Ceres.cmake @@ -8,10 +8,9 @@ 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 #--Configure step------------- SOURCE_DIR ${SB_SOURCE_DIR}/${_proj_name} CMAKE_ARGS @@ -19,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/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..76716db1 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 9152c991884eb53b233917cfe3097833f860835c #--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..5a0d0d5e 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 @@ -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/SuperBuild/cmake/External-PDALPython.cmake b/SuperBuild/cmake/External-PDALPython.cmake index f9108686..7580eca6 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} @@ -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------------- 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/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) 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, 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..8bf1bd33 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,40 +240,33 @@ 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 } + 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 +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/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/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/gpu.Dockerfile b/gpu.Dockerfile index 437d780f..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/local/lib/python3.12/dist-packages:/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 @@ -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 @@ -29,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" @@ -38,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/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/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/cropper.py b/opendm/cropper.py index 77c69750..c7f75e8c 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': double_quote(pc_wkt) } - run('ogr2ogr -overwrite -f GPKG -a_srs "{proj4}" {output} {input}'.format(**kwargs)) + run('ogr2ogr -overwrite -f GPKG -a_srs {wkt} {output} {input}'.format(**kwargs)) return bounds_gpkg_path diff --git a/opendm/cutline.py b/opendm/cutline.py index 692bbebd..bdfdf2fd 100644 --- a/opendm/cutline.py +++ b/opendm/cutline.py @@ -146,24 +146,26 @@ 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': {}, - 'geometry': 'MultiPolygon' + 'geometry': 'Polygon' } } 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/opendm/gcp.py b/opendm/gcp.py index 31f19316..78b558ba 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/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/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/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/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/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/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/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..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(round(altitude)) + gps_ifd[piexif.GPSIFD.GPSAltitude] = float_to_rational(round(altitude * 1000) / 1000) return gps_ifd \ No newline at end of file diff --git a/portable.Dockerfile b/portable.Dockerfile index 27c459a0..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/local/lib/python3.12/dist-packages:/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 @@ -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 @@ -29,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="$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 @@ -38,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/requirements.txt b/requirements.txt index 2eb06d3f..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/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/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,8 +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/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/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 @@ -26,7 +29,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..61685c8f 100755 --- a/run.py +++ b/run.py @@ -1,3 +1,5 @@ +#!/usr/bin/python3 + # Basic check import sys if sys.version_info.major < 3: @@ -15,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) @@ -65,49 +62,8 @@ 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('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/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, 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? diff --git a/stages/splitmerge.py b/stages/splitmerge.py index 1b69c3f8..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() @@ -265,7 +262,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: 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"