diff --git a/SuperBuild/CMakeLists.txt b/SuperBuild/CMakeLists.txt index 4cd2b367..d87649ca 100644 --- a/SuperBuild/CMakeLists.txt +++ b/SuperBuild/CMakeLists.txt @@ -194,7 +194,7 @@ externalproject_add(dem2points externalproject_add(odm_orthophoto DEPENDS opencv GIT_REPOSITORY https://github.com/OpenDroneMap/odm_orthophoto.git - GIT_TAG 288a + GIT_TAG 288b PREFIX ${SB_BINARY_DIR}/odm_orthophoto SOURCE_DIR ${SB_SOURCE_DIR}/odm_orthophoto CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${SB_INSTALL_DIR} diff --git a/opendm/orthophoto.py b/opendm/orthophoto.py index d2d30bbc..a058117e 100644 --- a/opendm/orthophoto.py +++ b/opendm/orthophoto.py @@ -56,6 +56,9 @@ def generate_png(orthophoto_file, output_file=None, outsize=None): red = bands.get(gdal.GCI_RedBand) green = bands.get(gdal.GCI_GreenBand) blue = bands.get(gdal.GCI_BlueBand) + if red is None or green is None or blue is None: + raise Exception("Cannot find bands") + bandparam = "-b %s -b %s -b %s -a_nodata 0" % (red, green, blue) except: bandparam = "-b 1 -b 2 -b 3 -a_nodata 0" diff --git a/opendm/types.py b/opendm/types.py index 7ce99321..9bc06ad8 100644 --- a/opendm/types.py +++ b/opendm/types.py @@ -26,6 +26,7 @@ class ODM_Reconstruction(object): self.georef = None self.gcp = None self.multi_camera = self.detect_multi_camera() + self.filter_photos() def detect_multi_camera(self): """ @@ -64,6 +65,29 @@ class ODM_Reconstruction(object): return None + def filter_photos(self): + if not self.multi_camera: + return # Nothing to do, use all images + + else: + # Sometimes people might try process both RGB + Blue/Red/Green bands + # because these are the contents of the SD card from a drone (e.g. DJI P4 Multispectral) + # But we don't want to process both, so we discard the RGB files in favor + bands = {} + for b in self.multi_camera: + bands[b['name'].lower()] = b['name'] + + if ('rgb' in bands or 'redgreenblue' in bands) and \ + ('red' in bands and 'green' in bands and 'blue' in bands): + band_to_remove = bands['rgb'] if 'rgb' in bands else bands['redgreenblue'] + + self.multi_camera = [b for b in self.multi_camera if b['name'] != band_to_remove] + photos_before = len(self.photos) + self.photos = [p for p in self.photos if p.band_name != band_to_remove] + photos_after = len(self.photos) + + log.ODM_WARNING("RGB images detected alongside individual Red/Green/Blue images, we will use individual bands (skipping %s images)" % (photos_before - photos_after)) + def is_georeferenced(self): return self.georef is not None diff --git a/stages/odm_orthophoto.py b/stages/odm_orthophoto.py index 62f0be34..a15e9728 100644 --- a/stages/odm_orthophoto.py +++ b/stages/odm_orthophoto.py @@ -42,6 +42,7 @@ class ODMOrthoPhotoStage(types.ODM_Stage): 'corners': tree.odm_orthophoto_corners, 'res': resolution, 'bands': '', + 'depth_idx': '', 'verbose': verbose } @@ -62,6 +63,21 @@ class ODMOrthoPhotoStage(types.ODM_Stage): subdir = band['name'].lower() models.append(os.path.join(base_dir, subdir, model_file)) kwargs['bands'] = '-bands %s' % (','.join([double_quote(b['name']) for b in reconstruction.multi_camera])) + + # If a RGB band is present, + # use bit depth of the first non-RGB band + depth_idx = None + all_bands = [b['name'].lower() for b in reconstruction.multi_camera] + for b in ['rgb', 'redgreenblue']: + if b in all_bands: + for idx in range(len(all_bands)): + if all_bands[idx] != b: + depth_idx = idx + break + break + + if depth_idx is not None: + kwargs['depth_idx'] = '-outputDepthIdx %s' % depth_idx else: models.append(os.path.join(base_dir, model_file)) @@ -70,7 +86,7 @@ class ODMOrthoPhotoStage(types.ODM_Stage): # run odm_orthophoto system.run('"{odm_ortho_bin}" -inputFiles {models} ' '-logFile "{log}" -outputFile "{ortho}" -resolution {res} {verbose} ' - '-outputCornerFile "{corners}" {bands}'.format(**kwargs)) + '-outputCornerFile "{corners}" {bands} {depth_idx}'.format(**kwargs)) # Create georeferenced GeoTiff geotiffcreated = False