Commit 692e4f2989ee241604b9abe58c68772505815da1

Authored by Arthur VINCENT
1 parent c1e5a5d2

ENH : IOTA2 could use atmospherically corrected normalized indices

config/Config_4Tuiles_Multi_FUS_Confidence.cfg
... ... @@ -163,5 +163,6 @@ iota2FeatureExtraction:
163 163 relrefl:False
164 164 keepduplicates:False
165 165 extractBands:False
  166 + acorfeat:False
166 167 }
167 168 ################################################################################################
... ...
doc/running_iota.org
... ... @@ -200,33 +200,34 @@ Classification's options
200 200  
201 201 Today, features computable are : NDVI, NDWI and the brightness. Only two sensors are supported, Landsat_8 and Landsat_5, but some others are coming soon. So you only have to fill out the Landsat_8 block composed by many fields.
202 202  
203   -| field | Description | Conditions | Example |
204   -|-----------------------+--------------------------------------------------------------------------------------------------------------+----------------------------------------------------+----------------------------------------------------------------------------|
205   -| nodata_Mask | argument used to indicate if a NoData mask exists | must be False or True | nodata_Mask : False |
206   -| nativeRes | native resolution of images | must be an integer | nativeRes : 30 |
207   -| arbo | inform the image's path, according to L8Path (1) | - | arbo : /*/* |
208   -| imtype | allow you to target a specific images in arbo | - | imtype : "ORTHO_SURF_CORR_PENTE*.TIF" |
209   -| arbomask | inform the path of the mask link to the image, according to L8Path | - | arbomask : "*/*/MASK/" |
210   -| nuages | target the mask of cloud in arbomask | - | nuages : "NUA.TIF" |
211   -| saturation | target the mask of saturation in arbomask | - | saturation : "SAT.TIF" |
212   -| div | target the mask of diverse in arbomask | - | div : "DIV.TIF" |
213   -| nodata | target the nodata mask in arbomask | - | nodata : "NODATA.TIF" if nodata_Mask is set to False, nodata could be : "" |
214   -| features | describre which features uses | must be a list of strings (2) | features: ["NDVI","NDWI","Brightness"] |
215   -| proj | output projection | must be an EPSG code | proj:"EPSG:2154" |
216   -| temporalResolution | temporal resolution in order to manage gapfilling (cloud management) | - | temporalResolution:16 |
217   -| autoDate | force gapfilling's output date or not | must be True or False | autoDate:True |
218   -| startDate | starting date to use in gapfilling ouput | must be 'YYYYMMDD' | startDate:'20150121' |
219   -| endDate | ending date to use in gapfilling ouput | must be 'YYYYMMDD' | endDate:'20151205' |
220   -| patterns | in user's features, pattern to chose features | - | patterns:'ALT,MNT' |
221   -| extractBands | flag to use targeted bands if not use (False) -> all bands are used | must be True or False | extractBands:False |
222   -| keepBands | bands to keep to produce features | must respect Sensors.py definition (4) | keepBands:[[1,"blue"],[2,"green"],[3,"red"],[7,"NIR"],[9,"SWIR"]] |
223   -| copyinput | if bindingPython is set to 'True', use sensor's data and derivated ceofficient | must be True or False | copyinput:True |
224   -| relrefl | normalize bands by the red band SWIR_norm = (SWIR-RED)/(SWIR+RED) | must be True or False | relrefl:False |
225   -| keepduplicates | using red normalization could introduce duplicate data, set keepduplicate to 'False' remove duplicates bands | must be True or False | keepduplicates:False |
226   -| additionalFeatures | user features definition | must be a bandMath (OTB) expression, comma splited | additionalFeatures:"b1+b2,(b1-b2)/(b1+b2)" |
227   -| useAdditionalFeatures | flag to indicate if the chain must use 'additionalFeatures' | must be True or False | useAdditionalFeatures:False |
228   -| writeOutputs | flag to indicate if temporary files musk be written on disk (faster if set to 'False') | must be True or False | writeOutputs:False |
229   -| useGapFilling | flag to use temporal interpolation | must be True or False | useGapFilling : True |
  203 +| field | Description | Conditions | Example |
  204 +|-----------------------+----------------------------------------------------------------------------------------------------------------+----------------------------------------------------+----------------------------------------------------------------------------|
  205 +| nodata_Mask | argument used to indicate if a NoData mask exists | must be False or True | nodata_Mask : False |
  206 +| nativeRes | native resolution of images | must be an integer | nativeRes : 30 |
  207 +| arbo | inform the image's path, according to L8Path (1) | - | arbo : /*/* |
  208 +| imtype | allow you to target a specific images in arbo | - | imtype : "ORTHO_SURF_CORR_PENTE*.TIF" |
  209 +| arbomask | inform the path of the mask link to the image, according to L8Path | - | arbomask : "*/*/MASK/" |
  210 +| nuages | target the mask of cloud in arbomask | - | nuages : "NUA.TIF" |
  211 +| saturation | target the mask of saturation in arbomask | - | saturation : "SAT.TIF" |
  212 +| div | target the mask of diverse in arbomask | - | div : "DIV.TIF" |
  213 +| nodata | target the nodata mask in arbomask | - | nodata : "NODATA.TIF" if nodata_Mask is set to False, nodata could be : "" |
  214 +| features | describre which features uses | must be a list of strings (2) | features: ["NDVI","NDWI","Brightness"] |
  215 +| proj | output projection | must be an EPSG code | proj:"EPSG:2154" |
  216 +| temporalResolution | temporal resolution in order to manage gapfilling (cloud management) | - | temporalResolution:16 |
  217 +| autoDate | force gapfilling's output date or not | must be True or False | autoDate:True |
  218 +| startDate | starting date to use in gapfilling ouput | must be 'YYYYMMDD' | startDate:'20150121' |
  219 +| endDate | ending date to use in gapfilling ouput | must be 'YYYYMMDD' | endDate:'20151205' |
  220 +| patterns | in user's features, pattern to chose features | - | patterns:'ALT,MNT' |
  221 +| extractBands | flag to use targeted bands if not use (False) -> all bands are used | must be True or False | extractBands:False |
  222 +| keepBands | bands to keep to produce features | must respect Sensors.py definition (4) | keepBands:[[1,"blue"],[2,"green"],[3,"red"],[7,"NIR"],[9,"SWIR"]] |
  223 +| copyinput | if bindingPython is set to 'True', use sensor's data and derivated ceofficient | must be True or False | copyinput:True |
  224 +| relrefl | normalize bands by the red band SWIR_norm = (SWIR-RED)/(SWIR+RED) | must be True or False | relrefl:False |
  225 +| acorfeat | use atmospherically corrected normalized indices according to http://www.cesbio.ups-tlse.fr/multitemp/?p=12746 | must be True or False | acorfeat:False |
  226 +| keepduplicates | using red normalization could introduce duplicate data, set keepduplicate to 'False' remove duplicates bands | must be True or False | keepduplicates:False |
  227 +| additionalFeatures | user features definition | must be a bandMath (OTB) expression, comma splited | additionalFeatures:"b1+b2,(b1-b2)/(b1+b2)" |
  228 +| useAdditionalFeatures | flag to indicate if the chain must use 'additionalFeatures' | must be True or False | useAdditionalFeatures:False |
  229 +| writeOutputs | flag to indicate if temporary files musk be written on disk (faster if set to 'False') | must be True or False | writeOutputs:False |
  230 +| useGapFilling | flag to use temporal interpolation | must be True or False | useGapFilling : True |
