Merge pull request #1623 from pierotofy/class

Automated point classification and other improvements
pull/1631/head
Piero Toffanin 2023-03-20 23:41:28 -04:00 zatwierdzone przez GitHub
commit 6a7ab131ca
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
8 zmienionych plików z 79 dodań i 65 usunięć

Wyświetl plik

@ -177,6 +177,7 @@ set(custom_libs OpenSfM
FPCFilter
PyPopsift
Obj2Tiles
OpenPointClass
)
externalproject_add(mve

Wyświetl plik

@ -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
)

Wyświetl plik

@ -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
)

Wyświetl plik

@ -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')

Wyświetl plik

@ -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

31
opendm/opc.py 100644
Wyświetl plik

@ -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))

Wyświetl plik

@ -330,3 +330,8 @@ class ODMLoadDatasetStage(types.ODM_Stage):
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

Wyświetl plik

@ -12,7 +12,7 @@ from opendm.cropper import Cropper
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 @@ class ODMDEMStage(types.ODM_Stage):
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 @@ class ODMDEMStage(types.ODM_Stage):
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))