Recherche de similarités avec l'ensemble de données d'embeddings satellite

Modifier sur GitHub
Signaler un problème
Historique des pages
Auteur(s) : spatialthoughts
Ce tutoriel fait partie d'une série de tutoriels sur l'ensemble de données Satellite Embedding. Consultez également Introduction, Classification non supervisée, Classification supervisée et Régression.

Les embeddings offrent une occasion unique de trouver des lieux et des caractéristiques similaires à l'aide de données d'observation de la Terre. En comparant le vecteur d'embedding d'un emplacement de référence avec les vecteurs d'embedding de tous les autres pixels d'une image d'embedding, nous pouvons trouver des emplacements qui présentent des propriétés similaires à celles de l'emplacement de référence. En pratique, cela nous permet de trouver facilement des objets ou des types de sites spécifiques dans notre région d'intérêt.

Pour ce tutoriel, nous allons essayer de trouver tous les silos à grains d'une région. Les silos ou les trémies à grains sont de grandes structures couramment utilisées pour le stockage en vrac des céréales. Elles se trouvent dans les fermes ou les usines de transformation. Il serait difficile de cartographier ces structures avec les méthodes de télédétection traditionnelles, et il faudrait entraîner un modèle de détection d'objets personnalisé. Comme les silos ont une forme et une structure uniques, et qu'ils sont généralement fabriqués à partir de matériaux similaires, ils seront représentés par des vecteurs d'embedding uniques dans les images Satellite Embedding, ce qui nous permettra de les localiser à l'aide d'une simple recherche de similarité.


Silos à grains (image : Wikipédia)

Sélectionnez la région de recherche.

Pour ce tutoriel, nous allons cartographier les silos à grains du comté de Franklin, au Kansas. Nous appliquons un filtre et sélectionnons le polygone correspondant à ce comté.

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');


Figure : Région sélectionnée

Sélectionnez une ou plusieurs zones géographiques de référence.

Nous commençons par marquer l'emplacement d'un ou de plusieurs silos à grains. Dans l'éditeur de code, vous pouvez utiliser le fond de carte satellite, qui permet de localiser facilement les objets.

// Use the satellite basemap
Map.setOptions('SATELLITE');

Une fois que vous avez trouvé l'emplacement de l'objet qui vous intéresse, utilisez l'outil "Ajouter un repère" des outils de dessin pour placer un point et le marquer comme emplacement de référence.


Figure : Ajouter un lieu de référence

Un seul emplacement suffit souvent, mais quelques exemples supplémentaires permettent de réduire les faux positifs (dans ce cas, les emplacements identifiés comme des silos à grains qui n'en sont pas). Nous allons modifier le type de géométrie pour qu'il devienne FeatureCollection afin de pouvoir ajouter plusieurs points de référence. Cliquez sur le bouton Modifier les propriétés du calque à côté de la géométrie. Renommez le calque en samples et définissez le type d'importation sur FeatureCollection. Cliquez sur OK.


Figure : Configuration du calque d'échantillons

De retour dans la fenêtre principale de l'éditeur de code, ajoutez des points à d'autres emplacements représentatifs.


Figure : Ajouter d'autres lieux de référence

Pour ce tutoriel, nous avons sélectionné trois emplacements de référence. Ils seront utilisés pour extraire les vecteurs d'embedding des images Satellite Embedding.

Sélectionner une période

Sélectionnez l'année pour laquelle vous souhaitez effectuer la recherche.

var year = 2024;
var startDate = ee.Date.fromYMD(year, 1, 1);
var endDate = startDate.advance(1, 'year');

Filtrer et mosaïquer l'ensemble de données Satellite Embedding

Nous chargeons l'ensemble de données Satellite Embedding, filtrons les images pour l'année choisie et créons une mosaïque.

var embeddings = ee.ImageCollection('GOOGLE/SATELLITE_EMBEDDING/V1/ANNUAL');

var mosaic = embeddings
  .filter(ee.Filter.date(startDate, endDate))
  .mosaic();

Extraire le vecteur d'embedding des échantillons

Nous échantillonnons la mosaïque aux emplacements de référence pour obtenir le vecteur d'embedding associé à ces points. Nous devons également sélectionner l'échelle à laquelle nous souhaitons extraire et comparer le vecteur d'intégration. Une propriété très pratique des embeddings dans Satellite Embedding est qu'ils ont été conçus pour être composables de manière linéaire, ce qui signifie qu'ils peuvent être agrégés ou mis en pyramide tout en conservant les relations de distance et la signification interprétée. Si nous prenons une moyenne spatiale sur 2x2 pixels, le résultat représente l'embedding d'un pixel plus grand et de résolution inférieure. La résolution native pour l'intégration de satellites est de 10 m. C'est une bonne échelle à utiliser pour identifier de petits objets comme des silos à grains. Toutefois, si vous souhaitez trouver des objets ou des sites plus grands, vous pouvez utiliser une valeur plus élevée (par exemple, 20 m, 1 000 m) pour faire correspondre les objets à des échelles plus grossières.

// 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
});

