diff --git a/eis_toolkit/cli.py b/eis_toolkit/cli.py index ae78b62d..c92246c8 100644 --- a/eis_toolkit/cli.py +++ b/eis_toolkit/cli.py @@ -200,6 +200,27 @@ class NodataHandling(str, Enum): remove = "remove" +class FocalFilterMethod(str, Enum): + """Focal filter methods.""" + + mean = "mean" + median = "median" + + +class FocalFilterShape(str, Enum): + """Shape of the filter window.""" + + square = "square" + circle = "circle" + + +class MexicanHatFilterDirection(str, Enum): + """Direction of calculating kernel values.""" + + rectangular = "rectangular" + circular = "circular" + + class LocalMoranWeightType(str, Enum): """Weight type for Local Moran's I.""" @@ -533,6 +554,276 @@ def local_morans_i_cli( # --- RASTER PROCESSING --- +# FOCAL FILTER +@app.command() +def focal_filter_cli( + input_raster: Annotated[Path, INPUT_FILE_OPTION], + output_raster: Annotated[Path, OUTPUT_FILE_OPTION], + method: FocalFilterMethod = FocalFilterMethod.mean, + size: int = 3, + shape: FocalFilterShape = FocalFilterShape.circle, +): + """Apply a basic focal filter to the input raster.""" + from eis_toolkit.raster_processing.filters.focal import focal_filter + + typer.echo("Progress: 10%") + + with rasterio.open(input_raster) as raster: + typer.echo("Progress: 25%") + out_image, out_meta = focal_filter(raster=raster, method=method, size=size, shape=shape) + typer.echo("Progress: 75%") + + with rasterio.open(output_raster, "w", **out_meta) as dest: + dest.write(out_image, 1) + typer.echo("Progress: 100%") + + typer.echo(f"Focal filter applied, output raster written to {output_raster}.") + + +# GAUSSIAN FILTER +@app.command() +def gaussian_filter_cli( + input_raster: Annotated[Path, INPUT_FILE_OPTION], + output_raster: Annotated[Path, OUTPUT_FILE_OPTION], + sigma: float = 1.0, + truncate: float = 4.0, + size: int = None, +): + """Apply a gaussian filter to the input raster.""" + from eis_toolkit.raster_processing.filters.focal import gaussian_filter + + typer.echo("Progress: 10%") + + with rasterio.open(input_raster) as raster: + typer.echo("Progress: 25%") + out_image, out_meta = gaussian_filter(raster=raster, sigma=sigma, truncate=truncate, size=size) + typer.echo("Progress: 75%") + + with rasterio.open(output_raster, "w", **out_meta) as dest: + dest.write(out_image, 1) + typer.echo("Progress: 100%") + + typer.echo(f"Gaussial filter applied, output raster written to {output_raster}.") + + +# MEXICAN HAT FILTER +@app.command() +def mexican_hat_filter_cli( + input_raster: Annotated[Path, INPUT_FILE_OPTION], + output_raster: Annotated[Path, OUTPUT_FILE_OPTION], + sigma: float = 1.0, + truncate: float = 4.0, + size: int = None, + direction: MexicanHatFilterDirection = MexicanHatFilterDirection.circular, +): + """Apply a mexican hat filter to the input raster.""" + from eis_toolkit.raster_processing.filters.focal import mexican_hat_filter + + typer.echo("Progress: 10%") + + with rasterio.open(input_raster) as raster: + typer.echo("Progress: 25%") + out_image, out_meta = mexican_hat_filter( + raster=raster, sigma=sigma, truncate=truncate, size=size, direction=direction + ) + typer.echo("Progress: 75%") + + with rasterio.open(output_raster, "w", **out_meta) as dest: + dest.write(out_image, 1) + typer.echo("Progress: 100%") + + typer.echo(f"Mexican hat filter applied, output raster written to {output_raster}.") + + +# LEE ADDITIVE NOISE FILTER +@app.command() +def lee_additive_noise_filter_cli( + input_raster: Annotated[Path, INPUT_FILE_OPTION], + output_raster: Annotated[Path, OUTPUT_FILE_OPTION], + size: int = 3, + add_noise_var: float = 0.25, +): + """Apply a Lee filter considering additive noise components in the input raster.""" + from eis_toolkit.raster_processing.filters.speckle import lee_additive_noise_filter + + typer.echo("Progress: 10%") + + with rasterio.open(input_raster) as raster: + typer.echo("Progress: 25%") + out_image, out_meta = lee_additive_noise_filter(raster=raster, size=size, add_noise_var=add_noise_var) + typer.echo("Progress: 75%") + + with rasterio.open(output_raster, "w", **out_meta) as dest: + dest.write(out_image, 1) + typer.echo("Progress: 100%") + + typer.echo(f"Additive Lee noise filter applied, output raster written to {output_raster}.") + + +# LEE MULTIPLICATIVE NOISE FILTER +@app.command() +def lee_multiplicative_noise_filter_cli( + input_raster: Annotated[Path, INPUT_FILE_OPTION], + output_raster: Annotated[Path, OUTPUT_FILE_OPTION], + size: int = 3, + multi_noise_mean: float = 1.0, + n_looks: int = 1, +): + """Apply a Lee filter considering multiplicative noise components in the input raster.""" + from eis_toolkit.raster_processing.filters.speckle import lee_multiplicative_noise_filter + + typer.echo("Progress: 10%") + + with rasterio.open(input_raster) as raster: + typer.echo("Progress: 25%") + out_image, out_meta = lee_multiplicative_noise_filter( + raster=raster, size=size, mult_noise_mean=multi_noise_mean, n_looks=n_looks + ) + typer.echo("Progress: 75%") + + with rasterio.open(output_raster, "w", **out_meta) as dest: + dest.write(out_image, 1) + typer.echo("Progress: 100%") + + typer.echo(f"Multiplicative Lee noise filter applied, output raster written to {output_raster}.") + + +# LEE ADDITIVE MULTIPLICATIVE NOISE FILTER +@app.command() +def lee_additive_multiplicative_noise_filter_cli( + input_raster: Annotated[Path, INPUT_FILE_OPTION], + output_raster: Annotated[Path, OUTPUT_FILE_OPTION], + size: int = 3, + add_noise_var: float = 0.25, + add_noise_mean: float = 0, + multi_noise_mean: float = 1.0, +): + """Apply a Lee filter considering both additive and multiplicative noise components in the input raster.""" + from eis_toolkit.raster_processing.filters.speckle import lee_additive_multiplicative_noise_filter + + typer.echo("Progress: 10%") + + with rasterio.open(input_raster) as raster: + typer.echo("Progress: 25%") + out_image, out_meta = lee_additive_multiplicative_noise_filter( + raster=raster, + size=size, + add_noise_var=add_noise_var, + add_noise_mean=add_noise_mean, + mult_noise_mean=multi_noise_mean, + ) + typer.echo("Progress: 75%") + + with rasterio.open(output_raster, "w", **out_meta) as dest: + dest.write(out_image, 1) + typer.echo("Progress: 100%") + + typer.echo(f"Additive multiplicative Lee noise filter applied, output raster written to {output_raster}.") + + +# LEE ENHANCED FILTER +@app.command() +def lee_enhanced_filter_cli( + input_raster: Annotated[Path, INPUT_FILE_OPTION], + output_raster: Annotated[Path, OUTPUT_FILE_OPTION], + size: int = 3, + n_looks: int = 1, + damping_factor: float = 1.0, +): + """Apply an enhanced Lee filter to the input raster.""" + from eis_toolkit.raster_processing.filters.speckle import lee_enhanced_filter + + typer.echo("Progress: 10%") + + with rasterio.open(input_raster) as raster: + typer.echo("Progress: 25%") + out_image, out_meta = lee_enhanced_filter( + raster=raster, size=size, n_looks=n_looks, damping_factor=damping_factor + ) + typer.echo("Progress: 75%") + + with rasterio.open(output_raster, "w", **out_meta) as dest: + dest.write(out_image, 1) + typer.echo("Progress: 100%") + + typer.echo(f"Enhanced Lee filter applied, output raster written to {output_raster}.") + + +# GAMMA FILTER +@app.command() +def gamma_filter_cli( + input_raster: Annotated[Path, INPUT_FILE_OPTION], + output_raster: Annotated[Path, OUTPUT_FILE_OPTION], + size: int = 3, + n_looks: int = 1, +): + """Apply a Gamma filter to the input raster.""" + from eis_toolkit.raster_processing.filters.speckle import gamma_filter + + typer.echo("Progress: 10%") + + with rasterio.open(input_raster) as raster: + typer.echo("Progress: 25%") + out_image, out_meta = gamma_filter(raster=raster, size=size, n_looks=n_looks) + typer.echo("Progress: 75%") + + with rasterio.open(output_raster, "w", **out_meta) as dest: + dest.write(out_image, 1) + typer.echo("Progress: 100%") + + typer.echo(f"Gamma filter applied, output raster written to {output_raster}.") + + +# FROST FILTER +@app.command() +def frost_filter_cli( + input_raster: Annotated[Path, INPUT_FILE_OPTION], + output_raster: Annotated[Path, OUTPUT_FILE_OPTION], + size: int = 3, + damping_factor: float = 1.0, +): + """Apply a Frost filter to the input raster.""" + from eis_toolkit.raster_processing.filters.speckle import frost_filter + + typer.echo("Progress: 10%") + + with rasterio.open(input_raster) as raster: + typer.echo("Progress: 25%") + out_image, out_meta = frost_filter(raster=raster, size=size, damping_factor=damping_factor) + typer.echo("Progress: 75%") + + with rasterio.open(output_raster, "w", **out_meta) as dest: + dest.write(out_image, 1) + typer.echo("Progress: 100%") + + typer.echo(f"Frost filter applied, output raster written to {output_raster}.") + + +# KUAN FILTER +@app.command() +def kuan_filter_cli( + input_raster: Annotated[Path, INPUT_FILE_OPTION], + output_raster: Annotated[Path, OUTPUT_FILE_OPTION], + size: int = 3, + n_looks: int = 1, +): + """Apply a Kuan filter to the input raster.""" + from eis_toolkit.raster_processing.filters.speckle import kuan_filter + + typer.echo("Progress: 10%") + + with rasterio.open(input_raster) as raster: + typer.echo("progress: 25%") + out_image, out_meta = kuan_filter(raster=raster, size=size, n_looks=n_looks) + typer.echo("Progress: 75%") + + with rasterio.open(output_raster, "w", **out_meta) as dest: + dest.write(out_image, 1) + typer.echo("Progress: 100%") + + typer.echo(f"Kuan filter applied, output raster written to {output_raster}.") + + # CHECK RASTER GRIDS @app.command() def check_raster_grids_cli(input_rasters: INPUT_FILES_ARGUMENT, same_extent: bool = False): diff --git a/eis_toolkit/raster_processing/filters/speckle.py b/eis_toolkit/raster_processing/filters/speckle.py index 387fd801..b1aa2779 100644 --- a/eis_toolkit/raster_processing/filters/speckle.py +++ b/eis_toolkit/raster_processing/filters/speckle.py @@ -179,7 +179,7 @@ def _gamma(window: np.ndarray, n_looks: int) -> np.ndarray: @beartype -def _frost(window: np.ndarray, damping_factor: int) -> Number: +def _frost(window: np.ndarray, damping_factor: Number) -> Number: """ Calculate the weighted value for a Frost filter from a window of pixels. @@ -381,8 +381,8 @@ def lee_additive_multiplicative_noise_filter( def lee_enhanced_filter( raster: rasterio.io.DatasetReader, size: int = 3, - n_looks: Number = 1, - damping_factor: Number = 1, + n_looks: int = 1, + damping_factor: Number = 1.0, ) -> tuple[np.ndarray, dict]: """ Apply an enhanced Lee filter to the input raster. @@ -431,7 +431,7 @@ def lee_enhanced_filter( def gamma_filter( raster: rasterio.io.DatasetReader, size: int = 3, - n_looks: Number = 1, + n_looks: int = 1, ) -> tuple[np.ndarray, dict]: """ Apply a Gamma filter to the input raster. @@ -476,7 +476,7 @@ def gamma_filter( def frost_filter( raster: rasterio.io.DatasetReader, size: int = 3, - damping_factor: Number = 1, + damping_factor: Number = 1.0, ) -> tuple[np.ndarray, dict]: """ Apply a Frost filter to the input raster. @@ -521,7 +521,7 @@ def frost_filter( def kuan_filter( raster: rasterio.io.DatasetReader, size: int = 3, - n_looks: Number = 1, + n_looks: int = 1, ) -> tuple[np.ndarray, dict]: """ Apply a Kuan filter to the input raster.