import numpy as np
from eolearn.core import FeatureType, EOTask, AddFeatureTask
from pathlib import Path
from osgeo import gdal
import os
import shutil
import subprocess
import rasterio
from eolearn.io import ExportToTiffTask, ImportFromTiffTask
[docs]class MultitempSpeckleFiltering(EOTask):
def __init__(self, otb_path, feature_name="BANDS-S1-IW", path_in="./", window=3):
"""
Multitemporal filtering ONLY for Sentinel-1 data using OTB
Parameters
----------
otb_path : str
Path where bin from Orfeo Toolbox package is installed
path_in : str
Path to write the temporary files (removed at the end of the process)
window : int
window to apply for Quegan filter for SAR data
"""
self.feature_name = feature_name
self.otb_path = otb_path
self.path_in = path_in
self.window = window
@staticmethod
def _refactor_dates(t):
# Add dates as suffix
year, d, m = str(t.year), str(t.day), str(t.month)
if len(d) == 1:
d = "0" + d
if len(m) == 1:
m = "0" + m
return "{0}{1}{2}".format(year, m, d)
def _apply_OTB_cmd(self, pol, ram=8):
path_in = os.path.join(self.path_in, "S1_" + pol)
s1_images = os.listdir(path_in)
infiles = [os.path.join(path_in, k) for k in s1_images]
infiles.sort()
cmd = [os.path.join(self.otb_path, "otbcli_MultitempFilteringOutcore"), "-inl"]
cmd += infiles
cmd += [
"-wr",
str(self.window),
"-oc",
os.path.join(path_in, "outcore.tif"),
"-ram",
str(8),
]
outdir = Path(path_in + "_filtered")
if not outdir.exists():
os.mkdir(outdir)
subprocess.call(cmd, shell=False)
cmd = [os.path.join(self.otb_path, "otbcli_MultitempFilteringFilter"), "-inl"]
cmd += infiles
cmd += [
"-enl",
os.path.join(outdir, "enl.tif"),
"-wr",
str(self.window),
"-filtpath",
outdir,
"-oc",
os.path.join(path_in, "outcore.tif"),
"-ram",
str(ram),
]
subprocess.call(cmd, shell=False)
outfiles = [
os.path.join(outdir, k.split(".")[0] + "_filtered.tif") for k in s1_images
]
outfiles.sort()
return infiles, outdir, outfiles
def _save_temporary_geotiff(self, i, date, eopatch):
## TODO : Find a way to write temporary file without writing on disk using ExportToTiffTask to make the process faster
export = ExportToTiffTask(
feature=(FeatureType.DATA, self.feature_name),
folder=os.path.join(self.path_in, "S1_VV/S1_VV_" + date),
band_indices=[0],
date_indices=[i],
)
export.execute(eopatch)
export = ExportToTiffTask(
feature=(FeatureType.DATA, self.feature_name),
folder=os.path.join(self.path_in, "S1_VH/S1_VH_" + date),
band_indices=[1],
date_indices=[i],
)
export.execute(eopatch)
def execute(self, eopatch, ram=8):
"""EOTask to execute the speckle filtering over the EOPatch"""
if os.path.exists(os.path.join(self.path_in, "S1_VV")):
shutil.rmtree(os.path.join(self.path_in, "S1_VV"))
shutil.rmtree(os.path.join(self.path_in, "S1_VH"))
os.mkdir(os.path.join(self.path_in, "S1_VV"))
os.mkdir(os.path.join(self.path_in, "S1_VH"))
times = list(eopatch.timestamp)
for i, t in enumerate(times):
date = self._refactor_dates(t)
self._save_temporary_geotiff(i, date, eopatch)
########################################################################################################
for pol in ["VV", "VH"]:
infiles, outdir, outfiles = self._apply_OTB_cmd(pol, ram)
##########################################################################
reference_file = infiles[0]
with rasterio.open(reference_file) as src0:
meta = src0.meta
meta["nodata"] = 0.0
meta["dtype"] = "float32"
meta["count"] = len(times)
year = str(eopatch.timestamp[0].year)
path_tif = outfiles[0].split("_" + year)[0] + ".tif"
if "outcore_filtered.tif" in os.listdir(str(outdir)):
outfiles.remove(os.path.join(outdir, "outcore_filtered.tif"))
outfiles.sort()
with rasterio.open(
os.path.join(self.path_in, path_tif), "w", **meta
) as dst:
for i in range(1, len(times) + 1):
img = gdal.Open(
os.path.join(self.path_in, outfiles[i - 1])
).ReadAsArray()
dst.write_band(i, img)
import_tif = ImportFromTiffTask(
(FeatureType.DATA, pol + "_filtered"), path_tif
)
eopatch = import_tif.execute(eopatch)
shutil.rmtree(os.path.join(self.path_in, "S1_VV_filtered"))
shutil.rmtree(os.path.join(self.path_in, "S1_VH_filtered"))
shutil.rmtree(os.path.join(self.path_in, "S1_VV"))
shutil.rmtree(os.path.join(self.path_in, "S1_VH"))
return eopatch
[docs]class PanSharpening(EOTask):
def __init__(
self,
fname="BANDS",
otb_path="/home/s999379/git-repo/OTB-7.4.0-Linux64/bin",
path_temporary_files="./tempo",
):
"""
Pansharpening for VHRS data. You must have a panchromatic band to make it working.
Parameters:
fname : str
Name of the feature stored in data that gathers the bands
otb_path : str
Path where bin from Orfeo Toolbox package is installed
path_temporary_files : str
path to save the temporary geotiff file to call OTB
"""
self.fname = fname
self.otb_path = otb_path
self.path_temporary_files = path_temporary_files
@staticmethod
def _refactor_dates(t):
# Add dates as suffix
year, d, m = str(t.year), str(t.day), str(t.month)
if len(d) == 1:
d = "0" + d
if len(m) == 1:
m = "0" + m
return "{0}{1}{2}".format(year, m, d)
def _extracted_from__save_temporary_geotiff(
self, date, i, eopatch, band_indices=None
):
if band_indices is None:
band_indices = list(range(4))
export = ExportToTiffTask(
feature=(FeatureType.DATA, self.fname),
folder=os.path.join(self.path_temporary_files, "PAN_" + date),
band_indices=[-1],
date_indices=[i],
)
export.execute(eopatch)
export = ExportToTiffTask(
feature=(FeatureType.DATA, self.fname),
folder=os.path.join(self.path_temporary_files, "BANDS_" + date),
band_indices=band_indices,
date_indices=[i],
)
export.execute(eopatch)
def _apply_OTB_cmd(self, date):
cm = [
os.path.join(self.otb_path, "otbcli_Pansharpening"),
"-inp",
os.path.join(self.path_temporary_files, "PAN_" + date + ".tif"),
"-inxs",
os.path.join(self.path_temporary_files, "BANDS_" + date + ".tif"),
"-method",
"lmvm",
"-out",
os.path.join(self.path_temporary_files, "Pansharpened_" + date + ".tif"),
"float",
]
subprocess.call(cm, shell=False)
def _clean_temporary_files(self):
shutil.rmtree(self.path_temporary_files)
def execute(self, eopatch, band_indices=None):
"""EOTask to execute the Pansharpening given the EOPatch"""
times = list(eopatch.timestamp)
pan_bands = []
for i, t in enumerate(times):
date = self._refactor_dates(t)
self._extracted_from__save_temporary_geotiff(date, i, eopatch, band_indices)
self._apply_OTB_cmd(date)
img = gdal.Open(
os.path.join(self.path_temporary_files, "Pansharpened_" + date + ".tif")
).ReadAsArray()
img = np.moveaxis(img, 0, -1)
pan_bands.append(img)
pan_bands = np.stack(pan_bands, axis=0)
self._clean_temporary_files()
add_pan = AddFeatureTask((FeatureType.DATA, "BANDS-PAN"))
return add_pan.execute(eopatch=eopatch, data=pan_bands)