Calculer la similarité

Le calcul du produit scalaire entre deux vecteurs de représentation vectorielle nous permet de calculer leur similarité. Le produit scalaire réduit la magnitude de deux vecteurs et l'angle entre eux à un seul nombre. Dans notre cas, les vecteurs de représentation vectorielle continue sont de longueur unitaire. Le résultat n'est donc que l'angle entre les vecteurs.

Il suffit de multiplier deux vecteurs d'intégration de longueur unitaire 64D et de faire la somme des produits pour obtenir le cosinus de l'angle entre les vecteurs (également appelé "produit scalaire"). Nous calculons une image par emplacement de référence et prenons la moyenne du résultat pour obtenir une image avec des valeurs de pixels du produit scalaire.

// 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();

Les pixels dont le produit scalaire est proche de 1 ont des vecteurs d'intégration relativement similaires (angle entre eux proche de 0), tandis que les produits scalaires plus proches de -1 indiquent une plus grande divergence entre les vecteurs (orthogonaux à la direction opposée). Nous pouvons visualiser les résultats en ajoutant l'image de la distance moyenne à la carte.

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);


Figure : similitude des pixels autour d'un point de référence (les zones plus claires sont plus similaires)

Extraire les correspondances de lieux

Pour la prochaine étape, nous devons définir un seuil et extraire les emplacements contenant notre objet cible. Tous les pixels contenant des silos à grains auront des vecteurs de représentation très semblables au vecteur de représentation de référence, et l'angle entre eux sera proche de 1. Nous définissons un seuil pour trouver tous les pixels de ce type dans la région. Le seuil approprié dépend de l'objet que vous essayez de trouver et de l'échelle. Vous pouvez tester différentes valeurs et voir celle qui convient le mieux à votre application.

// Apply a threshold
var threshold = 0.90;
var similarPixels = meanDistance.gt(threshold);

Le résultat est une image binaire avec des pixels dont les valeurs de similarité sont inférieures au seuil. Nous convertissons désormais l'image obtenue en polygones.

// 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
});

Chaque polygone représente un site correspondant aux emplacements de référence. Nous pouvons utiliser le centroïde pour représenter le lieu correspondant.

// Extract the centroids of vectorized polygons
var predictedMatches = polygons.map(function(f) {
  return f.centroid({maxError:1});
});

Exporter les correspondances vers un élément (facultatif)

La vectorisation est une opération gourmande en mémoire et en calcul dans Earth Engine. Pour éviter les erreurs Computation Timed Out ou Tile Error lors de la visualisation des résultats, il est conseillé d'exporter les résultats en tant qu'élément. Une fois le composant exporté, il peut être importé dans le script et visualisé. Cette méthode vous permet également de faire évoluer la recherche sur de grandes zones sans problème.

// 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
});

Lancez les tâches d'exportation et attendez qu'elles soient terminées avant de continuer. Une fois la tâche d'exportation terminée, nous réimportons les correspondances dans notre code.

// Use the exported asset
var predictedMatches = ee.FeatureCollection(matchesExportFcPath);

Visualiser les correspondances

Que vous ayez extrait les correspondances de manière interactive ou que vous les ayez exportées vers une collection d'entités, vous disposez désormais d'une variable predictedMatches contenant les correspondances prédites avec les lieux de référence dans la zone de recherche. Visualisons-les.

Map.addLayer(predictedMatches, {color: 'cyan'} , 'Predicted Matches');

Valider les résultats

Pour évaluer les résultats, vous pouvez faire un zoom avant sur chaque correspondance prédite pour voir s'il y a un silo à grains à cet endroit. Vous verrez que de nombreuses correspondances ont correctement identifié des silos à grains.


Figure : Sites avec silos à grains correctement identifiés

Les résultats comportent également des faux positifs. Si vous l'on observe les correspondances, on constate qu'elles présentent de nombreuses caractéristiques similaires à notre emplacement de référence et qu'elles ont donc des vecteurs d'intégration similaires.


Figure : Faux positifs

Pour améliorer les résultats, vous pouvez ajuster les lieux de référence et le seuil sélectionné.

Essayez le script complet de ce tutoriel dans l'éditeur de code Earth Engine.