Suivi de la santé des cultures à l’aide de l’indice de végétation amélioré

  • Produits utilisés : ls9_sr

Mots-clés données utilisées ; Landsat-9, index de bande ; EVI

Aperçu

L’indice de végétation amélioré <https://shorturl.at/oHRY9> peut être calculé à partir d’images Landsat ou Sentinel-2 et est similaire à l’indice de végétation par différence normalisée (NDVI), car il quantifie la verdure de la végétation. Cependant, l’EVI corrige certaines conditions atmosphériques et le bruit de fond de la canopée et est plus sensible dans les zones à végétation dense.

En utilisant les archives de données satellite prêtes à être analysées de Digital Earth Africa, nous pouvons facilement calculer l’EVI pour la cartographie et la surveillance de la végétation au fil du temps, ou comme entrées pour les algorithmes d’apprentissage automatique ou de classification.

Description

Ce cahier montre comment :

  1. Charger des images Landsat 9 pour une zone d’intérêt (AOI)

  2. Calculer l’indice de végétation amélioré (EVI)

  3. Visualisez les résultats.


Commencer

Pour exécuter cette analyse, exécutez toutes les cellules du bloc-notes, en commençant par la cellule « Charger les packages ».

Charger des paquets

[1]:
%matplotlib inline

import datacube
import xarray as xr
import geopandas as gpd
import matplotlib.pyplot as plt
from odc.geo.geom import Geometry

from deafrica_tools.datahandling import load_ard, mostcommon_crs
from deafrica_tools.plotting import rgb
from deafrica_tools.bandindices import calculate_indices
from deafrica_tools.areaofinterest import define_area

Se connecter au datacube

[2]:
dc = datacube.Datacube(app='crop_health_evi')

Paramètres d’analyse

La cellule suivante définit les paramètres qui définissent la zone d’intérêt et la durée de l’analyse. Les paramètres sont

  • « lat » : la latitude centrale à analyser (par exemple « 10,338 »).

  • « lon » : la longitude centrale à analyser (par exemple « -1,055 »).

  • « buffer » : le nombre de degrés carrés à charger autour de la latitude et de la longitude centrales. Pour des temps de chargement raisonnables, définissez cette valeur sur « 0,1 » ou moins.

Sélectionnez l’emplacement

Pour définir la zone d’intérêt, deux méthodes sont disponibles :

  1. En spécifiant la latitude, la longitude et la zone tampon. Cette méthode nécessite que vous saisissiez la latitude centrale, la longitude centrale et la valeur de la zone tampon en degrés carrés autour du point central que vous souhaitez analyser. Par exemple, « lat = 10,338 », « lon = -1,055 » et « buffer = 0,1 » sélectionneront une zone avec un rayon de 0,1 degré carré autour du point avec les coordonnées (10,338, -1,055).

    Vous pouvez également fournir des valeurs de tampon distinctes pour la latitude et la longitude d’une zone rectangulaire. Par exemple, « lat = 10.338 », « lon = -1.055 » et « lat_buffer = 0.1 » et « lon_buffer = 0.08 » sélectionneront une zone rectangulaire s’étendant sur 0,1 degré au nord et au sud et 0,08 degré à l’est et à l’ouest à partir du point « (10.338, -1.055) ».

    Pour des temps de chargement raisonnables, définissez la mémoire tampon sur « 0,1 » ou moins.

  2. By uploading a polygon as a GeoJSON or Esri Shapefile. If you choose this option, you will need to upload the geojson or ESRI shapefile into the Sandbox using Upload Files button 8f0a588a503e441aaceab1f32ce8db9e in the top left corner of the Jupyter Notebook interface. ESRI shapefiles must be uploaded with all the related files (.cpg, .dbf, .shp, .shx). Once uploaded, you can use the shapefile or geojson to define the area of interest. Remember to update the code to call the file you have uploaded.

Pour utiliser l’une de ces méthodes, vous pouvez décommenter la ligne de code concernée et commenter l’autre. Pour commenter une ligne, ajoutez le symbole "#" avant le code que vous souhaitez commenter. Par défaut, la première option qui définit l’emplacement à l’aide de la latitude, de la longitude et du tampon est utilisée.

