Image scaling
Uncomment the following line to install the latest version of geeagri if needed.
# !pip install -U geeagri
Import libraries¶
import ee
import geemap
from geeagri.preprocessing import (
MeanCentering,
StandardScaler,
MinMaxScaler,
RobustScaler,
)
Initialize a Map object¶
Authenticate and initialize Earth Engine. If it doesn't work, specify a project name
# ee.Authenticate()
# ee.Initialize(project='your-project-id')
Map = geemap.Map()
Map
Import region of interest¶
bbox = [-120.398369, 37.006574, -120.208168, 37.101924]
region = ee.Geometry.BBox(*bbox)
region_style = {"color": "red", "width": 1}
Map.addLayer(region, region_style, "Region")
Map.centerObject(region, 12)
Load Sentinel-2 data and create a median composite¶
image = (
ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED")
.filterBounds(region)
.filterDate("2024-01-01", "2025-01-01")
.filterMetadata("CLOUDY_PIXEL_PERCENTAGE", "less_than", 10)
.select(["B8", "B4", "B3"])
.median()
.multiply(0.0001)
.clip(region)
)
image_vis = {"bands": ["B8", "B4", "B3"], "min": 0, "max": 0.3}
Map.addLayer(image, image_vis, "Sentinel 2 FCC")
MeanCentering¶
Subtracts the mean from each band to center values around zero:
$$ X_\text{centered} = X - \mu $$
Where:
- $X$: original pixel value
- $\mu$: mean of the band computed over the given region
scaler = MeanCentering(image, region)
centered_image = scaler.transform()
# Adjust visualization range around 0 to reflect centered values
centered_image_vis = {"bands": ["B8", "B4", "B3"], "min": -0.09, "max": 0.09}
Map.addLayer(centered_image, centered_image_vis, "MeanCentering")
MinMaxScaler¶
Normalizes each band using the min and max values over the region:
$$ X_\text{scaled} = \frac{X - \min}{\max - \min}, \quad X_\text{scaled} \in [0, 1] $$
Where:
- $\min$, $\max$: band-wise minimum and maximum values over the region.
scaler = MinMaxScaler(image, region)
scaled_image = scaler.transform()
scaled_image_vis = {"bands": ["B8", "B4", "B3"], "min": 0, "max": 1}
Map.addLayer(scaled_image, scaled_image_vis, "MinMaxScaler")
StandardScaler¶
Standardizes each band using z-score normalization (mean and standard deviation):
$$ X_\text{standardized} = \frac{X - \mu}{\sigma} $$
Where:
- $X$: original pixel value
- $\mu$: mean of the band over the specified region
- $\sigma$: standard deviation of the band over the specified region
scaler = StandardScaler(image, region)
standardized_image = scaler.transform()
# You may want to visualize within a reasonable range
standardized_image_vis = {"bands": ["B8", "B4", "B3"], "min": -2, "max": 2}
Map.addLayer(standardized_image, standardized_image_vis, "StandardScaler")
RobustScaler¶
Scales each band using robust percentiles (e.g., 1st and 99th) to reduce the influence of outliers:
$$ X_\text{scaled} = \frac{X - P_\text{lower}}{P_\text{upper} - P_\text{lower}}, \quad X_\text{scaled} \in [0, 1] $$
Where:
- $X$: original pixel value
- $P_{\\text{lower}}$: lower percentile value (e.g., 25th percentile)
- $P_{\\text{upper}}$: upper percentile value (e.g., 75th percentile)
scaler = RobustScaler(image, region, lower=1, upper=99)
scaled_image = scaler.transform()
scaled_image_vis = {"bands": ["B8", "B4", "B3"], "min": 0, "max": 1}
Map.addLayer(scaled_image, scaled_image_vis, "RobustScaler")
💡 Tips for Efficient Processing
Increase the
scale
parameter to reduce computation time. Calculating statistics (e.g., mean, percentiles) over high-resolution images (like Sentinel-2 at 10 m) can be time-consuming or cause timeouts. Tryscale=100
or higher when possible.Use simpler geometries. Avoid complex shapes like administrative boundaries or large regions. Instead, use simplified or bounding box geometries.
You can simplify any geometry by converting it to a bounding rectangle using:
simple_region = complex_region.bounds()This can drastically speed up reduceRegion operations while still capturing spatial context.