diff --git a/SuperBuild/cmake/External-OpenSfM.cmake b/SuperBuild/cmake/External-OpenSfM.cmake index 1ccc5ed0..058caef5 100644 --- a/SuperBuild/cmake/External-OpenSfM.cmake +++ b/SuperBuild/cmake/External-OpenSfM.cmake @@ -9,7 +9,7 @@ ExternalProject_Add(${_proj_name} #--Download step-------------- DOWNLOAD_DIR ${SB_DOWNLOAD_DIR} GIT_REPOSITORY https://github.com/OpenDroneMap/OpenSfM/ - GIT_TAG 241 + GIT_TAG gpu #--Update/Patch step---------- UPDATE_COMMAND git submodule update --init --recursive #--Configure step------------- diff --git a/gpu.Dockerfile b/gpu.Dockerfile new file mode 100644 index 00000000..752bdad0 --- /dev/null +++ b/gpu.Dockerfile @@ -0,0 +1,46 @@ +FROM nvidia/cuda:11.2.0-runtime-ubuntu20.04 AS builder + +# Env variables +ENV DEBIAN_FRONTEND=noninteractive \ + PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/lib/python3.8/dist-packages:/code/SuperBuild/src/opensfm" \ + LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/code/SuperBuild/install/lib" + +# Prepare directories +WORKDIR /code + +# Copy everything +COPY . ./ + +# Run the build +RUN bash configure.sh install + +# Clean Superbuild +RUN bash configure.sh clean + +### END Builder + +### Use a second image for the final asset to reduce the number and +# size of the layers. +FROM nvidia/cuda:11.2.0-runtime-ubuntu20.04 + +# Env variables +ENV DEBIAN_FRONTEND=noninteractive \ + PYTHONPATH="$PYTHONPATH:/code/SuperBuild/install/lib/python3.8/dist-packages:/code/SuperBuild/src/opensfm" \ + LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/code/SuperBuild/install/lib" + +WORKDIR /code + +# Copy everything we built from the builder +COPY --from=builder /code /code + +# 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! +RUN bash configure.sh installruntimedepsonly \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# Entry point +ENTRYPOINT ["python3", "/code/run.py"] diff --git a/opendm/gpu.py b/opendm/gpu.py new file mode 100644 index 00000000..173010c2 --- /dev/null +++ b/opendm/gpu.py @@ -0,0 +1,15 @@ +import os, subprocess +from opendm import log +from repoze.lru import lru_cache + +@lru_cache(maxsize=None) +def has_gpus(): + import pyopencl + + try: + platforms = pyopencl.get_platforms() + print(platforms) + exit(1) + except Exception as e: + print(e) + return False diff --git a/opendm/osfm.py b/opendm/osfm.py index a3a48342..5abebfc0 100644 --- a/opendm/osfm.py +++ b/opendm/osfm.py @@ -17,7 +17,7 @@ from opensfm.actions import undistort from opensfm.dataset import DataSet from opensfm import report from opendm.multispectral import get_photos_by_band - +from opendm.gpu import has_gpus class OSFMContext: def __init__(self, opensfm_project_path): @@ -214,6 +214,14 @@ class OSFMContext: log.ODM_WARNING("Using BOW matching, will use HAHOG feature type, not SIFT") feature_type = "HAHOG" + # GPU acceleration? + if has_gpus() and feature_type == "SIFT": + log.ODM_INFO("Using GPU for extracting SIFT features") + feature_type = "SIFT_GPU" + + # TODO: REMOVE + config.append("matcher_type: SIFT_GPU") + config.append("feature_type: %s" % feature_type) if has_alt: diff --git a/requirements.txt b/requirements.txt index 8c852e51..783f4d04 100644 --- a/requirements.txt +++ b/requirements.txt @@ -27,3 +27,5 @@ scikit-image==0.17.2 scipy==1.5.4 xmltodict==0.12.0 fpdf2==2.2.0rc2 +silx>=0.12.0 +pyopencl==2021.1.1 \ No newline at end of file diff --git a/start-dev-env.sh b/start-dev-env.sh index 323b9fe5..ff832d6e 100755 --- a/start-dev-env.sh +++ b/start-dev-env.sh @@ -90,6 +90,7 @@ fi export PORT="${PORT:=3000}" export QTC="${QTC:=NO}" export IMAGE="${IMAGE:=opendronemap/nodeodm}" +export GPU="${GPU:=NO}" if [ -z "$DATA" ]; then echo "Usage: DATA=/path/to/datasets [VARS] $0" @@ -98,6 +99,7 @@ if [ -z "$DATA" ]; then echo " DATA Path to directory that contains datasets for testing. The directory will be mounted in /datasets. If you don't have any, simply set it to a folder outside the ODM repository." echo " PORT Port to expose for NodeODM (default: $PORT)" echo " IMAGE Docker image to use (default: $IMAGE)" + echo " GPU Enable GPU support (default: $GPU)" echo " QTC When set to YES, installs QT Creator for C++ development (default: $QTC)" exit 1 fi @@ -108,6 +110,7 @@ echo "Datasets path: $DATA" echo "Expose port: $PORT" echo "QT Creator: $QTC" echo "Image: $IMAGE" +echo "GPU: $GPU" if [ ! -e "$HOME"/.odm-dev-home ]; then mkdir -p "$HOME"/.odm-dev-home @@ -116,6 +119,11 @@ fi USER_ID=$(id -u) GROUP_ID=$(id -g) USER=$(id -un) +GPU_FLAG="" +if [[ "$GPU" != "NO" ]]; then + GPU_FLAG="--gpus all" +fi + xhost + || true -docker run -ti --entrypoint bash --name odmdev -v $(pwd):/code -v "$DATA":/datasets -p $PORT:3000 --privileged -e DISPLAY -e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 -v="/tmp/.X11-unix:/tmp/.X11-unix:rw" -v="$HOME/.odm-dev-home:/home/$USER" $IMAGE -c "/code/start-dev-env.sh --setup $USER $USER_ID $GROUP_ID $QTC" +docker run -ti --entrypoint bash --name odmdev -v $(pwd):/code -v "$DATA":/datasets -p $PORT:3000 $GPU_FLAG --privileged -e DISPLAY -e LANG=C.UTF-8 -e LC_ALL=C.UTF-8 -v="/tmp/.X11-unix:/tmp/.X11-unix:rw" -v="$HOME/.odm-dev-home:/home/$USER" $IMAGE -c "/code/start-dev-env.sh --setup $USER $USER_ID $GROUP_ID $QTC" exit 0