Si vous exécutez le bloc-notes pour la première fois, conservez les paramètres par défaut ci-dessous. Cela permettra de démontrer le fonctionnement de l’analyse et de fournir des résultats significatifs.

[3]:
# Method 1: Specify the latitude, longitude, and buffer
aoi = define_area(lat=31.13907, lon=31.41094, buffer=0.02)

# Method 2: Use a polygon as a GeoJSON or Esri Shapefile.
# aoi = define_area(vector_path='aoi.shp')

#Create a geopolygon and geodataframe of the area of interest
geopolygon = Geometry(aoi["features"][0]["geometry"], crs="epsg:4326")
geopolygon_gdf = gpd.GeoDataFrame(geometry=[geopolygon], crs=geopolygon.crs)

# Get the latitude and longitude range of the geopolygon
lat_range = (geopolygon_gdf.total_bounds[1], geopolygon_gdf.total_bounds[3])
lon_range = (geopolygon_gdf.total_bounds[0], geopolygon_gdf.total_bounds[2])

Créer une requête et charger des données satellite

La fonction « load_ard » masquera automatiquement les nuages de l’ensemble de données, ce qui nous permettra de nous concentrer sur les pixels qui contiennent des données utiles. Elle exclura également les images où plus de 99 % des pixels sont masqués, ce qui est défini à l’aide du paramètre « min_gooddata » dans l’appel « load_ard ».

[4]:
# Create a reusable query
query = {
    'x': lon_range,
    'y': lat_range,
    'time': ('2022'),
    'resolution': (-10, 10)
}

# Identify the most common projection system in the input query
output_crs = mostcommon_crs(dc=dc, product='ls9_sr', query=query)

# Load available data from Landsat 9 and filter to retain only times
# with at least 99% good data
ds = load_ard(dc=dc,
              products=['ls9_sr'],
              min_gooddata=0.99,
              measurements=['red', 'green', 'blue', 'nir'],
              output_crs=output_crs,
              **query)
Using pixel quality parameters for USGS Collection 2
Finding datasets
    ls9_sr
Counting good quality pixels for each time step
Filtering to 30 out of 66 time steps with at least 99.0% good quality pixels
Applying pixel quality/cloud mask
Re-scaling Landsat C2 data
Loading 30 time steps
[5]:
display(ds)
<xarray.Dataset> Size: 84MB
Dimensions:      (time: 30, y: 450, x: 388)
Coordinates:
  * time         (time) datetime64[ns] 240B 2022-01-24T08:23:44.035758 ... 20...
  * y            (y) float64 4kB 3.448e+06 3.448e+06 ... 3.444e+06 3.444e+06
  * x            (x) float64 3kB 3.466e+05 3.466e+05 ... 3.504e+05 3.504e+05
    spatial_ref  int32 4B 32636
Data variables:
    red          (time, y, x) float32 21MB 0.0447 0.0447 ... 0.02567 0.04439
    green        (time, y, x) float32 21MB 0.04164 0.04164 ... 0.03636 0.05229
    blue         (time, y, x) float32 21MB 0.0263 0.0263 ... 0.02121 0.02619
    nir          (time, y, x) float32 21MB 0.1054 0.1054 ... 0.07621 0.2103
Attributes:
    crs:           epsg:32636
    grid_mapping:  spatial_ref

Tracez les images pour voir à quoi ressemble la zone

Nous utilisons la fonction « rgb » pour tracer les pas de temps dans notre ensemble de données sous forme d’images RVB en couleurs réelles.

[6]:
# Plot an RGB image
rgb(ds, index=[1, 10, 15, -1])
../../../_images/sandbox_notebooks_Real_world_examples_Crop_health_EVI_15_0.png

Calcul de l’indice EVI à l’aide de la fonction calculate_indices

L’indice de végétation amélioré nécessite les bandes rouge, nir et bleue ainsi qu’une valeur « L » pour ajuster le fond de la canopée, des valeurs « C » comme coefficients pour la résistance atmosphérique et un facteur de gain (G).

La formule est

\[\begin{split}\begin{aligned} \text{EVI} & = G \times \frac{(\text{NIR} - \text{Rouge})}{(\text{NIR} + C1 \times \text{Rouge} -C2 \times \text{Bleu} + L)} \\ \end{aligned}\end{split}\]

