diff --git a/json_schemas/schema_S1IW.json b/json_schemas/schema_S1IW.json index e8213ae931d6498f0bac9c1264071d1cc6ecc621..19781acb335925bc39f4c7048c51bc2b3a031731 100644 --- a/json_schemas/schema_S1IW.json +++ b/json_schemas/schema_S1IW.json @@ -79,20 +79,41 @@ { "type": "object", "required": ["GridStep_range", "GridStep_azimut", "Grid_Threshold", "Grid_Gap", - "Interferogram_gain", "Interferogram_ortho"], + "Interferogram_gain"], "additionalProperties": false, "properties": {"GridStep_range": {"type": "number"}, "GridStep_azimut": {"type": "number"}, "Grid_Threshold": {"type": "number"}, "Grid_Gap": {"type": "number"}, "Interferogram_gain": {"type": "number"}, - "Interferogram_ortho": {"type": "boolean"}, "ESD_iter" : {"type": ["integer","string"]} } } }, "additionalProperties": false, "required": ["parameter"] + }, + + "Post_Processing": + { + "type": "object", + "properties": + { + "parameter": + { + "type": "object", + "required": ["Activate_Ortho"], + "additionalProperties": false, + "properties": {"Activate_Ortho": {"type": "string"}, + "Spacingxy": {"type": "number", "default": 0.0001}, + "Activate_Filtering": {"type": "string"}, + "Filtered_Interferogram_mlran": {"type": "number"}, + "Filtered_Interferogram_mlazi": {"type": "number"} + } + } + }, + "additionalProperties": false, + "required": ["parameter"] } } } diff --git a/json_schemas/schema_S1SM.json b/json_schemas/schema_S1SM.json index 2df1353ed431bb844abf14fccec2ab69e3c2ece2..250121e80528b53f49314cecd8616b3db87fda13 100644 --- a/json_schemas/schema_S1SM.json +++ b/json_schemas/schema_S1SM.json @@ -121,6 +121,28 @@ }, "additionalProperties": false, "required": ["parameter"] + }, + + "Post_Processing": + { + "type": "object", + "properties": + { + "parameter": + { + "type": "object", + "required": ["Activate_Ortho"], + "additionalProperties": false, + "properties": {"Activate_Ortho": {"type": "string"}, + "Spacingxy": {"type": "number", "default": 0.0001}, + "Activate_Filtering": {"type": "string"}, + "Filtered_Interferogram_mlran": {"type": "number"}, + "Filtered_Interferogram_mlazi": {"type": "number"} + } + } + }, + "additionalProperties": false, + "required": ["parameter"] } } } diff --git a/python_src/diapOTB.py b/python_src/diapOTB.py index 6ce3e15503823b7821aaa13f3a5a10aa559c0f60..229217d3e74c8746facc0b12cc20a0ed396563f4 100644 --- a/python_src/diapOTB.py +++ b/python_src/diapOTB.py @@ -45,6 +45,7 @@ from processings import Pre_Processing from processings import Ground from processings import DInSar from processings import Metadata_Correction +from processings import Post_Processing from utils import func_utils @@ -67,6 +68,7 @@ if __name__ == "__main__": dict_PreProcessing = dataConfig['Pre_Processing'] dict_Metadata_Correction = dataConfig['Metadata_Correction'] dict_DInSAR = dataConfig['DIn_SAR'] + dict_PostProcessing = dataConfig['Post_Processing'] # Get elements from configuration file # Global @@ -110,13 +112,32 @@ if __name__ == "__main__": ml_interf_range = ml_range ml_interf_azimut = ml_azimut - + if "Interferogram_mlran" in dict_DInSAR['parameter'] : ml_interf_range = int(dict_DInSAR['parameter']['Interferogram_mlran']) if "Interferogram_mlazi" in dict_DInSAR['parameter'] : ml_interf_azimut = int(dict_DInSAR['parameter']['Interferogram_mlazi']) + # Post_Processing + activateOrtho = dict_PostProcessing['parameter']['Activate_Ortho'] + + spacingxy = 0.00001 + if "spacingxy" in dict_PostProcessing['parameter'] : + spacingxy = dict_PostProcessing['parameter']['Spacingxy'] + + activateFiltering = "false" + if "Activate_Filtering" in dict_PostProcessing['parameter'] : + activateFiltering = dict_PostProcessing['parameter']['Activate_Filtering'] + + ml_interf_filt_range = 3 + if "Filtered_Interferogram_mlran" in dict_PostProcessing['parameter'] : + ml_interf_filt_range = int(dict_PostProcessing['parameter']['Filtered_Interferogram_mlran']) + + ml_interf_filt_azimut = 3 + if "Filtered_Interferogram_mlazi" in dict_PostProcessing['parameter'] : + ml_interf_filt_azimut = int(dict_PostProcessing['parameter']['Filtered_Interferogram_mlazi']) + if (geoGrid_threshold < 0) or (geoGrid_threshold > 1) : func_utils.log(logging.CRITICAL, "Error, Wrong Threshold for fine deformation grid") @@ -177,8 +198,19 @@ if __name__ == "__main__": func_utils.log(logging.INFO, "ml_geoGrid_azimut : {param}".format(param=ml_geoGrid_azimut)) + # Post_Processing + func_utils.log(logging.INFO, " Post_Processing : ") + func_utils.log(logging.INFO, "activateOrtho : {param}".format(param=activateOrtho)) + if func_utils.str2bool(activateOrtho): + func_utils.log(logging.INFO, "spacingxy : {param}".format(param=spacingxy)) + func_utils.log(logging.INFO, "activateFiltering : {param}".format(param=activateFiltering)) + if func_utils.str2bool(activateFiltering): + func_utils.log(logging.INFO, "ml_interf_filt_range : {param}".format(param=ml_interf_filt_range)) + func_utils.log(logging.INFO, "ml_interf_filt_azimut : {param}".format(param=ml_interf_filt_azimut)) + + func_utils.log(logging.INFO, "########### Input Images for the current execution ############## ") - + master_Image_base = os.path.basename(master_Image) slave_Image_base = os.path.basename(slave_Image) @@ -358,5 +390,26 @@ if __name__ == "__main__": DInSar.gridToInterferogram(dem, master_Image, master_Image_base, slave_Image, slave_Image_base, output_dir, output_dir, param, "Others", output_dir) + + ######################## Post_Processing Chain ############################# + func_utils.printOnStd("\n Post_Processing chain \n") + func_utils.log(logging.INFO, "Post_Processing chain") + + # Phase Filtering (if required) + if func_utils.str2bool(activateFiltering): + # Default paramater + alpha = 0.7 + step = 16 + sizetiles = 64 + + paramPost = {} + paramPost['ml_filt_interf_range'] = ml_interf_filt_range + paramPost['ml_filt_interf_azimut'] = ml_interf_filt_azimut + paramPost['geoGrid_gridstep_range'] = geoGrid_gridstep_range + paramPost['geoGrid_gridstep_azimut'] = geoGrid_gridstep_azimut + + Post_Processing.filtering(master_Image, master_Image_base, slave_Image, slave_Image_base, output_dir, output_dir, paramPost, "Others", output_dir) + + func_utils.printOnStd("\n End of DiapOTB processing (S1 SM or Cosmo mode) \n") func_utils.log(logging.INFO, "############ End of DiapOTB processing (S1 SM or Cosmo mode) ##############") diff --git a/python_src/processings/Post_Processing.py b/python_src/processings/Post_Processing.py new file mode 100644 index 0000000000000000000000000000000000000000..0714a0a36fc353b0791bd8adb9dbf92aa84e3c8a --- /dev/null +++ b/python_src/processings/Post_Processing.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES) +# +# This file is part of Orfeo Toolbox +# +# https://www.orfeo-toolbox.org/ +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +""" + The ``Post_Processing`` chain + ====================== + + Use the module to launch post processigns like phase filtering. + + main function : filtering + ----------------------------------- + +""" + +import os +import sys +from functools import partial + +import utils.DiapOTB_applications as diapOTBApp +from utils import func_utils + +import otbApplication as otb + + +def filtering(master_Image, master_Image_base, slave_Image, slave_Image_base, master_dir, slave_dir, param, mode, output_dir): + """ + Main function for Post processing + + This function applies several processing to provide the filtering result interferogram + (according to the mode) + + :param master_Image: Master image name (with path included) + :param master_Image_base: Master image name + :param slave_Image: Slave image name (with path included) + :param slave_Image_base: Slave image name + :param master_dir: Output directory (to store result on master image only) + :param slave_dir: Output directory (to store result on slave image only) + :param param: Dictionary to retrieve all parameters used into this processing chain + :param mode: Selected mode according to input product : S1IW or other (for Cosmo and S1 StripMap products) + :param output_dir: Output directory + + :type master_Image: string + :type master_Image_base: string + :type slave_Image: string + :type slave_Image_base: string + :type master_dir: string + :type slave_dir: string + :type param: dict + :type mode: string + :type output_dir: string + + :return: filtered interferogram + :rtype: string + """ + if mode == 'S1_IW' : + return filtering_S1IW(master_Image, master_Image_base, slave_Image, slave_Image_base, master_dir, slave_dir, param, output_dir) + else : + return filtering_Others(master_Image, master_Image_base, slave_Image, slave_Image_base, master_dir, slave_dir, param, output_dir) + + + +def filtering_Others(master_Image, master_Image_base, slave_Image, slave_Image_base, master_dir, slave_dir, param, output_dir): + """ + Main function for post processing and other than S1IW mode (S1SM and Cosmo) + + This function applies several processing to provide the result interferogram + + :param master_Image: Master image name (with path included) + :param master_Image_base: Master image name + :param slave_Image: Slave image name (with path included) + :param slave_Image_base: Slave image name + :param master_dir: Output directory (to store result on master image only) + :param slave_dir: Output directory (to store result on slave image only) + :param param: Dictionary to retrieve all parameters used into this processing chain + :param output_dir: Output directory + + :type master_Image: string + :type master_Image_base: string + :type slave_Image: string + :type slave_Image_base: string + :type master_dir: string + :type slave_dir: string + :type param: dict + :type output_dir: string + + :return: list of grids and interferograms + :rtype: list, list + """ + # Get elements into param dictionnaries + ml_azimut = 1 + ml_range = 1 + + ml_filt_interf_range = ml_range + if "ml_filt_interf_range" in param : + ml_filt_interf_range = param['ml_filt_interf_range'] + + ml_filt_interf_azimut = ml_azimut + if "ml_filt_interf_azimut" in param : + ml_filt_interf_azimut = param['ml_filt_interf_azimut'] + + geoGrid_gridstep_range = param['geoGrid_gridstep_range'] + geoGrid_gridstep_azimut = param['geoGrid_gridstep_azimut'] + + + # define partial function with previous parameters + phaseFilteringApp = partial(diapOTBApp.phaseFiltering, withComplex="true", + mlran=ml_filt_interf_range, mlazi=ml_filt_interf_azimut, step=16, + sizetiles=64, alpha=0.7) + + addAmpApp = partial(diapOTBApp.addAmpInterferogram, withComplex="true", + mlran=ml_filt_interf_range, mlazi=ml_filt_interf_azimut, gain=1) + + + # Filtering + master_cartesian_mean = "CartMeanMaster.tif" + fine_grid = "fineDeformationGrid.tif" + + topographicPhase = "Topo.tif" + filt_dir = os.path.join(output_dir, "filt") + + if not os.path.exists(filt_dir): + os.makedirs(filt_dir) + + # First SARTopographicPhase + appTopoPhase = otb.Registry.CreateApplication("SARTopographicPhase") + appTopoPhase.SetParameterString("insarslave", slave_Image) + appTopoPhase.SetParameterString("ingrid", os.path.join(master_dir, fine_grid)) + appTopoPhase.SetParameterString("incartmeanmaster", + os.path.join(master_dir, master_cartesian_mean)) + appTopoPhase.SetParameterInt("mlran", 1) + appTopoPhase.SetParameterInt("mlazi", 1) + appTopoPhase.SetParameterInt("gridsteprange", geoGrid_gridstep_range) + appTopoPhase.SetParameterInt("gridstepazimut", geoGrid_gridstep_azimut) + appTopoPhase.SetParameterString("out", os.path.join(filt_dir, topographicPhase)) + appTopoPhase.Execute() + + # Second CompensatedComplex + slave_Image_CoRe = os.path.splitext(slave_Image_base)[0] + "_coregistrated.tif" + if "slave_CoRe_Name" in param : + slave_Image_CoRe = param['slave_CoRe_Name'] + slave_Image_CoRe += "?&gdal:co:TILED=YES" + + coRe_path = os.path.join(output_dir, slave_Image_CoRe) + + complexImg = "CompensatedComplex.tif" + + appComplex = otb.Registry.CreateApplication("SARCompensatedComplex") + appComplex.SetParameterString("insarslave", coRe_path) + appComplex.SetParameterString("insarmaster", master_Image) + appComplex.SetParameterInputImage("topographicphase", + appTopoPhase.GetParameterOutputImage("out")) + appComplex.SetParameterString("out", os.path.join(filt_dir, complexImg)) + appComplex.ExecuteAndWriteOutput() + + # Third SARPhaseFiltering + filt_phacoh = "filfPhaCoh.tif" + filt_phacoh_path = os.path.join(filt_dir, filt_phacoh) + phaseFilteringApp(inForFiltering=os.path.join(filt_dir, complexImg), + outPath=filt_phacoh_path) + + + # Eventually SARAddBandInterfergoram + filt_interferogram = "filtered_interferogram.tif" + addAmpApp(inForAmp=os.path.join(filt_dir, complexImg), + inForPhaCoh=filt_phacoh_path, + outPath=os.path.join(output_dir, filt_interferogram)) + + + +def filtering_S1IW(master_Image, master_Image_base, slave_Image, slave_Image_base, master_dir, slave_dir, param, output_dir): + """ + Main function for Post processing and S1IW mode + + This function applies several processing to provide the result interferogram (with filtering) + + :param master_Image: Master image name (with path included) + :param master_Image_base: Master image name + :param slave_Image: Slave image name (with path included) + :param slave_Image_base: Slave image name + :param master_dir: Output directory (to store result on master image only) + :param slave_dir: Output directory (to store result on slave image only) + :param param: Dictionary to retrieve all parameters used into this processing chain + :param output_dir: Output directory + + :type master_Image: string + :type master_Image_base: string + :type slave_Image: string + :type slave_Image_base: string + :type master_dir: string + :type slave_dir: string + :type param: dict + :type output_dir: string + + :return: list of grids and interferograms + :rtype: list, list + """ + # Get elements into param dictionnaries + ml_azimut = param['ml_azimut'] + ml_range = param['ml_range'] + diff --git a/python_src/utils/DiapOTB_applications.py b/python_src/utils/DiapOTB_applications.py index 9da1acf96f6cefb8ebcf12c43516f8e804e1af93..12f360e417497a84db74b75c06d8e1b1cc629fd4 100644 --- a/python_src/utils/DiapOTB_applications.py +++ b/python_src/utils/DiapOTB_applications.py @@ -1,3 +1,4 @@ + #!/usr/bin/env python # -*- coding: utf-8 -*- # @@ -136,7 +137,7 @@ def multilook(inImg, mlran, mlazi, mlgain, outPath, ram="4000"): This application creates the multi-look image of a SLC product. :param inImg: Input image (complex here). - :param mlran: Averaging on distance). + :param mlran: Averaging on distance. :param mlazi: Averaging on azimut. :param mlgain: Gain to apply on ML image. :param outPath: Output ML Image. @@ -168,7 +169,7 @@ def demToAmplitude(insar, dem, mlran, mlazi, mlgain, outPath, nodata=-32768, ram :param insar: SAR Image to extract SAR geometry. :param indem: DEM to extract DEM geometry. - :param mlran: Averaging on distance). + :param mlran: Averaging on distance. :param mlazi: Averaging on azimut. :param mlgain: Gain to apply on ML image. :param nodata: No Data values for the DEM. @@ -490,6 +491,8 @@ def interferogram(insarmaster, incoregistratedslave, insarslave, ingrid, incartm :param incartmeanmaster: Input Cartesian Mean Master image. :param gridsteprange: Grid step for range dimension (into SLC/SAR geometry). :param gridstepazimut: Grid step for azimut dimension (into SLC/SAR geometry). + :param mlran: MultiLook factor on distance. + :param mlazi: MultiLook factor on azimut. :param gain: Gain to apply for amplitude estimation. :param outPath: Output interferogram (ML geometry). @@ -500,6 +503,8 @@ def interferogram(insarmaster, incoregistratedslave, insarslave, ingrid, incartm :type incartmeanmaster: string :type gridsteprange: int :type gridstepazimut: int + :type mlran: int + :type mlazi: int :type gain: float :type outPath: string @@ -607,6 +612,135 @@ def concatenate(list_of_Interferograms, insar, firstBurst, outPath, ram="4000"): appCon.SetParameterString("ram", ram) appCon.ExecuteAndWriteOutput() + +def topographicPhase(ingrid, insarslave, incartmeanmaster, gridsteprange, gridstepazimut, + mlran, mlazi, outPath, ram="4000"): + """ + Launch SARTopographicPhase application (from DiapOTB). + + This application estimates the topographic phase thanks to cartesian image. + + :param ingrid: Input deformation grid. + :param insarslave: Input SAR Slave image (Metadata). + :param incartmeanmaster: Input Cartesian Mean Master image. + :param gridsteprange: Grid step for range dimension (into SLC/SAR geometry). + :param gridstepazimut: Grid step for azimut dimension (into SLC/SAR geometry). + :param mlran: MultiLook factor on distance. + :param mlazi: MultiLook factor on azimut. + :param outPath: Output interferogram (ML geometry). + + :type ingrid: string + :type insarslave: string + :type incartmeanmaster: string + :type gridsteprange: int + :type gridstepazimut: int + :type mlran: int + :type mlazi: int + :type outPath: string + """ + appTopoPhase = otb.Registry.CreateApplication("SARTopographicPhase") + appTopoPhase.SetParameterString("insarslave", insarslave) + appTopoPhase.SetParameterString("ingrid", ingrid) + appTopoPhase.SetParameterString("incartmeanmaster", incartmeanmaster) + appTopoPhase.SetParameterInt("mlran", mlran) + appTopoPhase.SetParameterInt("mlazi", mlazi) + appTopoPhase.SetParameterInt("gridsteprange", gridsteprange) + appTopoPhase.SetParameterInt("gridstepazimut", gridstepazimut) + appTopoPhase.SetParameterString("ram", ram) + appTopoPhase.SetParameterString("out", outPath) + appTopoPhase.ExecuteAndWriteOutput() + + +def phaseFiltering(withComplex, inForFiltering, mlran, mlazi, step, sizetiles, alpha, + outPath, ram="4000"): + """ + Launch SARPhaseFiltering application (from DiapOTB). + + This application performs a filtering for phase and coherency bands. + Two kinds of inputs are possible (according to the sensor and mode) : + _ complex conjugate image for S1 SM and Cosmo + _ interferogram ML 11 fir S1 IW + + + :param withComplex: A boolean to indicate selected input. + :param inForFiltering: Input for filtering (complex conjugate image or inteferogram). + :param mlran: MultiLook factor on distance. + :param mlazi: MultiLook factor on azimut. + :param step: Step for window extractions into input + :param sizetiles: Size Tiles for output cut + :param alpha: Alpha parameter for Goldstein filter (0->1) + :param outPath: The concatenated and debursted output image. + + :type withComplex: bool + :type inForFiltering: string + :type mlran: int + :type mlazi: int + :type step: int + :type sizetiles: int + :type alpha: float + :type outPath: string + + :return: None + """ + appPhaFiltering = otb.Registry.CreateApplication("SARPhaseFiltering") + if fUtils.str2bool(withComplex) : + appPhaFiltering.SetParameterString("incomplex", inForFiltering) + else : + appPhaFiltering.SetParameterString("ininterf", inForFiltering) + appPhaFiltering.SetParameterInt("mlran", mlran) + appPhaFiltering.SetParameterInt("mlazi", mlazi) + appPhaFiltering.SetParameterInt("step", step) + appPhaFiltering.SetParameterInt("sizetiles", sizetiles) + appPhaFiltering.SetParameterFloat("alpha", alpha) + appPhaFiltering.SetParameterString("out", outPath) + appPhaFiltering.SetParameterString("ram", ram) + appPhaFiltering.ExecuteAndWriteOutput() + + +def addAmpInterferogram(withComplex, inForAmp, inForPhaCoh, mlran, mlazi, gain, + outPath, ram="4000"): + """ + Launch SARAddBandInterfergoram application (from DiapOTB). + + This application adds an amplitude band into filtered interferogram (pha/coh) to build + a full interferogram. + Two kinds of inputs are possible to retrive original amplitude + (according to the sensor and mode) : + _ complex conjugate image for S1 SM and Cosmo + _ interferogram ML 11 fir S1 IW + + + :param withComplex: A boolean to indicate selected input (for amplitude). + :param inForAmp: Input for amplitude. + :param inForPhaCoh: Input for phase and coherency. + :param mlran: MultiLook factor on distance. + :param mlazi: MultiLook factor on azimut. + :param gain: Gain to apply for amplitude estimation. + :param outPath: The concatenated and debursted output image. + + :type withComplex: bool + :type inForAmp: string + :type inForPhaCoh: string + :type mlran: int + :type mlazi: int + :type gain: float + :type outPath: string + + :return: None + """ + appAddAmp = otb.Registry.CreateApplication("SARAddBandInterferogram") + if fUtils.str2bool(withComplex) : + appAddAmp.SetParameterString("incomplexamp", inForAmp) + else : + appAddAmp.SetParameterString("ininterfamp", inForAmp) + appAddAmp.SetParameterString("ininterf", inForPhaCoh) + appAddAmp.SetParameterInt("mlran", mlran) + appAddAmp.SetParameterInt("mlazi", mlazi) + appAddAmp.SetParameterString("out", outPath) + appAddAmp.SetParameterString("ram", ram) + appAddAmp.ExecuteAndWriteOutput() + + def orthorectification(inImg, spacingxy, hgts_path, geoid_path, outPath, ram="4000"): """ Launch OrthoRectification application (from OTB).