Skip to content

Commit 755662f

Browse files
thuydotmgiancastro
andauthored
true_color: added output name and attrs (#484)
* true_color: name of output data array * output attrs * docs * added contrast as input param * example * Update xrspatial/multispectral.py Co-authored-by: Giancarlo Castro <giancastrok@gmail.com> * Update xrspatial/multispectral.py Co-authored-by: Giancarlo Castro <giancastrok@gmail.com> * fix true_color function docstring Co-authored-by: Giancarlo Castro <giancastrok@gmail.com>
1 parent 317beb4 commit 755662f

File tree

2 files changed

+87
-30
lines changed

2 files changed

+87
-30
lines changed

xrspatial/multispectral.py

Lines changed: 81 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,14 +1528,14 @@ def ebbi(red_agg: xr.DataArray,
15281528

15291529

15301530
@ngjit
1531-
def _normalize_data_cpu(data, min_val, max_val, pixel_max):
1531+
def _normalize_data_cpu(data, min_val, max_val, pixel_max, contrast):
15321532
out = np.zeros_like(data)
15331533
out[:] = np.nan
15341534

15351535
range_val = max_val - min_val
15361536
rows, cols = data.shape
15371537

1538-
c = 10
1538+
c = contrast
15391539
th = .125
15401540

15411541
# check range_val to avoid dividing by zero
@@ -1550,35 +1550,37 @@ def _normalize_data_cpu(data, min_val, max_val, pixel_max):
15501550
return out
15511551

15521552

1553-
def _normalize_data_numpy(data, pixel_max):
1553+
def _normalize_data_numpy(data, pixel_max, contrast):
15541554
min_val = np.nanmin(data)
15551555
max_val = np.nanmax(data)
1556-
out = _normalize_data_cpu(data, min_val, max_val, pixel_max)
1556+
out = _normalize_data_cpu(data, min_val, max_val, pixel_max, contrast)
15571557
return out
15581558

15591559

1560-
def _normalize_data_dask(data, pixel_max):
1560+
def _normalize_data_dask(data, pixel_max, contrast):
15611561
min_val = da.nanmin(data)
15621562
max_val = da.nanmax(data)
1563-
out = da.map_blocks(_normalize_data_cpu, data, min_val, max_val, pixel_max,
1564-
meta=np.array(()))
1563+
out = da.map_blocks(
1564+
_normalize_data_cpu, data, min_val, max_val, pixel_max, contrast,
1565+
meta=np.array(())
1566+
)
15651567
return out
15661568

15671569

1568-
def _normalize_data_cupy(data, pixel_max):
1570+
def _normalize_data_cupy(data, pixel_max, contrast):
15691571
raise NotImplementedError('Not Supported')
15701572

15711573

1572-
def _normalize_data_dask_cupy(data, pixel_max):
1574+
def _normalize_data_dask_cupy(data, pixel_max, contrast):
15731575
raise NotImplementedError('Not Supported')
15741576

15751577

1576-
def _normalize_data(agg, pixel_max=255.0):
1578+
def _normalize_data(agg, pixel_max=255.0, contrast=10):
15771579
mapper = ArrayTypeFunctionMapping(numpy_func=_normalize_data_numpy,
15781580
dask_func=_normalize_data_dask,
15791581
cupy_func=_normalize_data_cupy,
15801582
dask_cupy_func=_normalize_data_dask_cupy)
1581-
out = mapper(agg)(agg.data, pixel_max)
1583+
out = mapper(agg)(agg.data, pixel_max, contrast)
15821584
return out
15831585

15841586

@@ -1609,56 +1611,107 @@ def _alpha(red, nodata=1):
16091611
return out
16101612

16111613

1612-
def _true_color_numpy(r, g, b, nodata):
1614+
def _true_color_numpy(r, g, b, nodata, contrast):
16131615
a = np.where(np.logical_or(np.isnan(r), r <= nodata), 0, 255)
16141616

16151617
h, w = r.shape
16161618
out = np.zeros((h, w, 4), dtype=np.uint8)
16171619

16181620
pixel_max = 255
1619-
out[:, :, 0] = (_normalize_data(r, pixel_max)).astype(np.uint8)
1620-
out[:, :, 1] = (_normalize_data(g, pixel_max)).astype(np.uint8)
1621-
out[:, :, 2] = (_normalize_data(b, pixel_max)).astype(np.uint8)
1621+
out[:, :, 0] = (_normalize_data(r, pixel_max, contrast)).astype(np.uint8)
1622+
out[:, :, 1] = (_normalize_data(g, pixel_max, contrast)).astype(np.uint8)
1623+
out[:, :, 2] = (_normalize_data(b, pixel_max, contrast)).astype(np.uint8)
16221624
out[:, :, 3] = a.astype(np.uint8)
16231625
return out
16241626

16251627

1626-
def _true_color_dask(r, g, b, nodata):
1628+
def _true_color_dask(r, g, b, nodata, contrast):
16271629
pixel_max = 255
1628-
red = (_normalize_data(r, pixel_max)).astype(np.uint8)
1629-
green = (_normalize_data(g, pixel_max)).astype(np.uint8)
1630-
blue = (_normalize_data(b, pixel_max)).astype(np.uint8)
1630+
red = (_normalize_data(r, pixel_max, contrast)).astype(np.uint8)
1631+
green = (_normalize_data(g, pixel_max, contrast)).astype(np.uint8)
1632+
blue = (_normalize_data(b, pixel_max, contrast)).astype(np.uint8)
16311633

16321634
alpha = _alpha(r, nodata).astype(np.uint8)
16331635

16341636
out = da.stack([red, green, blue, alpha], axis=-1)
16351637
return out
16361638

16371639

1638-
def _true_color_cupy(r, g, b, nodata):
1640+
def _true_color_cupy(r, g, b, nodata, contrast):
16391641
raise NotImplementedError('Not Supported')
16401642

16411643

1642-
def _true_color_dask_cupy(r, g, b, nodata):
1644+
def _true_color_dask_cupy(r, g, b, nodata, contrast):
16431645
raise NotImplementedError('Not Supported')
16441646

16451647

1646-
def true_color(r, g, b, nodata=1, name='true_color'):
1648+
def true_color(r, g, b, nodata=1, contrast=10.0, name='true_color'):
1649+
"""
1650+
Create true color composite from a combination of red, green and
1651+
blue bands satellite images.
1652+
1653+
Parameters
1654+
----------
1655+
r : xarray.DataArray
1656+
2D array of red band data.
1657+
g : xarray.DataArray
1658+
2D array of green band data.
1659+
b : xarray.DataArray
1660+
2D array of blue band data.
1661+
nodata : int, float numeric value
1662+
Nodata value of input DataArrays.
1663+
contrast : int, float numeric value
1664+
Contrast controlling parameter for output image.
1665+
name : str, default='true_color'
1666+
Name of output DataArray.
1667+
1668+
Returns
1669+
-------
1670+
true_color_agg : xarray.DataArray of the same type as inputs
1671+
3D array true color image with dims of [y, x, band].
1672+
All output attributes are copied from red band image.
1673+
1674+
1675+
Examples
1676+
--------
1677+
.. plot::
1678+
:include-source:
1679+
1680+
import matplotlib.pyplot as plt
1681+
from xrspatial.multispectral import true_color
1682+
from xrspatial.datasets import get_data
1683+
1684+
# Open Example Data
1685+
data = get_data('sentinel-2')
1686+
1687+
red = data['Red']
1688+
green = data['Green']
1689+
blue = data['Blue']
1690+
1691+
# Generate ARVI Aggregate Array
1692+
true_color_img = true_color(r=red, g=green, b=blue)
1693+
true_color_img.plot.imshow()
1694+
"""
1695+
16471696
mapper = ArrayTypeFunctionMapping(numpy_func=_true_color_numpy,
16481697
dask_func=_true_color_dask,
16491698
cupy_func=_true_color_cupy,
16501699
dask_cupy_func=_true_color_dask_cupy)
16511700
with warnings.catch_warnings():
16521701
warnings.simplefilter('ignore')
1653-
out = mapper(r)(r, g, b, nodata)
1702+
out = mapper(r)(r, g, b, nodata, contrast)
16541703

1655-
# TODO: output metadata: coords, dims, atts
1704+
# TODO: output metadata: coords, dims, attrs
16561705
_dims = ['y', 'x', 'band']
1706+
_attrs = r.attrs
16571707
_coords = {'y': r['y'],
16581708
'x': r['x'],
16591709
'band': [0, 1, 2, 3]}
16601710

1661-
return DataArray(out,
1662-
dims=_dims,
1663-
coords=_coords
1664-
)
1711+
return DataArray(
1712+
out,
1713+
name=name,
1714+
dims=_dims,
1715+
coords=_coords,
1716+
attrs=_attrs,
1717+
)

xrspatial/tests/test_multispectral.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -788,13 +788,17 @@ def test_true_color_cpu():
788788
red = create_test_arr(arr1)
789789
green = create_test_arr(arr2)
790790
blue = create_test_arr(arr3)
791-
numpy_result = true_color(red, green, blue)
791+
numpy_result = true_color(red, green, blue, name='np_true_color')
792+
assert numpy_result.name == 'np_true_color'
792793

793794
# dask
794795
red_dask = create_test_arr(arr1, backend='dask')
795796
green_dask = create_test_arr(arr2, backend='dask')
796797
blue_dask = create_test_arr(arr3, backend='dask')
797-
dask_result = true_color(red_dask, green_dask, blue_dask)
798+
dask_result = true_color(
799+
red_dask, green_dask, blue_dask, name='dask_true_color'
800+
)
801+
assert dask_result.name == 'dask_true_color'
798802

799803
# TODO: test output metadata: dims, coords, attrs
800804
assert isinstance(numpy_result, xa.DataArray)

0 commit comments

Comments
 (0)