L’indice est disponible via la fonction calculate_indices, importée depuis deafrica_tools.bandindices. Ici, satellite_mission='ls' est utilisé puisque nous travaillons avec Landsat 9.

[7]:
# Calculate EVI using `calculate indices`
ds = calculate_indices(ds, index='EVI', satellite_mission='ls')

#The vegetation proxy index should now appear as a data variable,
#along with the loaded measurements, in the `ds` object.

# Plot the selected EVI results at timestep 1, 10, 15 and last image
ds.isel(time=[1, 10, 15, -1]).EVI.plot(col='time',
                                       cmap='RdYlGn',
                                       size=6,
                                       col_wrap=2)
[7]:
<xarray.plot.facetgrid.FacetGrid at 0x7f4cbacb9490>
../../../_images/sandbox_notebooks_Real_world_examples_Crop_health_EVI_17_1.png

Masquer la région avec la carte de l’étendue des terres cultivées de l’Afrique de l’Est

Chargez le masque de terres cultivées sur la région d’intérêt.

[8]:
cm = dc.load(product='crop_mask',
             time=('2019'),
             measurements='filtered',
             resampling='nearest',
             like=ds.geobox).filtered.squeeze()

#Filter out the no-data pixels (255) and non-crop pixels (0) from the cropland map
cm.where(cm < 255).plot.imshow(
    add_colorbar=False,
    figsize=(6, 6))  # we filter to <255 to omit missing data
plt.title('Cropland Extent');
../../../_images/sandbox_notebooks_Real_world_examples_Crop_health_EVI_19_0.png
[9]:
#mask only the cropland from the landsat 9 data.
ds = ds.where(cm == 1)
[10]:
# Plot the selected EVI results with crops only at timestep 1, 10, 15 and last image
ds.isel(time=[1, 10, 15, -1]).EVI.plot(cmap='RdYlGn',
                                       col='time',
                                       size=6,
                                       col_wrap=2)
[10]:
<xarray.plot.facetgrid.FacetGrid at 0x7f4ca8f95730>
../../../_images/sandbox_notebooks_Real_world_examples_Crop_health_EVI_21_1.png

Moyenne zonale de l’EVI

Pour comprendre les changements dans la santé de la végétation au cours des années, nous traçons une série chronologique zonale sur la région d’intérêt. Nous allons d’abord réaliser un graphique simple de la moyenne zonale des données.

Le graphique ci-dessous montre deux pics, suggérant que la zone d’intérêt est utilisée pour la double culture (culture de deux cultures par an).

[11]:
ds.EVI.mean(['x', 'y']).plot.line('g-*', figsize=(11, 4))
plt.title('Zonal mean of vegetation timeseries');
../../../_images/sandbox_notebooks_Real_world_examples_Crop_health_EVI_23_0.png

Tracez une image individuelle pour visualiser les variations spatiales de l’EVI

[12]:
ds.isel(time=8).EVI.plot(cmap='RdYlGn', size=6, col_wrap=2)
[12]:
<matplotlib.collections.QuadMesh at 0x7f4ca8288890>
../../../_images/sandbox_notebooks_Real_world_examples_Crop_health_EVI_25_1.png

Informations Complémentaires

Licence Le code de ce notebook est sous licence Apache, version 2.0 <https://www.apache.org/licenses/LICENSE-2.0>`__.

Les données de Digital Earth Africa sont sous licence Creative Commons Attribution 4.0 <https://creativecommons.org/licenses/by/4.0/>.

Contact Si vous avez besoin d’aide, veuillez poster une question sur le canal Slack DE Africa <https://digitalearthafrica.slack.com/> ou sur le GIS Stack Exchange <https://gis.stackexchange.com/questions/ask?tags=open-data-cube> en utilisant la balise open-data-cube (vous pouvez consulter les questions posées précédemment `ici <https://gis.stackexchange.com/questions/tagged/open-data-

Si vous souhaitez signaler un problème avec ce notebook, vous pouvez en déposer un sur Github.

Version de Datacube compatible

[13]:
print(datacube.__version__)
1.8.20

Dernier test :

[14]:
from datetime import date

print(date.today())
2025-01-16