Mapeo de la cobertura terrestre con datos de GLOBE y representaciones satelitales#
Aplicaremos aprendizaje automático, específicamente clasificación supervisada, para mapear la cobertura terrestre mediante datos de GLOBE Land Cover y las representaciones satelitales de AlphaEarth.
# Descomenta la siguiente línea si necesitas instalar geemap
# !pip install -q geemap
import ee
import geemap
import geopandas as gpd
import pandas as pd
from IPython.display import display
# Autenticar Google Earth Engine
ee.Authenticate()
# Cambia "emerge-lessons" por el ID de tu proyecto si es diferente
ee.Initialize(project="emerge-lessons")
Primero, cargaremos y prepararemos los datos de GLOBE Land Cover. Para obtener más información sobre cómo cargar y preprocesar los datos, consulta esta lección de nuestro libro de análisis de datos de EMERGE.
gdf = gpd.read_file(
"https://github.com/geo-di-lab/emerge-lessons/"
"raw/refs/heads/main/docs/data/globe_land_cover.zip"
)
# Eliminar las filas que no tienen MucCode o geometría
gdf = gdf.dropna(subset=["MucCode", "geometry"])
Los datos de GLOBE Land Cover incluyen observaciones MUC, que representan categorías de cobertura terrestre con distintos niveles de detalle. Por ejemplo, un código MUC de 1 corresponde a Woodland, mientras que un código MUC de 11 corresponde a Mainly Evergreen Woodland.
Para este análisis nos concentraremos en el primer nivel, que incluye 10 categorías: bosque cerrado, bosque abierto, matorral o espesura, matorral enano o espesura enana, vegetación herbácea, terreno sin vegetación, humedal, aguas abiertas, terreno cultivado y zona urbana.
# Definir los códigos MUC únicos del primer nivel
muc_level1_map = {
"0": "Bosque cerrado",
"1": "Bosque abierto",
"2": "Matorral o espesura",
"3": "Matorral enano o espesura enana",
"4": "Vegetación herbácea",
"5": "Terreno sin vegetación",
"6": "Humedal",
"7": "Aguas abiertas",
"8": "Terreno cultivado",
"9": "Zona urbana"
}
# Definir los colores correspondientes a cada código MUC
custom_palette = [
"#004b23", # 0: Bosque cerrado
"#2d6a4f", # 1: Bosque abierto
"#52b788", # 2: Matorral
"#95d5b2", # 3: Matorral enano
"#d8f3dc", # 4: Vegetación herbácea
"#d4a373", # 5: Terreno sin vegetación
"#40E0D0", # 6: Humedal
"#1E90FF", # 7: Aguas abiertas
"#8B4513", # 8: Terreno cultivado
"#808080" # 9: Zona urbana
]
# Extraer el carácter correspondiente del MucCode para agrupar
# las observaciones en el nivel 1
gdf["Level1Code"] = gdf["MucCode"].astype(str).str[1]
gdf["label"] = gdf["Level1Code"].astype(int)
# Asignar las descripciones según el diccionario
gdf["MucDescription"] = gdf["Level1Code"].map(muc_level1_map)
# Convertir los datos en una FeatureCollection de Earth Engine
gdf_subset = gdf[
["label", "Level1Code", "MucDescription", "geometry"]
]
fc = geemap.geopandas_to_ee(gdf_subset)
A continuación, cargaremos las representaciones satelitales de AlphaEarth para nuestra región de estudio, Florida.
Estas representaciones satelitales condensan imágenes de satélite, datos de radar, modelos digitales de elevación y simulaciones climáticas en imágenes anuales disponibles públicamente. Cada área terrestre de 10 por 10 metros recibe una combinación única de números que permite distinguir sus características ambientales.
Al combinar estas representaciones con las observaciones de GLOBE, podemos aplicar aprendizaje automático para mapear la cobertura terrestre de una región utilizando datos recopilados en el mundo real.
# Definir la región de interés: Florida
fl = gpd.read_file(
"https://github.com/geo-di-lab/emerge-lessons/"
"raw/refs/heads/main/docs/data/florida_boundary.geojson"
)[["geometry"]]
region = geemap.gdf_to_ee(fl).geometry()
# Filtrar los datos de campo globales para conservar solamente
# las observaciones dentro de la región de Florida
local_fc = fc.filterBounds(region)
# Cargar las representaciones satelitales anuales V1 de AlphaEarth
embeddings = (
ee.ImageCollection("GOOGLE/SATELLITE_EMBEDDING/V1/ANNUAL")
.filterDate("2024-01-01", "2025-01-01")
.mosaic()
.clip(region)
)
A continuación, entrenaremos un modelo de bosque aleatorio con las representaciones satelitales y los datos de GLOBE.
Un bosque aleatorio es un modelo de aprendizaje automático que combina varios árboles de decisión para realizar clasificaciones y predicciones. Cada árbol procesa los datos mediante una serie de condiciones, similar a un diagrama de flujo con respuestas de sí o no. Al combinarse, los árboles pueden identificar patrones complejos en los datos.
En este caso, el modelo procesará las representaciones satelitales para decidir qué clasificación de cobertura terrestre corresponde a cada área de 10 por 10 metros.
# Obtener los datos de las representaciones satelitales
# correspondientes a cada punto
training_data = embeddings.sampleRegions(
collection=local_fc,
properties=["label", "Level1Code"],
scale=10,
tileScale=4
)
# Dividir los datos: 80 % para entrenamiento y 20 % para pruebas
withRandom = training_data.randomColumn("random")
split = 0.8
training = withRandom.filter(ee.Filter.lt("random", split))
testing = withRandom.filter(ee.Filter.gte("random", split))
# Entrenar un clasificador de bosque aleatorio con todas las bandas
# de las representaciones satelitales, 64 en total
band_names = embeddings.bandNames()
classifier = ee.Classifier.smileRandomForest(50).train(
features=training,
classProperty="label",
inputProperties=band_names
)
Aquí evaluaremos la exactitud de las clasificaciones de cobertura terrestre predichas por el modelo de bosque aleatorio.
validated = testing.classify(classifier)
confusion_matrix = validated.errorMatrix(
"label",
"classification"
)
print(
"Exactitud general: "
f"{confusion_matrix.accuracy().getInfo():.4f}"
)
Por último, mostraremos en un mapa los resultados predichos para toda la región de estudio.
classified_image = embeddings.classify(classifier)
# Crear dinámicamente el diccionario de la leyenda interactiva
legend_dict = {}
for code, desc in muc_level1_map.items():
legend_label = f"{code}: {desc}"
legend_dict[legend_label] = custom_palette[int(code)]
# Inicializar el mapa interactivo
Map = geemap.Map(
center=[28.473813, -81.660044],
zoom=9
)
# Agregar la capa de la imagen clasificada
# Los valores mínimo y máximo se alinean con la paleta de 10 colores
Map.addLayer(
classified_image,
{
"min": 0,
"max": 9,
"palette": custom_palette
},
"Cobertura terrestre predicha: nivel 1"
)
Map.addLayer(
local_fc,
{"color": "red"},
"Puntos de referencia de GLOBE"
)
# Agregar la leyenda flotante
Map.add_legend(
title="Cobertura terrestre: nivel 1",
legend_dict=legend_dict
)
# Mostrar el mapa
Map
from IPython.display import display, Image
# Definir los parámetros de visualización de la imagen clasificada
vis_params = {
"min": 0,
"max": 9,
"palette": custom_palette,
"region": region,
"dimensions": 800, # Ancho de la imagen en píxeles
"format": "png"
}
# Generar una URL directa para la imagen estática
# desde los servidores de Earth Engine
url = classified_image.getThumbURL(vis_params)
# Mostrar la imagen en Colab
display(Image(url=url))
