diff --git a/VHR/vhrbase.py b/VHR/vhrbase.py index d5b2942d678bac77e2fd652e79b8cd81fb558abe..89f58ed20f02f3720a028fa9ccc142bbd6c7657e 100644 --- a/VHR/vhrbase.py +++ b/VHR/vhrbase.py @@ -228,3 +228,48 @@ class SPOT67RasterPipeline: self.types = self.types[:pipe_length] self.out_p = self.out_p[:pipe_length] return out + +class PleiadesOrthoPipeline(SPOT67RasterPipeline): + # BEGIN PLEIADES (ORT) VHR PROTOTYPE + MS_FOLDER_PATTERN = 'IMG_PHR*_MS_*' + PAN_FOLDER_PATTERN = 'IMG_PHR*_P_*' + TILE_PATTERN = '*_R*C*.TIF' + NDT = 0.0 + REF_TYPE = otb.ImagePixelType_uint16 + MS_LABEL = 'MS' + OPT_IN = '' + +class PleiadesOrthoAutoMosaicPipeline: + def __init__(self, mosaic_root, pattern, out_fld): + lst = sorted(glob.glob(os.path.join(mosaic_root, pattern))) + lst = [x for x in lst if os.path.isdir(x)] + self.scene_list = [PleiadesOrthoPipeline(x) for x in lst] + self.processed_scenes = [] + self.out_fld = out_fld + + def process_scenes(self, roi=None, compress=False): + for s in self.scene_list: + s.to_toa() + if roi is not None and os.path.exists(roi): + s.clip(roi) + s.write_outputs(self.out_fld, update_pipe=True, compress=compress) + s.pansharp() + self.processed_scenes.extend(s.write_outputs(self.out_fld, compress=compress)) + return + + def generate_mosaic(self, vrt=True): + if len(self.processed_scenes) > 0: + lst = self.processed_scenes + fn = lst[0].split('_') + fn[-3] = 'MOSAIC' + fn = '_'.join(fn) + if vrt is True: + vrtopt = gdal.BuildVRTOptions() + fn = fn.replace('.TIF', '.vrt') + gdal.BuildVRT(fn, lst, options=vrtopt) + else: + print('Not implemented yet.') + return fn + else: + print('Preprocess scenes first.') + return None \ No newline at end of file diff --git a/Workflows/operations.py b/Workflows/operations.py index 3117b65d0afa16524df25486f5e014d473a7d55c..0117e52d8fc96ab05767a46af32ed6ecdcce8991 100644 --- a/Workflows/operations.py +++ b/Workflows/operations.py @@ -32,6 +32,24 @@ def preprocess_spot67(in_fld, out_fld, dem_fld, geoid_file, skip_ps, compress, sp.rigid_align(align_to, this_band=align_using_band-1, ref_band=align_to_band-1) return sp.write_outputs(out_fld, compress=compress) +def preprocess_pleiades(in_fld, out_fld, skip_ps, compress, clip, + align_to=None, align_to_band=3, align_using_band=1): + sp = VHR.vhrbase.PleiadesOrthoPipeline(in_fld) + sp.to_toa() + if clip is not None and os.path.exists(clip): + sp.clip(clip) + if not skip_ps: + sp.write_outputs(out_fld, update_pipe=True, compress=compress) + sp.pansharp() + if align_to is not None and os.path.exists(align_to): + sp.rigid_align(align_to, this_band=align_using_band-1, ref_band=align_to_band-1) + return sp.write_outputs(out_fld, compress=compress) + +def preprocess_pleiades_mosaic(in_fld, out_fld, pattern): + sp = VHR.vhrbase.PleiadesOrthoAutoMosaicPipeline(in_fld, pattern, out_fld) + sp.process_scenes() + return sp.generate_mosaic() + def preprocess_s2(in_fld, out_fld, output_dates_file=None, roi=None, align_to=None, align_to_band=3, align_using_band=3, provider='theia'): S2Processor = None diff --git a/moringa.py b/moringa.py index 771c3b52fed8f068645beb114d34a84149da8adc..69d271ca91fcc9c42e06df78dea6328495ac3377 100755 --- a/moringa.py +++ b/moringa.py @@ -48,6 +48,23 @@ def main(args): vhrprep.add_argument("--skip_ps", help="Skip pansharpening step.", action='store_true') vhrprep.add_argument("--compress", help="Use lossless compression on outputs.", action='store_true') + plprep = subpar.add_parser("preprocess_pleiades", help="Perform baseline pre-processing of a Pleaides ortho scene.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + plprep.add_argument("fld", type=str, help="Path to the root folder containing PAN and MS subfolders.") + plprep.add_argument("out_fld", type=str, help="Path to the output folder for preprocessed images.") + plprep.add_argument("--clip", type=str, default=None, help="Path to a vector file for clipping.") + plprep.add_argument("--align_to", type=str, default=None, help="Path to a reference image to which the image must be aligned (rigid).") + plprep.add_argument("--align_to_band", type=int, default=3, help="Band of reference image used for alignment.") + plprep.add_argument("--align_using_band", type=int, default=1, help="Band of current image used for alignment.") + plprep.add_argument("--skip_ps", help="Skip pansharpening step.", action='store_true') + plprep.add_argument("--compress", help="Use lossless compression on outputs.", action='store_true') + + plmprep = subpar.add_parser("preprocess_pleiades_mosaic", help="Perform baseline pre-processing and auto-mosaic of Pleaides ortho scenes.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + plmprep.add_argument("fld", type=str, help="Path to the root folder containing Pleaides acquisitions.") + plmprep.add_argument("pattern", type=str, help="File pattern to collect scene folders within in_fld.") + plmprep.add_argument("out_fld", type=str, help="Path to the output folder for preprocessed images.") + s1prepr = subpar.add_parser("preprocess_s1", help="Performs Moringa preset time series preprocessing for Sentinel-1.", formatter_class=argparse.ArgumentDefaultsHelpFormatter) s1prepr.add_argument("in_folder", type=str, help="Path to the folder containing (de-zipped) S1 images.") @@ -125,6 +142,13 @@ def main(args): if arg.cmd == "preprocess_spot67": preprocess_spot67(arg.fld, arg.out_fld, arg.dem_fld, arg.geoid, arg.skip_ps, arg.compress, arg.clip, arg.align_to, arg.align_to_band, arg.align_using_band) + + if arg.cmd == "preprocess_pleiades": + preprocess_pleiades(arg.fld, arg.out_fld, arg.skip_ps, arg.compress, arg.clip, + arg.align_to, arg.align_to_band, arg.align_using_band) + + if arg.cmd == "preprocess_pleiades_mosaic": + preprocess_pleiades_mosaic(arg.fld, arg.out_fld, arg.pattern) if arg.cmd == "preprocess_s1": preprocess_s1(arg.in_folder, arg.roi, arg.out_folder, arg.dem_fld, arg.geoid, arg.direction, arg.satellite,