Las incorporaciones presentan una oportunidad única para encontrar ubicaciones y características similares con datos de observación de la Tierra. Si comparamos el vector de incorporación de una ubicación de referencia con los vectores de incorporación de todos los demás píxeles de una imagen de incorporación, podemos encontrar ubicaciones que exhiban propiedades similares a la ubicación de referencia. En la práctica, esto nos permite encontrar fácilmente objetos o tipos particulares de sitios en nuestra región de interés.
En este instructivo, intentaremos encontrar todos los silos de granos en una región. Los silos o depósitos de granos son estructuras altas que se usan comúnmente para el almacenamiento a granel de granos. Se encuentran en granjas o instalaciones de procesamiento. Asignar estas estructuras sería difícil con los métodos tradicionales de detección remota y requeriría entrenar un modelo personalizado de detección de objetos. Dado que los silos tienen una forma y estructura únicas, y suelen estar hechos de materiales similares, se representarán con vectores de incorporación únicos en las imágenes de Satellite Embedding, lo que nos permitirá ubicarlos con una simple búsqueda de similitud.
Silos de grano (imagen: Wikipedia)
Selecciona la región de búsqueda
En este instructivo, trazaremos los silos de granos del condado de Franklin, Kansas. Aplicamos un filtro y seleccionamos el polígono de este condado.
var counties = ee.FeatureCollection('TIGER/2018/Counties');
// Select Franklin County, Kansas
var selected = counties
.filter(ee.Filter.eq('GEOID', '20059'));
var geometry = selected.geometry();
Map.centerObject(geometry);
Map.addLayer(geometry, {color: 'red'}, 'Search Area');
Figura: Región seleccionada
Selecciona las ubicaciones de referencia
Comenzamos marcando la ubicación de uno o más silos de granos. En el editor de código, puedes usar el mapa base de satélite, que facilita la ubicación de objetos.
// Use the satellite basemap
Map.setOptions('SATELLITE');
Una vez que encuentres la ubicación del objeto de interés, usa la herramienta Agregar un marcador de Herramientas de dibujo para colocar un punto y marcarlo como ubicación de referencia.
Figura: Cómo agregar una ubicación de referencia
Incluso una sola ubicación suele ser suficiente, pero tener algunos ejemplos más ayuda a reducir los falsos positivos (en este caso, ubicaciones identificadas como silos de granos que en realidad no lo son). Cambiaremos el tipo de geometría a FeatureCollection para poder agregar varios puntos de referencia. Haz clic en el botón Editar propiedades de la capa junto a la geometría. Cambia el nombre de la capa a samples
y establece el tipo de importación como FeatureCollection
. Haz clic en Aceptar.
Figura: Configuración de la capa de muestras
De vuelta en la ventana principal del editor de código, agrega puntos en algunas ubicaciones más representativas.
Figura: Cómo agregar más ubicaciones de referencia
En este instructivo, seleccionamos 3 ubicaciones de referencia. Se usarán para extraer los vectores de incorporación de las imágenes de Satellite Embedding.
Selecciona un período
Elige un año para el que queremos ejecutar la búsqueda.
var year = 2024;
var startDate = ee.Date.fromYMD(year, 1, 1);
var endDate = startDate.advance(1, 'year');
Filtra y genera un mosaico del conjunto de datos de Satellite Embedding
Cargamos el conjunto de datos de Satellite Embedding, filtramos las imágenes del año elegido y creamos un mosaico.
var embeddings = ee.ImageCollection('GOOGLE/SATELLITE_EMBEDDING/V1/ANNUAL');
var mosaic = embeddings
.filter(ee.Filter.date(startDate, endDate))
.mosaic();
Extrae el vector de embedding de las muestras
Tomamos muestras del mosaico en las ubicaciones de referencia para obtener el vector de embedding asociado con estos puntos. También debemos seleccionar la escala en la que deseamos extraer y comparar el vector de incorporación. Una propiedad muy práctica de las incorporaciones en Satellite Embedding es que se diseñaron para ser linealmente componibles, lo que significa que se pueden agregar o piramidar y, al mismo tiempo, conservar las relaciones de distancia y el significado interpretado. Si tomamos un promedio espacial de píxeles de 2 x 2, el resultado representa la incorporación de un píxel más grande de menor resolución. La resolución nativa de Satellite Embedding es de 10 m, y será una buena escala para identificar objetos pequeños, como silos de granos. Sin embargo, si quieres encontrar objetos o sitios más grandes, puedes usar un valor mayor (es decir, 20 m, 1,000 m) para que coincidan con los objetos en escalas más gruesas.
// Choose the scale
// You may choose a larger value for larger objects
var scale = 10;
// Extract the embedding vector from the samples
var sampleEmbeddings = mosaic.sampleRegions({
collection: samples,
scale: scale
});
Cómo calcular la similitud
Calcular el producto escalar entre dos vectores de incorporación nos permite calcular su similitud. El producto escalar reduce la magnitud de dos vectores y el ángulo entre ellos a un solo número. En nuestro caso, los vectores de incorporación tienen una longitud unitaria, por lo que el resultado es solo el ángulo entre los vectores.
Podemos multiplicar dos vectores de incorporación de longitud unitaria y 64 D, y sumar los productos para obtener el coseno del ángulo entre los vectores (también conocido como "producto escalar"). Calculamos 1 imagen por ubicación de referencia y tomamos la media del resultado para obtener una imagen con valores de píxeles del producto escalar.
// We compute the dot product between two embedding vectors
var bandNames = mosaic.bandNames();
var sampleDistances = ee.ImageCollection(sampleEmbeddings.map(function (f) {
var arrayImage = ee.Image(f.toArray(bandNames)).arrayFlatten([bandNames]);
var dotProduct = arrayImage.multiply(mosaic)
.reduce('sum')
.rename('similarity');
return dotProduct;
}));
// Calculate mean distance from all reference locations
var meanDistance = sampleDistances.mean();
Los píxeles con un producto punto cercano a 1 tienen vectores de incorporación relativamente similares (ángulo entre ellos cercano a 0), mientras que los productos punto más cercanos a -1 indican una mayor divergencia entre los vectores (ortogonales a la dirección opuesta). Podemos visualizar los resultados agregando la imagen de la distancia media al mapa.
var palette = [
'000004', '2C105C', '711F81', 'B63679',
'EE605E', 'FDAE78', 'FCFDBF', 'FFFFFF'
];
var similarityVis = {palette: palette, min: 0, max: 1};
Map.addLayer(meanDistance.clip(geometry), similarityVis,
'Similarity (bright = close)', false);
Figura: Similitud de píxeles alrededor de un punto de referencia. Las áreas más brillantes son más similares
Extrae coincidencias de ubicación
En el siguiente paso, debemos definir un umbral y extraer las ubicaciones que contienen nuestro objeto objetivo. Todos los píxeles con silos de grano tendrán vectores de incorporación muy similares al vector de incorporación de referencia, y el ángulo entre ellos será cercano a 1. Definimos un umbral para encontrar todos esos píxeles dentro de la región. Encontrar el umbral adecuado dependerá del objeto que intentes encontrar y de la escala. Puedes experimentar con diferentes valores y ver cuál funciona mejor para tu aplicación.
// Apply a threshold
var threshold = 0.90;
var similarPixels = meanDistance.gt(threshold);
El resultado es una imagen binaria con píxeles que tienen valores de similitud inferiores al umbral. Ahora convertimos la imagen resultante en polígonos.
// Mask 0 values using selfMask()
// to get polygons only for the matched pixels
var polygons = similarPixels.selfMask().reduceToVectors({
scale: scale,
eightConnected: false,
maxPixels: 1e10,
geometry: geometry
});
Cada polígono representa un sitio que coincide con las ubicaciones de referencia. Podemos usar el centroide para representar la ubicación coincidente.
// Extract the centroids of vectorized polygons
var predictedMatches = polygons.map(function(f) {
return f.centroid({maxError:1});
});
Exporta coincidencias a un activo (opcional)
La vectorización es una operación que requiere mucha memoria y capacidad de procesamiento en Earth Engine. Para evitar los errores Computation Timed Out o Tile Error cuando visualices los resultados, es una buena práctica exportarlos como un recurso. Una vez que se exporta el recurso, se puede importar a la secuencia de comandos y visualizar. Este método también garantiza que puedas escalar la búsqueda en áreas grandes sin problemas.
// Replace this with your asset folder
// The folder must exist before exporting
var exportFolder = 'projects/spatialthoughts/assets/satellite_embedding/';
var matchesExportFc = 'predicted_grain_silo_matches';
var matchesExportFcPath = exportFolder + matchesExportFc;
Export.table.toAsset({
collection: predictedMatches,
description: 'Predicted_Matches_Export',
assetId: matchesExportFcPath
});
Inicia las tareas de exportación y espera a que finalicen antes de continuar. Una vez que finaliza la tarea de exportación, importamos las coincidencias de nuevo en nuestro código.
// Use the exported asset
var predictedMatches = ee.FeatureCollection(matchesExportFcPath);
Visualiza las coincidencias
Ya sea que hayas extraído las coincidencias de forma interactiva o las hayas exportado a una colección de entidades, ahora tendrás una variable predictedMatches
con las coincidencias predichas para las ubicaciones de referencia dentro del área de búsqueda. Visualicémoslos.
Map.addLayer(predictedMatches, {color: 'cyan'} , 'Predicted Matches');
Valida los resultados
Para evaluar los resultados, puedes acercar el mapa en cada coincidencia predicha y ver si hay un silo de granos en esa ubicación. Verás que hay muchas coincidencias que identificaron correctamente los silos de granos.
Figura: Sitios identificados correctamente con silos de granos
Los resultados también tienen algunos falsos positivos. Si observas, las coincidencias tienen muchas características similares a nuestra ubicación de referencia y, por lo tanto, tienen vectores de incorporación similares.
Figura: Coincidencias de falsos positivos
Para mejorar los resultados, puedes ajustar las ubicaciones de referencia y el umbral seleccionado.
Prueba la secuencia de comandos completa de este instructivo en el editor de código de Earth Engine.