diff --git a/README.md b/README.md index cdf8650d..7495cc03 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,11 @@ instructions through "Create a Docker group". The Docker image workflow has equivalent procedures for Mac OS X and Windows found at [docs.docker.com](docs.docker.com). Then run the following command which will build a pre-built image and run on images found in `$(pwd)/images` (you can change this if you need to, see the [wiki](https://github.com/OpenDroneMap/OpenDroneMap/wiki/Docker) for more detailed instructions. ``` -docker run -it --rm -v $(pwd)/images:/code/images -v $(pwd)/odm_orthophoto:/code/odm_orthophoto -v $(pwd)/odm_texturing:/code/odm_texturing opendronemap/opendronemap +docker run -it --rm \ + -v "$(pwd)/images:/code/images" \ + -v "$(pwd)/odm_orthophoto:/code/odm_orthophoto" \ + -v "$(pwd)/odm_texturing:/code/odm_texturing" \ + opendronemap/opendronemap ``` ### Native Install (Ubuntu 16.04) @@ -126,7 +130,7 @@ When the process finishes, the results will be organized as follows: |-- texture_N.jpg # Associated textured images used by the model |-- odm_georeferencing/ |-- odm_georeferenced_model.ply # A georeferenced dense point cloud - |-- odm_georeferenced_model.ply.laz # LAZ format point cloud + |-- odm_georeferenced_model.laz # LAZ format point cloud |-- odm_georeferenced_model.csv # XYZ format point cloud |-- odm_georeferencing_log.txt # Georeferencing log |-- odm_georeferencing_transform.txt# Transform used for georeferencing @@ -155,12 +159,20 @@ installed on your machine. Docker software is free to install and use in this co see the [Docker Ubuntu installation tutorial](https://docs.docker.com/engine/installation/linux/ubuntulinux/) and follow the instructions through "Create a Docker group". Once Docker is installed, the fastest way to use OpenDroneMap is to run a pre-built image by typing: - docker run -it --rm -v $(pwd)/images:/code/images -v $(pwd)/odm_orthophoto:/code/odm_orthophoto -v $(pwd)/odm_texturing:/code/odm_texturing opendronemap/opendronemap + docker run -it --rm \ + -v "$(pwd)/images:/code/images" \ + -v "$(pwd)/odm_orthophoto:/code/odm_orthophoto" \ + -v "$(pwd)/odm_texturing:/code/odm_texturing" \ + opendronemap/opendronemap If you want to build your own Docker image from sources, type: docker build -t my_odm_image . - docker run -it --rm -v $(pwd)/images:/code/images -v $(pwd)/odm_orthophoto:/code/odm_orthophoto -v $(pwd)/odm_texturing:/code/odm_texturing my_odm_image + docker run -it --rm \ + -v "$(pwd)/images:/code/images" \ + -v "$(pwd)/odm_orthophoto:/code/odm_orthophoto" \ + -v "$(pwd)/odm_texturing:/code/odm_texturing" \ + my_odm_image Using this method, the containerized ODM will process the images in the OpenDroneMap/images directory and output results to the OpenDroneMap/odm_orthophoto and OpenDroneMap/odm_texturing directories as described in the [Viewing Results](https://github.com/OpenDroneMap/OpenDroneMap/wiki/Output-and-Results) section. @@ -168,19 +180,40 @@ If you want to view other results outside the Docker image simply add which dire established above. For example, if you're interested in the dense cloud results generated by PMVS and in the orthophoto, simply use the following `docker run` command after building the image: - docker run -it --rm -v $(pwd)/images:/code/images -v $(pwd)/odm_georeferencing:/code/odm_georeferencing -v $(pwd)/odm_orthophoto:/code/odm_orthophoto my_odm_image + docker run -it --rm \ + -v "$(pwd)/images:/code/images" \ + -v "$(pwd)/odm_georeferencing:/code/odm_georeferencing" \ + -v "$(pwd)/odm_orthophoto:/code/odm_orthophoto" \ + my_odm_image If you want to get all intermediate outputs, run the following command: - docker run -it --rm -v $(pwd)/images:/code/images -v $(pwd)/odm_georeferencing:/code/odm_georeferencing -v $(pwd)/odm_meshing:/code/odm_meshing -v $(pwd)/odm_orthophoto:/code/odm_orthophoto -v $(pwd)/odm_texturing:/code/odm_texturing -v $(pwd)/opensfm:/code/opensfm -v $(pwd)/pmvs:/code/pmvs opendronemap/opendronemap + docker run -it --rm \ + -v "$(pwd)/images:/code/images" \ + -v "$(pwd)/odm_georeferencing:/code/odm_georeferencing" \ + -v "$(pwd)/odm_meshing:/code/odm_meshing" \ + -v "$(pwd)/odm_orthophoto:/code/odm_orthophoto" \ + -v "$(pwd)/odm_texturing:/code/odm_texturing" \ + -v "$(pwd)/opensfm:/code/opensfm" \ + -v "$(pwd)/pmvs:/code/pmvs" \ + opendronemap/opendronemap To pass in custom parameters to the run.py script, simply pass it as arguments to the `docker run` command. For example: - docker run -it --rm -v $(pwd)/images:/code/images v $(pwd)/odm_orthophoto:/code/odm_orthophoto -v $(pwd)/odm_texturing:/code/odm_texturing opendronemap/opendronemap --resize-to 1800 --force-ccd 6.16 + docker run -it --rm \ + -v "$(pwd)/images:/code/images" \ + -v "$(pwd)/odm_orthophoto:/code/odm_orthophoto" \ + -v "$(pwd)/odm_texturing:/code/odm_texturing" \ + opendronemap/opendronemap --resize-to 1800 --force-ccd 6.16 If you want to pass in custom parameters using the settings.yaml file, you can pass it as a -v volume binding: - docker run -it --rm -v $(pwd)/images:/code/images v $(pwd)/odm_orthophoto:/code/odm_orthophoto -v $(pwd)/odm_texturing:/code/odm_texturing -v $(pwd)/settings.yaml:/code/settings.yaml opendronemap/opendronemap + docker run -it --rm \ + -v "$(pwd)/images:/code/images" \ + -v "$(pwd)/odm_orthophoto:/code/odm_orthophoto" \ + -v "$(pwd)/odm_texturing:/code/odm_texturing" \ + -v "$(pwd)/settings.yaml:/code/settings.yaml" \ + opendronemap/opendronemap When building your own Docker image, if image size is of importance to you, you should use the ```--squash``` flag, like so: @@ -203,7 +236,7 @@ A web interface and API to OpenDroneMap is currently under active development in ## Video Support -Currently we have an experimental feature that uses ORB_SLAM to render a textured mesh from video. It is only supported on Ubuntu 14.04 on machines with X11 support. See the [wiki](https://github.com/OpenDroneMap/OpenDroneMap/wiki/Reconstruction-from-Video)for details on installation and use. +Currently we have an experimental feature that uses ORB_SLAM to render a textured mesh from video. It is only supported on Ubuntu 14.04 on machines with X11 support. See the [wiki](https://github.com/OpenDroneMap/OpenDroneMap/wiki/Reconstruction-from-Video) for details on installation and use. ## Examples diff --git a/SuperBuild/CMakeLists.txt b/SuperBuild/CMakeLists.txt index 7b5cf6c0..51187869 100644 --- a/SuperBuild/CMakeLists.txt +++ b/SuperBuild/CMakeLists.txt @@ -124,6 +124,7 @@ set(custom_libs OpenGV CMVS Catkin Ecto + LASzip PDAL MvsTexturing ) diff --git a/SuperBuild/cmake/External-LASzip.cmake b/SuperBuild/cmake/External-LASzip.cmake new file mode 100644 index 00000000..c2e997eb --- /dev/null +++ b/SuperBuild/cmake/External-LASzip.cmake @@ -0,0 +1,29 @@ +set(_proj_name laszip) +set(_SB_BINARY_DIR "${SB_BINARY_DIR}/${_proj_name}") + +ExternalProject_Add(${_proj_name} + DEPENDS + PREFIX ${_SB_BINARY_DIR} + TMP_DIR ${_SB_BINARY_DIR}/tmp + STAMP_DIR ${_SB_BINARY_DIR}/stamp + #--Download step-------------- + DOWNLOAD_DIR ${SB_DOWNLOAD_DIR}/${_proj_name} + URL https://github.com/LASzip/LASzip/archive/master.zip + #--Update/Patch step---------- + UPDATE_COMMAND "" + #--Configure step------------- + SOURCE_DIR ${SB_SOURCE_DIR}/${_proj_name} + CMAKE_ARGS + -DBUILD_SHARED_LIBS=ON + -DBUILD_STATIC_LIBS=OFF + -DCMAKE_INSTALL_PREFIX=${SB_INSTALL_DIR} + -DCMAKE_INSTALL_LIBDIR=lib + #--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/SuperBuild/cmake/External-MvsTexturing.cmake b/SuperBuild/cmake/External-MvsTexturing.cmake index 0999c14d..a5eaa1f9 100644 --- a/SuperBuild/cmake/External-MvsTexturing.cmake +++ b/SuperBuild/cmake/External-MvsTexturing.cmake @@ -7,7 +7,7 @@ ExternalProject_Add(${_proj_name} TMP_DIR ${_SB_BINARY_DIR}/tmp STAMP_DIR ${_SB_BINARY_DIR}/stamp #--Download step-------------- - DOWNLOAD_DIR ${SB_DOWNLOAD_DIR} + DOWNLOAD_DIR ${SB_DOWNLOAD_DIR}/${_proj_name} URL https://github.com/OpenDroneMap/mvs-texturing/archive/master.zip #--Update/Patch step---------- UPDATE_COMMAND "" diff --git a/SuperBuild/cmake/External-PDAL.cmake b/SuperBuild/cmake/External-PDAL.cmake index 7a919804..685f1913 100644 --- a/SuperBuild/cmake/External-PDAL.cmake +++ b/SuperBuild/cmake/External-PDAL.cmake @@ -2,14 +2,13 @@ set(_proj_name pdal) set(_SB_BINARY_DIR "${SB_BINARY_DIR}/${_proj_name}") ExternalProject_Add(${_proj_name} - DEPENDS hexer + DEPENDS hexer laszip 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/PDAL/PDAL/archive/e881b581e3b91a928105d67db44c567f3b6d1afe.tar.gz - URL_MD5 cadbadf1c83d69d6525cfffd41473323 + URL https://github.com/PDAL/PDAL/releases/download/1.7.2/PDAL-1.7.2-src.tar.gz #--Update/Patch step---------- UPDATE_COMMAND "" #--Configure step------------- diff --git a/opendm/types.py b/opendm/types.py index 6008bf0c..e4d20036 100644 --- a/opendm/types.py +++ b/opendm/types.py @@ -255,16 +255,18 @@ class ODM_GeoRef(object): 'srs': self.projection.srs, 'json': json_file} - # create pipeline file transform.xml to enable transformation + # create pipeline file las.json to write odm_georeferenced_model.laz point cloud pipeline = '{{' \ ' "pipeline":[' \ ' "untransformed.ply",' \ ' {{' \ + ' "type":"writers.las",' \ ' "a_srs":"{srs}",' \ ' "offset_x":"{east}",' \ ' "offset_y":"{north}",' \ ' "offset_z":"0",' \ - ' "filename":"transformed.las"' \ + ' "compression":"laszip",' \ + ' "filename":"{f_out}"' \ ' }}' \ ' ]' \ '}}'.format(**kwargs) @@ -272,9 +274,14 @@ class ODM_GeoRef(object): with open(json_file, 'w') as f: f.write(pipeline) +<<<<<<< HEAD # call pdal system.run('{bin}/pdal pipeline -i {json} --readers.ply.filename={f_in} ' '--writers.las.filename={f_out}'.format(**kwargs)) +======= + # call pdal + system.run('{bin}/pdal pipeline -i {json} --readers.ply.filename={f_in}'.format(**kwargs)) +>>>>>>> 4a00c4d8411befc0c1b01a36f713e61633f002b3 def utm_to_latlon(self, _file, _photo, idx): @@ -484,8 +491,8 @@ class ODM_Tree(object): self.odm_georeferencing, 'odm_georeferenced_model.csv') self.odm_georeferencing_las_json = io.join_paths( self.odm_georeferencing, 'las.json') - self.odm_georeferencing_model_las = io.join_paths( - self.odm_georeferencing, 'odm_georeferenced_model.las') + self.odm_georeferencing_model_laz = io.join_paths( + self.odm_georeferencing, 'odm_georeferenced_model.laz') self.odm_georeferencing_dem = io.join_paths( self.odm_georeferencing, 'odm_georeferencing_model_dem.tif') diff --git a/scripts/odm_dem.py b/scripts/odm_dem.py index ec039eeb..7958fe91 100644 --- a/scripts/odm_dem.py +++ b/scripts/odm_dem.py @@ -28,7 +28,7 @@ class ODMDEMCell(ecto.Cell): # get inputs args = self.inputs.args tree = self.inputs.tree - las_model_found = io.file_exists(tree.odm_georeferencing_model_las) + las_model_found = io.file_exists(tree.odm_georeferencing_model_laz) # check if we rerun cell or not rerun_cell = (args.rerun is not None and @@ -40,7 +40,7 @@ class ODMDEMCell(ecto.Cell): log.ODM_INFO('Classify: ' + str(args.pc_classify != "none")) log.ODM_INFO('Create DSM: ' + str(args.dsm)) log.ODM_INFO('Create DTM: ' + str(args.dtm)) - log.ODM_INFO('DEM input file {0} found: {1}'.format(tree.odm_georeferencing_model_las, str(las_model_found))) + log.ODM_INFO('DEM input file {0} found: {1}'.format(tree.odm_georeferencing_model_laz, str(las_model_found))) # Setup terrain parameters terrain_params_map = { @@ -61,8 +61,8 @@ class ODMDEMCell(ecto.Cell): pc_classify_marker = os.path.join(odm_dem_root, 'pc_classify_done.txt') if not io.file_exists(pc_classify_marker) or rerun_cell: - log.ODM_INFO("Classifying {} using {}".format(tree.odm_georeferencing_model_las, args.pc_classify)) - commands.classify(tree.odm_georeferencing_model_las, + log.ODM_INFO("Classifying {} using {}".format(tree.odm_georeferencing_model_laz, args.pc_classify)) + commands.classify(tree.odm_georeferencing_model_laz, args.pc_classify == "smrf", slope, cellsize, @@ -96,7 +96,7 @@ class ODMDEMCell(ecto.Cell): for product in products: commands.create_dems( - [tree.odm_georeferencing_model_las], + [tree.odm_georeferencing_model_laz], product, radius=map(str, radius_steps), gapfill=True, diff --git a/scripts/odm_georeferencing.py b/scripts/odm_georeferencing.py index 054ba278..69a519e3 100644 --- a/scripts/odm_georeferencing.py +++ b/scripts/odm_georeferencing.py @@ -138,7 +138,7 @@ class ODMGeoreferencingCell(ecto.Cell): # convert ply model to LAS reference system geo_ref.convert_to_las(odm_georeferencing_model_ply_geo, - tree.odm_georeferencing_model_las, + tree.odm_georeferencing_model_laz, tree.odm_georeferencing_las_json) reconstruction.georef = geo_ref @@ -171,7 +171,7 @@ class ODMGeoreferencingCell(ecto.Cell): if args.crop > 0: log.ODM_INFO("Calculating cropping area and generating bounds shapefile from point cloud") cropper = Cropper(tree.odm_georeferencing, 'odm_georeferenced_model') - cropper.create_bounds_shapefile(tree.odm_georeferencing_model_las, args.crop) + cropper.create_bounds_shapefile(tree.odm_georeferencing_model_laz, args.crop) # Do not execute a second time, since # We might be doing georeferencing for diff --git a/tests/test_odm.py b/tests/test_odm.py index 648a657b..2604c315 100644 --- a/tests/test_odm.py +++ b/tests/test_odm.py @@ -136,7 +136,7 @@ class TestGeoreferencing(unittest.TestCase): def test_las_out(self): self.assertTrue(os.path.isfile(os.path.join(self.app.georeferencing.inputs.tree.odm_georeferencing, - "odm_georeferenced_model.ply.las"))) + "odm_georeferenced_model.laz"))) class TestOrthophoto(unittest.TestCase):