diff --git a/SuperBuild/CMakeLists.txt b/SuperBuild/CMakeLists.txt index d693a6c97..a2b46062d 100644 --- a/SuperBuild/CMakeLists.txt +++ b/SuperBuild/CMakeLists.txt @@ -177,6 +177,7 @@ set(custom_libs OpenSfM FPCFilter PyPopsift Obj2Tiles + OpenPointClass ) externalproject_add(mve diff --git a/SuperBuild/cmake/External-OpenPointClass.cmake b/SuperBuild/cmake/External-OpenPointClass.cmake new file mode 100644 index 000000000..953a259fc --- /dev/null +++ b/SuperBuild/cmake/External-OpenPointClass.cmake @@ -0,0 +1,33 @@ +set(_proj_name openpointclass) +set(_SB_BINARY_DIR "${SB_BINARY_DIR}/${_proj_name}") + +ExternalProject_Add(${_proj_name} + DEPENDS pdal eigen34 + 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/uav4geo/OpenPointClass + GIT_TAG v1.1.3 + #--Update/Patch step---------- + UPDATE_COMMAND "" + #--Configure step------------- + SOURCE_DIR ${SB_SOURCE_DIR}/${_proj_name} + CMAKE_ARGS + -DPDAL_DIR=${SB_INSTALL_DIR}/lib/cmake/PDAL + -DWITH_GBT=ON + -DBUILD_PCTRAIN=OFF + -DEIGEN3_INCLUDE_DIR=${SB_SOURCE_DIR}/eigen34/ + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_INSTALL_PREFIX:PATH=${SB_INSTALL_DIR} + ${WIN32_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 +) diff --git a/SuperBuild/cmake/External-PCL.cmake b/SuperBuild/cmake/External-PCL.cmake deleted file mode 100644 index c7322e2d3..000000000 --- a/SuperBuild/cmake/External-PCL.cmake +++ /dev/null @@ -1,55 +0,0 @@ -set(_proj_name pcl) -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} - URL https://github.com/PointCloudLibrary/pcl/archive/refs/tags/pcl-1.11.1.zip - #--Update/Patch step---------- - UPDATE_COMMAND "" - #--Configure step------------- - SOURCE_DIR ${SB_SOURCE_DIR}/${_proj_name} - CMAKE_ARGS - -DBUILD_features=OFF - -DBUILD_filters=OFF - -DBUILD_geometry=OFF - -DBUILD_keypoints=OFF - -DBUILD_outofcore=OFF - -DBUILD_people=OFF - -DBUILD_recognition=OFF - -DBUILD_registration=OFF - -DBUILD_sample_consensus=OFF - -DBUILD_segmentation=OFF - -DBUILD_features=OFF - -DBUILD_surface_on_nurbs=OFF - -DBUILD_tools=OFF - -DBUILD_tracking=OFF - -DBUILD_visualization=OFF - -DWITH_OPENGL=OFF - -DWITH_VTK=OFF - -DWITH_QT=OFF - -DBUILD_OPENNI=OFF - -DBUILD_OPENNI2=OFF - -DWITH_OPENNI=OFF - -DWITH_OPENNI2=OFF - -DWITH_FZAPI=OFF - -DWITH_LIBUSB=OFF - -DWITH_PCAP=OFF - -DWITH_PXCAPI=OFF - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -DPCL_VERBOSITY_LEVEL=Error - -DCMAKE_INSTALL_PREFIX:PATH=${SB_INSTALL_DIR} - -DPCL_BUILD_WITH_FLANN_DYNAMIC_LINKING_WIN32=ON - ${WIN32_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 -) \ No newline at end of file diff --git a/opendm/config.py b/opendm/config.py index 415829b10..c9ee57874 100755 --- a/opendm/config.py +++ b/opendm/config.py @@ -344,7 +344,7 @@ def config(argv=None, parser=None): action=StoreTrue, nargs=0, default=False, - help='Classify the point cloud outputs using a Simple Morphological Filter. ' + help='Classify the point cloud outputs. ' 'You can control the behavior of this option by tweaking the --dem-* parameters. ' 'Default: ' '%(default)s') diff --git a/opendm/gpu.py b/opendm/gpu.py index fa0712dc1..2b4236141 100644 --- a/opendm/gpu.py +++ b/opendm/gpu.py @@ -16,18 +16,15 @@ def has_popsift_and_can_handle_texsize(width, height): compute_major, compute_minor = get_cuda_compute_version(0) if compute_major < 3 or (compute_major == 3 and compute_minor < 5): # Not supported - log.ODM_WARNING("CUDA compute platform is not supported (detected: %s.%s but we need at least 3.5)" % (compute_major, compute_minor)) + log.ODM_INFO("CUDA compute platform is not supported (detected: %s.%s but we need at least 3.5)" % (compute_major, compute_minor)) return False except Exception as e: - log.ODM_WARNING("Cannot use GPU for feature extraction: %s" % str(e)) + log.ODM_INFO("Using CPU for feature extraction: %s" % str(e)) return False try: from opensfm import pypopsift - fits = pypopsift.fits_texture(int(width * 1.02), int(height * 1.02)) - if not fits: - log.ODM_WARNING("Image size (%sx%spx) would not fit in GPU memory, try lowering --feature-quality. Falling back to CPU" % (width, height)) - return fits + return pypopsift.fits_texture(int(width * 1.02), int(height * 1.02)) except (ModuleNotFoundError, ImportError): return False except Exception as e: @@ -91,5 +88,4 @@ def has_gpu(args): log.ODM_INFO("nvidia-smi detected") return True else: - log.ODM_INFO("nvidia-smi not found in PATH, using CPU") return False diff --git a/opendm/opc.py b/opendm/opc.py new file mode 100644 index 000000000..4ca3d8e44 --- /dev/null +++ b/opendm/opc.py @@ -0,0 +1,31 @@ +import os +from opendm.ai import get_model +from opendm import log +from opendm.system import run +from opendm import io + +def classify(point_cloud): + tmp_output = io.related_file_path(point_cloud, postfix=".classified") + if os.path.isfile(tmp_output): + os.remove(tmp_output) + + try: + model = get_model("openpointclass", + "https://github.com/uav4geo/OpenPointClass/releases/download/v1.1.3/vehicles-vegetation-buildings.zip", + "v1.0.0", + name="model.bin") + + if model is not None: + run('pcclassify "%s" "%s" "%s" -u -s 2,64' % (point_cloud, tmp_output, model)) + + if os.path.isfile(tmp_output): + os.remove(point_cloud) + os.rename(tmp_output, point_cloud) + else: + log.ODM_WARNING("Cannot classify using OpenPointClass (no output generated)") + else: + log.ODM_WARNING("Cannot download/access model from %s" % (model_url)) + + except Exception as e: + log.ODM_WARNING("Cannot classify using OpenPointClass: %s" % str(e)) + diff --git a/stages/dataset.py b/stages/dataset.py index c7b84ab9d..a859180b4 100644 --- a/stages/dataset.py +++ b/stages/dataset.py @@ -330,3 +330,8 @@ def parallel_bg_filter(item): log.ODM_WARNING("No omega/phi/kappa angles found in input photos (%s), switching sfm-algorithm to incremental" % p.filename) args.sfm_algorithm = 'incremental' break + + # Rolling shutter cannot be done in non-georeferenced datasets + if args.rolling_shutter and not reconstruction.is_georeferenced(): + log.ODM_WARNING("Reconstruction is not georeferenced, disabling rolling shutter correction") + args.rolling_shutter = False diff --git a/stages/odm_dem.py b/stages/odm_dem.py index 91c3e41f5..9a6b3a966 100755 --- a/stages/odm_dem.py +++ b/stages/odm_dem.py @@ -12,7 +12,7 @@ from opendm import pseudogeo from opendm.tiles.tiler import generate_dem_tiles from opendm.cogeo import convert_to_cogeo - +from opendm.opc import classify class ODMDEMStage(types.ODM_Stage): def process(self, args, outputs): @@ -49,7 +49,7 @@ def process(self, args, outputs): pc_classify_marker = os.path.join(odm_dem_root, 'pc_classify_done.txt') if not io.file_exists(pc_classify_marker) or self.rerun(): - log.ODM_INFO("Classifying {} using Simple Morphological Filter".format(dem_input)) + log.ODM_INFO("Classifying {} using Simple Morphological Filter (1/2)".format(dem_input)) commands.classify(dem_input, args.smrf_scalar, args.smrf_slope, @@ -57,6 +57,9 @@ def process(self, args, outputs): args.smrf_window ) + log.ODM_INFO("Classifying {} using OpenPointClass (2/2)".format(dem_input)) + classify(dem_input) + with open(pc_classify_marker, 'w') as f: f.write('Classify: smrf\n') f.write('Scalar: {}\n'.format(args.smrf_scalar))