Skip to content

Commit

Permalink
Added functions rsgislib.imagecalc.calc_band_range_thres_msk and rsgi…
Browse files Browse the repository at this point in the history
…slib.imagecalc.calc_band_percentile_msk
  • Loading branch information
petebunting committed Jun 24, 2024
1 parent 2f7ca73 commit ee74e5c
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 3 deletions.
6 changes: 4 additions & 2 deletions doc/python/source/rsgislib_imagecalc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Band & Image Maths
.. autofunction:: rsgislib.imagecalc.image_math
.. autofunction:: rsgislib.imagecalc.image_band_math
.. autofunction:: rsgislib.imagecalc.all_bands_equal_to
.. autofunction:: rsgislib.imagecalc.calc_band_range_thres_msk
.. autoclass:: rsgislib.imagecalc.BandDefn


Expand All @@ -25,6 +26,8 @@ Statistical Summary
.. autofunction:: rsgislib.imagecalc.calc_img_mean
.. autofunction:: rsgislib.imagecalc.calc_img_stdev
.. autofunction:: rsgislib.imagecalc.calc_band_percentile
.. autofunction:: rsgislib.imagecalc.calc_band_percentile_msk
.. autofunction:: rsgislib.imagecalc.calc_imgs_pxl_percentiles
.. autofunction:: rsgislib.imagecalc.get_img_band_stats_in_env
.. autofunction:: rsgislib.imagecalc.get_img_band_mode_in_env
.. autofunction:: rsgislib.imagecalc.calc_prop_true_exp
Expand All @@ -35,12 +38,11 @@ Statistical Summary
.. autofunction:: rsgislib.imagecalc.identify_min_pxl_value_in_win
.. autofunction:: rsgislib.imagecalc.calc_img_mean_in_mask
.. autofunction:: rsgislib.imagecalc.count_pxls_of_val
.. autofunction:: rsgislib.imagecalc.count_imgs_int_val_occur
.. autofunction:: rsgislib.imagecalc.get_unique_values
.. autofunction:: rsgislib.imagecalc.calc_imgs_pxl_mode
.. autofunction:: rsgislib.imagecalc.calc_img_basic_stats_for_ref_region
.. autofunction:: rsgislib.imagecalc.calc_sum_stats_msk_vals
.. autofunction:: rsgislib.imagecalc.count_imgs_int_val_occur
.. autofunction:: rsgislib.imagecalc.calc_imgs_pxl_percentiles
.. autoclass:: rsgislib.imagecalc.StatsSummary


