@@ -1528,16 +1528,13 @@ def ebbi(red_agg: xr.DataArray,
15281528
15291529
15301530@ngjit
1531- def _normalize_data_cpu (data , min_val , max_val , pixel_max , contrast ):
1531+ def _normalize_data_cpu (data , min_val , max_val , pixel_max , c , th ):
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 = contrast
1539- th = .125
1540-
15411538 # check range_val to avoid dividing by zero
15421539 if range_val != 0 :
15431540 for y in range (rows ):
@@ -1550,37 +1547,39 @@ def _normalize_data_cpu(data, min_val, max_val, pixel_max, contrast):
15501547 return out
15511548
15521549
1553- def _normalize_data_numpy (data , pixel_max , contrast ):
1550+ def _normalize_data_numpy (data , pixel_max , c , th ):
15541551 min_val = np .nanmin (data )
15551552 max_val = np .nanmax (data )
1556- out = _normalize_data_cpu (data , min_val , max_val , pixel_max , contrast )
1553+ out = _normalize_data_cpu (
1554+ data , min_val , max_val , pixel_max , c , th
1555+ )
15571556 return out
15581557
15591558
1560- def _normalize_data_dask (data , pixel_max , contrast ):
1559+ def _normalize_data_dask (data , pixel_max , c , th ):
15611560 min_val = da .nanmin (data )
15621561 max_val = da .nanmax (data )
15631562 out = da .map_blocks (
1564- _normalize_data_cpu , data , min_val , max_val , pixel_max , contrast ,
1565- meta = np .array (())
1563+ _normalize_data_cpu , data , min_val , max_val , pixel_max ,
1564+ c , th , meta = np .array (())
15661565 )
15671566 return out
15681567
15691568
1570- def _normalize_data_cupy (data , pixel_max , contrast ):
1569+ def _normalize_data_cupy (data , pixel_max , c , th ):
15711570 raise NotImplementedError ('Not Supported' )
15721571
15731572
1574- def _normalize_data_dask_cupy (data , pixel_max , contrast ):
1573+ def _normalize_data_dask_cupy (data , pixel_max , c , th ):
15751574 raise NotImplementedError ('Not Supported' )
15761575
15771576
1578- def _normalize_data (agg , pixel_max = 255.0 , contrast = 10 ):
1577+ def _normalize_data (agg , pixel_max , c , th ):
15791578 mapper = ArrayTypeFunctionMapping (numpy_func = _normalize_data_numpy ,
15801579 dask_func = _normalize_data_dask ,
15811580 cupy_func = _normalize_data_cupy ,
15821581 dask_cupy_func = _normalize_data_dask_cupy )
1583- out = mapper (agg )(agg .data , pixel_max , contrast )
1582+ out = mapper (agg )(agg .data , pixel_max , c , th )
15841583 return out
15851584
15861585
@@ -1611,45 +1610,50 @@ def _alpha(red, nodata=1):
16111610 return out
16121611
16131612
1614- def _true_color_numpy (r , g , b , nodata , contrast ):
1613+ def _true_color_numpy (r , g , b , nodata , c , th ):
16151614 a = np .where (np .logical_or (np .isnan (r ), r <= nodata ), 0 , 255 )
16161615
16171616 h , w = r .shape
16181617 out = np .zeros ((h , w , 4 ), dtype = np .uint8 )
16191618
16201619 pixel_max = 255
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 )
1620+ out [:, :, 0 ] = (_normalize_data (r , pixel_max , c , th )).astype (np .uint8 )
1621+ out [:, :, 1 ] = (_normalize_data (g , pixel_max , c , th )).astype (np .uint8 )
1622+ out [:, :, 2 ] = (_normalize_data (b , pixel_max , c , th )).astype (np .uint8 )
16241623 out [:, :, 3 ] = a .astype (np .uint8 )
16251624 return out
16261625
16271626
1628- def _true_color_dask (r , g , b , nodata , contrast ):
1627+ def _true_color_dask (r , g , b , nodata , c , th ):
16291628 pixel_max = 255
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 )
1629+ red = (_normalize_data (r , pixel_max , c , th )).astype (np .uint8 )
1630+ green = (_normalize_data (g , pixel_max , c , th )).astype (np .uint8 )
1631+ blue = (_normalize_data (b , pixel_max , c , th )).astype (np .uint8 )
16331632
16341633 alpha = _alpha (r , nodata ).astype (np .uint8 )
16351634
16361635 out = da .stack ([red , green , blue , alpha ], axis = - 1 )
16371636 return out
16381637
16391638
1640- def _true_color_cupy (r , g , b , nodata , contrast ):
1639+ def _true_color_cupy (r , g , b , nodata , c , th ):
16411640 raise NotImplementedError ('Not Supported' )
16421641
16431642
1644- def _true_color_dask_cupy (r , g , b , nodata , contrast ):
1643+ def _true_color_dask_cupy (r , g , b , nodata , c , th ):
16451644 raise NotImplementedError ('Not Supported' )
16461645
16471646
1648- def true_color (r , g , b , nodata = 1 , contrast = 10.0 , name = 'true_color' ):
1647+ def true_color (r , g , b , nodata = 1 , c = 10.0 , th = 0.125 , name = 'true_color' ):
16491648 """
16501649 Create true color composite from a combination of red, green and
16511650 blue bands satellite images.
16521651
1652+ A sigmoid function will be used to improve the contrast of output image.
1653+ The function is defined as:
1654+ ``normalized_pixel = 1 / (1 + np.exp(c * (th - normalized_pixel)))``
1655+ where ``c`` and ``th`` are contrast and brightness controlling parameters.
1656+
16531657 Parameters
16541658 ----------
16551659 r : xarray.DataArray
@@ -1660,8 +1664,10 @@ def true_color(r, g, b, nodata=1, contrast=10.0, name='true_color'):
16601664 2D array of blue band data.
16611665 nodata : int, float numeric value
16621666 Nodata value of input DataArrays.
1663- contrast : int, float numeric value
1664- Contrast controlling parameter for output image.
1667+ c : float, default=10
1668+ Contrast and brighness controlling parameter for output image.
1669+ th : float, default=0.125
1670+ Contrast and brighness controlling parameter for output image.
16651671 name : str, default='true_color'
16661672 Name of output DataArray.
16671673
@@ -1671,7 +1677,6 @@ def true_color(r, g, b, nodata=1, contrast=10.0, name='true_color'):
16711677 3D array true color image with dims of [y, x, band].
16721678 All output attributes are copied from red band image.
16731679
1674-
16751680 Examples
16761681 --------
16771682 .. plot::
@@ -1699,7 +1704,7 @@ def true_color(r, g, b, nodata=1, contrast=10.0, name='true_color'):
16991704 dask_cupy_func = _true_color_dask_cupy )
17001705 with warnings .catch_warnings ():
17011706 warnings .simplefilter ('ignore' )
1702- out = mapper (r )(r , g , b , nodata , contrast )
1707+ out = mapper (r )(r , g , b , nodata , c , th )
17031708
17041709 # TODO: output metadata: coords, dims, attrs
17051710 _dims = ['y' , 'x' , 'band' ]
0 commit comments