230 231  
231 232  
232 233  
... ...
scripts/common/fileUtils.py
... ... @@ -595,6 +595,7 @@ def iota2FeatureExtractionParameter(otbObject, cfg):
595 595 copyinput = cfg.getParam('iota2FeatureExtraction', 'copyinput')
596 596 relrefl = cfg.getParam('iota2FeatureExtraction', 'relrefl')
597 597 keepduplicates = cfg.getParam('iota2FeatureExtraction', 'keepduplicates')
  598 + acorfeat = cfg.getParam('iota2FeatureExtraction', 'acorfeat')
598 599  
599 600 if copyinput == True:
600 601 otbObject.SetParameterEmpty("copyinput", True)
... ... @@ -602,6 +603,8 @@ def iota2FeatureExtractionParameter(otbObject, cfg):
602 603 otbObject.SetParameterEmpty("relrefl", True)
603 604 if keepduplicates == True:
604 605 otbObject.SetParameterEmpty("keepduplicates", True)
  606 + if acorfeat == True:
  607 + otbObject.SetParameterEmpty("acorfeat", True)
605 608  
606 609  
607 610 def keepBiggestArea(shpin, shpout):
... ...
scripts/common/genAnnualSamples.py
... ... @@ -233,10 +233,13 @@ def genAnnualShapePoints(coord, gdalDriver, workingDirectory, rasterResolution,
233 233 addField(vector_region, "seed_" + str(run), undetermined_flag,
234 234 valueType=str, driver_name="SQLite")
235 235  
236   - outlearningShape_name = os.path.splitext(os.path.split(outlearningShape)[-1])[0]
237   - outlearningShape_dir = os.path.split(outlearningShape)[0]
  236 + outlearningShape_name = os.path.splitext(os.path.split(outlearningShape)[-1])[0]
  237 + outlearningShape_dir = os.path.split(outlearningShape)[0]
238 238  
239   - fu.mergeSQLite(outlearningShape_name, outlearningShape_dir, vector_regions)
  239 + fu.mergeSQLite(outlearningShape_name, outlearningShape_dir, vector_regions)
  240 +
  241 + for vec in vector_regions:
  242 + os.remove(vec)
240 243  
241 244 if add == 0:
242 245 return False
... ...
scripts/common/serviceConfigFile.py
... ... @@ -297,7 +297,8 @@ class serviceConfigFile:
297 297 self.testVarConfigFile('iota2FeatureExtraction', 'relrefl', bool)
298 298 self.testVarConfigFile('iota2FeatureExtraction', 'keepduplicates', bool)
299 299 self.testVarConfigFile('iota2FeatureExtraction', 'extractBands', bool)
300   -
  300 + self.testVarConfigFile('iota2FeatureExtraction', 'acorfeat', bool)
  301 +
301 302 if self.cfg.chain.L5Path != "None":
302 303 #L5 variable check
303 304 self.testVarConfigFile('Landsat5', 'nodata_Mask', bool)
... ...
scripts/common/vectorSampler.py
... ... @@ -686,7 +686,7 @@ def generateSamples_classifMix(folderSample, workingDirectory, trainShape,
686 686 nonAnnualShape = os.path.join(wd, "{}_nonAnnual_selection.sqlite".format(currentTile))
687 687 AnnualShape = os.path.join(wd, "{}_annual_selection.sqlite".format(currentTile))
688 688 nb_feat_Nannu = extract_class(sampleSelection, nonAnnualShape, AllClass, dataField)
689   -
  689 +
690 690 annu_repartition = get_repartition(sampleSelection, annualCrop, dataField)
691 691  
692 692 nb_feat_annu = sum([v for k, v in annu_repartition.items()])
... ... @@ -708,11 +708,12 @@ def generateSamples_classifMix(folderSample, workingDirectory, trainShape,
708 708  
709 709 regions = fu.getFieldElement(trainShape, driverName="ESRI Shapefile", field=regionField, mode="unique",
710 710 elemType="str")
  711 +
711 712 #build regions mask into the tile
712 713 masks = [getRegionModelInTile(currentTile, currentRegion, pathWd, cfg,
713 714 classificationRaster, testMode, testShapeRegion,
714 715 testOutputFolder=folderSample) for currentRegion in regions]
715   -
  716 +
716 717 if nb_feat_annu > 0:
717 718 annualPoints = genAS.genAnnualShapePoints(allCoord, "SQLite", workingDirectory,
718 719 targetResolution, annualCrop, dataField,
... ... @@ -725,6 +726,7 @@ def generateSamples_classifMix(folderSample, workingDirectory, trainShape,
725 726  
726 727 if (nb_feat_Nannu > 0) and (nb_feat_annu > 0 and annualPoints):
727 728 fu.mergeSQLite(MergeName, workingDirectory,[nonAnnualShape, AnnualShape])
  729 +
728 730 elif (nb_feat_Nannu > 0) and not (nb_feat_annu > 0 and annualPoints):
729 731 shutil.copy(SampleSel_NA, sampleSelection)
730 732 elif not (nb_feat_Nannu > 0) and (nb_feat_annu > 0 and annualPoints):
... ... @@ -733,7 +735,7 @@ def generateSamples_classifMix(folderSample, workingDirectory, trainShape,
733 735  
734 736 sampleExtr, dep_tmp = gapFillingToSample(sampleSelection,
735 737 workingDirectory, samples,
736   - dataField, cfg, wMode)
  738 + dataField, cfg, wMode)
737 739  
738 740  
739 741 sampleExtr.ExecuteAndWriteOutput()
... ... @@ -750,6 +752,8 @@ def generateSamples_classifMix(folderSample, workingDirectory, trainShape,
750 752  
751 753 if os.path.exists(nonAnnualShape):
752 754 os.remove(nonAnnualShape)
  755 + if os.path.exists(AnnualShape):
  756 + os.remove(AnnualShape)
753 757  
754 758 if not sampleSel:
755 759 os.remove(sampleSelection)
... ... @@ -768,6 +772,11 @@ def generateSamples_classifMix(folderSample, workingDirectory, trainShape,
768 772 fu.updateDirectory(workingDirectory + "/" + currentTile + "/tmp", targetDirectory + "/tmp")
769 773  
770 774 os.remove(samples)
  775 + os.remove(classificationRaster)
  776 + os.remove(validityRaster)
  777 + for mask in masks:
  778 + os.remove(mask)
  779 +
771 780  
772 781 def cleanContentRepo(outputPath):
773 782 """
... ...