Expand Down
8 changes: 8 additions & 0 deletions python/rsgislib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@
* STATS_CORR_KENDALL_TAU = 3
* STATS_CORR_POINT_BISERIAL = 4
Options for logical combination of data:
LOGIC_AND = 1
LOGIC_OR = 2
"""
from __future__ import print_function

Expand Down Expand Up @@ -284,6 +289,9 @@
STATS_CORR_KENDALL_TAU = 3 # Kendall's tau
STATS_CORR_POINT_BISERIAL = 4 # pointbiserialr

LOGIC_AND = 1
LOGIC_OR = 2


def get_install_base_path() -> pathlib.PurePath:
"""
Expand Down
108 changes: 107 additions & 1 deletion python/rsgislib/imagecalc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1428,7 +1428,7 @@ def recode_int_raster(
def _recode(info, inputs, outputs, otherargs):
out_arr = numpy.zeros_like(inputs.inimage[0], dtype=otherargs.np_dtype)
if otherargs.keep_vals_not_in_dict:
numpy.copyto(out_arr, inputs.inimage[0], casting='same_kind')
numpy.copyto(out_arr, inputs.inimage[0], casting="same_kind")

for rc_val in recode_dict:
out_arr[inputs.inimage[0] == rc_val] = recode_dict[rc_val]
Expand Down Expand Up @@ -2770,3 +2770,109 @@ def _applyNormalisation(info, inputs, outputs, otherargs):
applier.apply(_applyNormalisation, infiles, outfiles, otherargs, controls=aControls)

return stch_min_max_vals


def calc_band_percentile_msk(
input_img: str,
in_msk_img: str,
msk_val: int,
percentiles: List[float],
no_data_val: float = None,
):
"""
A function to calculate the percentiles for all the bands in the
input image for the pixels specified within the input image mask.
:param input_img: Input image on which the percentiles will be calculated
:param in_msk_img: Input mask for which the percentiles will be calculated
:param msk_val: The image mask value
:param percentiles: list of percentiles to be calculated
:param no_data_val: no data value for the input image.
"""
n_bands = rsgislib.imageutils.get_img_band_count(input_img)
img_bands = list(range(1, n_bands + 1, 1))

pxl_vals = rsgislib.imageutils.extract_img_pxl_vals_in_msk(
input_img=input_img,
img_bands=img_bands,
in_msk_img=in_msk_img,
img_mask_val=msk_val,
no_data_val=no_data_val,
)
percent_vals = numpy.percentile(pxl_vals, percentiles, axis=0)

return percent_vals


def calc_band_range_thres_msk(
input_img: str,
output_img: str,
band_thres_dict: Dict[int, Tuple[float, float]],
gdalformat: str = "KEA",
combine_mthd: int = rsgislib.LOGIC_AND,
):
"""
A function which applies a list of min/max thresholds to the image bands witin
the input image. The thresholds are specified as a dictionary with the key being
the band number (band numbering starts from 1) and the value being a tuple
(min, max) where a true pixel value is > min and < max. A band can be used multiple
times within the thresholds dictionary. The different thresholds produce a series
of binary mask which are combined using either an 'and' (min) or a 'or' (max)
operation.
:param input_img: Input image path
:param output_img: Output image path
:param band_thres_dict: Dictionary of band thresholds using the key being the
band number and the value being a tuple (min, max).
:param gdalformat: The output gdal format
:param combine_mthd: the method of combining the band thresholds into a single
output image. Options are either rsgislib.LOGIC_AND (Default)
or rsgislib.LOGIC_OR
"""
from rios import applier

if TQDM_AVAIL:
progress_bar = rsgislib.TQDMProgressBar()
else:
progress_bar = rios.cuiprogress.GDALProgressBar()

# Generated the combined mask.
infiles = applier.FilenameAssociations()
infiles.inimage = input_img
outfiles = applier.FilenameAssociations()
outfiles.outimage = output_img
otherargs = applier.OtherInputs()
otherargs.band_thres_dict = band_thres_dict
otherargs.combine_mthd = combine_mthd
aControls = applier.ApplierControls()
aControls.progress = progress_bar
aControls.drivername = gdalformat
aControls.omitPyramids = False
aControls.calcStats = False

def _calc_thres_msk(info, inputs, outputs, otherargs):
msk_arrs = []
for band_n in band_thres_dict:
band_arr = inputs.inimage[band_n - 1]
msk_arrs.append(
numpy.logical_and(
band_arr > band_thres_dict[band_n][0],
band_arr < band_thres_dict[band_n][1],
)
)

msk_arr = numpy.array(msk_arrs, dtype=numpy.uint8)
if otherargs.combine_mthd == rsgislib.LOGIC_OR:
out_msk_arr = msk_arr.max(axis=0)
elif otherargs.combine_mthd == rsgislib.LOGIC_AND:
out_msk_arr = msk_arr.min(axis=0)
else:
raise rsgislib.RSGISPyException(
"Do not recognise combine_mthd: should be "
"rsgislib.LOGIC_OR or rsgislib.LOGIC_AND"
)
outputs.outimage = numpy.expand_dims(out_msk_arr, axis=0)

applier.apply(_calc_thres_msk, infiles, outfiles, otherargs, controls=aControls)

0 comments on commit ee74e5c

Please sign in to comment.