From 29a346c6aa22d39c1c4eb06017e582e0f9435888 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Wed, 13 Jan 2021 22:22:44 +0000 Subject: [PATCH] Remove --use-opensfm-dense, add more stats data for report, diagram --- opendm/config.py | 35 ---------- opendm/osfm.py | 4 -- opendm/report/overlap_color_map.txt | 7 ++ opendm/report/overlap_diagram_legend.png | Bin 0 -> 8113 bytes opendm/types.py | 1 - stages/dataset.py | 16 ----- stages/odm_app.py | 2 +- stages/odm_filterpoints.py | 2 - stages/odm_report.py | 81 ++++++++++++++++++++--- stages/openmvs.py | 2 + stages/run_opensfm.py | 10 +-- 11 files changed, 82 insertions(+), 78 deletions(-) create mode 100644 opendm/report/overlap_color_map.txt create mode 100644 opendm/report/overlap_diagram_legend.png diff --git a/opendm/config.py b/opendm/config.py index 15492af2..99e9520f 100755 --- a/opendm/config.py +++ b/opendm/config.py @@ -236,35 +236,6 @@ def config(argv=None, parser=None): 'but produce denser point clouds. ' 'Default: %(default)s')) - parser.add_argument('--opensfm-depthmap-min-consistent-views', - metavar='', - action=StoreValue, - type=int, - default=3, - help=('Minimum number of views that should reconstruct a point for it to be valid. Use lower values ' - 'if your images have less overlap. Lower values result in denser point clouds ' - 'but with more noise. ' - 'Default: %(default)s')) - - parser.add_argument('--opensfm-depthmap-method', - metavar='', - action=StoreValue, - default='PATCH_MATCH', - choices=['PATCH_MATCH', 'BRUTE_FORCE', 'PATCH_MATCH_SAMPLE'], - help=('Raw depthmap computation algorithm. ' - 'PATCH_MATCH and PATCH_MATCH_SAMPLE are faster, but might miss some valid points. ' - 'BRUTE_FORCE takes longer but produces denser reconstructions. ' - 'Default: %(default)s')) - - parser.add_argument('--opensfm-depthmap-min-patch-sd', - metavar='', - action=StoreValue, - type=float, - default=1, - help=('When using PATCH_MATCH or PATCH_MATCH_SAMPLE, controls the standard deviation threshold to include patches. ' - 'Patches with lower standard deviation are ignored. ' - 'Default: %(default)s')) - parser.add_argument('--use-hybrid-bundle-adjustment', action=StoreTrue, nargs=0, @@ -284,12 +255,6 @@ def config(argv=None, parser=None): default=False, help='Skip generation of a full 3D model. This can save time if you only need 2D results such as orthophotos and DEMs. Default: %(default)s') - parser.add_argument('--use-opensfm-dense', - action=StoreTrue, - nargs=0, - default=False, - help='Use OpenSfM to compute the dense point cloud instead of OpenMVS. Default: %(default)s') - parser.add_argument('--ignore-gsd', action=StoreTrue, nargs=0, diff --git a/opendm/osfm.py b/opendm/osfm.py index 99fa7d75..d226df98 100644 --- a/opendm/osfm.py +++ b/opendm/osfm.py @@ -185,10 +185,6 @@ class OSFMContext: "processes: %s" % args.max_concurrency, "matching_gps_neighbors: %s" % args.matcher_neighbors, "matching_gps_distance: %s" % args.matcher_distance, - "depthmap_method: %s" % args.opensfm_depthmap_method, - "depthmap_resolution: %s" % depthmap_resolution, - "depthmap_min_patch_sd: %s" % args.opensfm_depthmap_min_patch_sd, - "depthmap_min_consistent_views: %s" % args.opensfm_depthmap_min_consistent_views, "optimize_camera_parameters: %s" % ('no' if args.use_fixed_camera_params or args.cameras else 'yes'), "undistorted_image_format: tif", "bundle_outlier_filtering_type: AUTO", diff --git a/opendm/report/overlap_color_map.txt b/opendm/report/overlap_color_map.txt new file mode 100644 index 00000000..924fc9b0 --- /dev/null +++ b/opendm/report/overlap_color_map.txt @@ -0,0 +1,7 @@ +# QGIS Generated Color Map Export File +2,215,25,28,255,2 +3,246,201,5,255,3 +4,117,188,39,255,4 +5,26,150,65,255,5+ +inf,26,150,65,255,> 5 +nv 0 0 0 0 diff --git a/opendm/report/overlap_diagram_legend.png b/opendm/report/overlap_diagram_legend.png new file mode 100644 index 0000000000000000000000000000000000000000..6136e438da683c758d7b6ef05a9438ebe38e6de0 GIT binary patch literal 8113 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 Q-0L7_MplMb^!G;o3zPmpi2wiq literal 0 HcmV?d00001 diff --git a/opendm/types.py b/opendm/types.py index 10b3b76d..39e1814c 100644 --- a/opendm/types.py +++ b/opendm/types.py @@ -243,7 +243,6 @@ class ODM_Tree(object): self.opensfm_image_list = os.path.join(self.opensfm, 'image_list.txt') self.opensfm_reconstruction = os.path.join(self.opensfm, 'reconstruction.json') self.opensfm_reconstruction_nvm = os.path.join(self.opensfm, 'undistorted/reconstruction.nvm') - self.opensfm_model = os.path.join(self.opensfm, 'undistorted/depthmaps/merged.ply') self.opensfm_transformation = os.path.join(self.opensfm, 'geocoords_transformation.txt') # OpenMVS diff --git a/stages/dataset.py b/stages/dataset.py index 809ee49b..4dbdc195 100644 --- a/stages/dataset.py +++ b/stages/dataset.py @@ -135,22 +135,6 @@ class ODMLoadDatasetStage(types.ODM_Stage): log.ODM_INFO('Found %s usable images' % len(photos)) - # TODO: add support for masks in OpenMVS - has_mask = False - for p in photos: - if p.mask is not None: - has_mask = True - break - - if has_mask and not args.use_opensfm_dense and not args.fast_orthophoto: - log.ODM_WARNING("Image masks found, will use OpenSfM for dense reconstruction") - args.use_opensfm_dense = True - - # Remove OpenMVS from pipeline. Yep. - opensfm_stage = self.next_stage.next_stage.next_stage - opensfm_stage.next_stage = opensfm_stage.next_stage.next_stage - opensfm_stage.next_stage.prev_stage = opensfm_stage - # Create reconstruction object reconstruction = types.ODM_Reconstruction(photos) diff --git a/stages/odm_app.py b/stages/odm_app.py index 7b14c080..e6c5cee5 100644 --- a/stages/odm_app.py +++ b/stages/odm_app.py @@ -65,7 +65,7 @@ class ODMApp: .connect(merge) \ .connect(opensfm) - if args.use_opensfm_dense or args.fast_orthophoto: + if args.fast_orthophoto: opensfm.connect(filterpoints) else: opensfm.connect(openmvs) \ diff --git a/stages/odm_filterpoints.py b/stages/odm_filterpoints.py index 418b0e93..98902e59 100644 --- a/stages/odm_filterpoints.py +++ b/stages/odm_filterpoints.py @@ -18,8 +18,6 @@ class ODMFilterPoints(types.ODM_Stage): if not io.file_exists(tree.filtered_point_cloud) or self.rerun(): if args.fast_orthophoto: inputPointCloud = os.path.join(tree.opensfm, 'reconstruction.ply') - elif args.use_opensfm_dense: - inputPointCloud = tree.opensfm_model else: inputPointCloud = tree.openmvs_model diff --git a/stages/odm_report.py b/stages/odm_report.py index cebb46e5..861b0014 100644 --- a/stages/odm_report.py +++ b/stages/odm_report.py @@ -1,4 +1,7 @@ import os +import json +import math +import shutil from opendm import log from opendm import io @@ -8,7 +11,6 @@ from opendm.shots import get_geojson_shots_from_opensfm from opendm.osfm import OSFMContext from opendm import gsd from opendm.point_cloud import export_summary_json -import json def hms(seconds): @@ -23,6 +25,14 @@ def hms(seconds): return '{}s'.format(s) +def generate_point_cloud_stats(input_point_cloud, pc_summary_file): + if not os.path.exists(pc_summary_file): + export_summary_json(input_point_cloud, pc_summary_file) + + if os.path.exists(pc_summary_file): + with open(pc_summary_file, 'r') as f: + return json.loads(f.read()) + class ODMReport(types.ODM_Stage): def process(self, args, outputs): tree = outputs['tree'] @@ -56,6 +66,8 @@ class ODMReport(types.ODM_Stage): octx = OSFMContext(tree.opensfm) osfm_stats_json = octx.path("stats", "stats.json") odm_stats = None + point_cloud_file = None + views_dimension = None if not os.path.exists(odm_stats_json) or self.rerun(): if os.path.exists(osfm_stats_json): @@ -63,15 +75,25 @@ class ODMReport(types.ODM_Stage): odm_stats = json.loads(f.read()) # Add point cloud stats - pc_summary_file = os.path.join(tree.odm_georeferencing, "odm_georeferenced_model.summary.json") - - # This should have been generated by cropper, but in case it hasn't.. - if not os.path.exists(pc_summary_file) and os.path.exists(tree.odm_georeferencing_model_laz): - export_summary_json(tree.odm_georeferencing_model_laz, pc_summary_file) - - if os.path.exists(pc_summary_file): - with open(pc_summary_file, 'r') as f: - odm_stats['point_cloud_statistics'] = json.loads(f.read()) + if os.path.exists(tree.odm_georeferencing_model_laz): + point_cloud_file = tree.odm_georeferencing_model_laz + views_dimension = "UserData" + + # pc_summary_file should have been generated by cropper + pc_summary_file = os.path.join(tree.odm_georeferencing, "odm_georeferenced_model.summary.json") + odm_stats['point_cloud_statistics'] = generate_point_cloud_stats(tree.odm_georeferencing_model_laz, pc_summary_file) + else: + ply_pc = os.path.join(tree.odm_filterpoints, "point_cloud.ply") + if os.path.exists(ply_pc): + point_cloud_file = ply_pc + views_dimension = "views" + + pc_summary_file = os.path.join(tree.odm_filterpoints, "point_cloud.summary.json") + odm_stats['point_cloud_statistics'] = generate_point_cloud_stats(ply_pc, pc_summary_file) + else: + log.ODM_WARNING("No point cloud found") + + odm_stats['point_cloud_statistics']['dense'] = not args.fast_orthophoto # Add runtime stats odm_stats['odm_processing_statistics'] = { @@ -89,4 +111,43 @@ class ODMReport(types.ODM_Stage): with open(odm_stats_json, 'r') as f: odm_stats = json.loads(f.read()) + # Generate overlap diagram + if odm_stats.get('point_cloud_statistics') and point_cloud_file and views_dimension: + bounds = odm_stats['point_cloud_statistics'].get('summary', {}).get('bounds') + if bounds: + diagram_target_size = 1600 # pixels + osfm_stats_dir = os.path.join(tree.opensfm, "stats") + diagram_tiff = os.path.join(osfm_stats_dir, "overlap.tif") + diagram_png = os.path.join(osfm_stats_dir, "overlap.png") + + width = bounds.get('maxx') - bounds.get('minx') + height = bounds.get('maxy') - bounds.get('miny') + max_dim = max(width, height) + resolution = float(max_dim) / float(diagram_target_size) + radius = resolution * math.sqrt(2) + + # Larger radius for sparse point cloud diagram + if not odm_stats['point_cloud_statistics']['dense']: + radius *= 10 + + system.run("pdal translate -i \"{}\" " + "-o \"{}\" " + "--writer gdal " + "--writers.gdal.resolution={} " + "--writers.gdal.data_type=uint8_t " + "--writers.gdal.dimension={} " + "--writers.gdal.output_type=max " + "--writers.gdal.radius={} ".format(point_cloud_file, diagram_tiff, + resolution, views_dimension, radius)) + report_assets = os.path.abspath(os.path.join(os.path.dirname(__file__), "../opendm/report")) + overlap_color_map = os.path.join(report_assets, "overlap_color_map.txt") + system.run("gdaldem color-relief \"{}\" \"{}\" \"{}\" -of PNG -alpha".format(diagram_tiff, overlap_color_map, diagram_png)) + + # Copy legend + shutil.copy(os.path.join(report_assets, "overlap_diagram_legend.png"), os.path.join(osfm_stats_dir, "overlap_diagram_legend.png")) + else: + log.ODM_WARNING("Cannot generate overlap diagram, cannot compute point cloud bounds") + else: + log.ODM_WARNING("Cannot generate overlap diagram, point cloud stats missing") + octx.export_report(os.path.join(tree.odm_report, "report.pdf"), odm_stats, self.rerun()) \ No newline at end of file diff --git a/stages/openmvs.py b/stages/openmvs.py index 0b16f05c..0edb5d35 100644 --- a/stages/openmvs.py +++ b/stages/openmvs.py @@ -55,6 +55,8 @@ class ODMOpenMVSStage(types.ODM_Stage): log.ODM_INFO("Running dense reconstruction. This might take a while.") + # TODO: add support for image masks + system.run('%s "%s" %s' % (context.omvs_densify_path, os.path.join(tree.openmvs, 'scene.mvs'), ' '.join(config))) diff --git a/stages/run_opensfm.py b/stages/run_opensfm.py index 4189e3b7..125606f1 100644 --- a/stages/run_opensfm.py +++ b/stages/run_opensfm.py @@ -193,14 +193,6 @@ class ODMOpenSfMStage(types.ODM_Stage): else: log.ODM_WARNING("Found a valid PLY reconstruction in %s" % output_file) - elif args.use_opensfm_dense: - output_file = tree.opensfm_model - - if not io.file_exists(output_file) or self.rerun(): - octx.run('compute_depthmaps') - else: - log.ODM_WARNING("Found a valid dense reconstruction in %s" % output_file) - self.update_progress(90) if reconstruction.is_georeferenced() and (not io.file_exists(tree.opensfm_transformation) or self.rerun()): @@ -222,7 +214,7 @@ class ODMOpenSfMStage(types.ODM_Stage): os.remove(f) # Keep these if using OpenMVS - if args.fast_orthophoto or args.use_opensfm_dense: + if args.fast_orthophoto: files = [octx.path("undistorted", "tracks.csv"), octx.path("undistorted", "reconstruction.json") ]