Pesquisa por similaridade com o conjunto de dados de embeddings de satélite

Editar no GitHub
Informar problema
Histórico da página
Este tutorial faz parte de uma série sobre o conjunto de dados de incorporação de satélite. Consulte também Introdução, Classificação não supervisionada, Classificação supervisionada e Regressão.

Os embeddings oferecem uma oportunidade única de encontrar locais e recursos semelhantes usando dados de observação da Terra. Ao comparar o vetor de incorporação de um local de referência com os vetores de incorporação de todos os outros pixels de uma imagem de incorporação, podemos encontrar locais que exibem propriedades semelhantes ao local de referência. Na prática, isso nos permite encontrar facilmente objetos ou tipos específicos de sites na nossa região de interesse.

Neste tutorial, vamos tentar encontrar todos os silos de grãos em uma região. Silos ou depósitos de grãos são estruturas altas usadas para armazenamento a granel de grãos. Eles são encontrados em fazendas ou instalações de processamento. Mapear essas estruturas seria difícil com métodos tradicionais de sensoriamento remoto e exigiria o treinamento de um modelo personalizado de detecção de objetos. Como os silos têm um formato e uma estrutura únicos e geralmente são feitos de materiais semelhantes, eles são representados com vetores de embedding exclusivos nas imagens de embedding de satélite, o que permite localizá-los com uma simples pesquisa de similaridade.


Silos de grãos (imagem: Wikipedia)

Selecione a região de pesquisa

Neste tutorial, vamos mapear os silos de grãos no condado de Franklin, Kansas. Aplicamos um filtro e selecionamos o polígono desse município.

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ão selecionada

Selecionar locais de referência

Começamos marcando a localização de um ou mais silos de grãos. No editor de código, você pode usar o mapa de base de satélite, que facilita a localização de objetos.

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

Depois de encontrar o local do objeto de interesse, use a ferramenta "Adicionar um marcador" das Ferramentas de desenho para inserir um ponto e marcá-lo como um local de referência.


Figura: adicionar um local de referência

Mesmo um único local costuma ser suficiente, mas ter mais alguns exemplos ajuda a reduzir falsos positivos (neste caso, locais identificados como silos de grãos que não são silos de grãos). Vamos mudar o tipo de geometria para FeatureCollection para adicionar vários pontos de referência. Clique no botão Editar propriedades da camada ao lado da geometria. Mude o nome da camada para samples e defina o tipo de importação como FeatureCollection. Clique em OK.


Figura: configuração da camada de amostras

De volta à janela principal do Editor de código, adicione pontos em mais alguns locais representativos.


Figura: adicionar mais locais de referência

Para este tutorial, selecionamos três locais de referência. Eles serão usados para extrair os vetores de embedding das imagens de embedding de satélite.

Selecione um período

Escolha um ano para fazer a pesquisa.

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

Filtrar e criar mosaicos no conjunto de dados de incorporação de satélite

Carregamos o conjunto de dados de incorporação de satélite, filtramos as imagens do ano escolhido e criamos um mosaico.

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

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

Extrair o vetor de embedding das amostras

Fazemos uma amostragem do mosaico nos locais de referência para receber o vetor de incorporação associado a esses pontos. Também precisamos selecionar a escala em que queremos extrair e comparar o vetor de embedding. Uma propriedade muito prática dos embeddings no Satellite Embedding é que eles foram projetados para serem linearmente combináveis. Isso significa que podem ser agregados ou piramidados, mantendo as relações de distância e o significado interpretado. Se pegarmos uma média espacial de pixels 2x2, o resultado vai representar a incorporação de um pixel maior de resolução mais baixa. A resolução nativa para incorporação de satélite é de 10 m. Para identificar objetos pequenos, como silos de grãos, essa é uma boa escala para usar. Mas se você quiser encontrar objetos ou sites maiores, use um valor maior (por exemplo, 20 m, 1.000 m) para corresponder a objetos em escalas mais grosseiras.

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

Calcular a similaridade

Ao calcular o produto escalar entre dois vetores de embedding, podemos calcular a semelhança deles. O produto escalar reduz a magnitude de dois vetores e o ângulo entre eles a um único número. No nosso caso, os vetores de embedding têm comprimento unitário, e o resultado é apenas o ângulo entre os vetores.

Basta multiplicar dois vetores de embedding de comprimento unitário 64D e somar os produtos para obter o cosseno do ângulo entre os vetores (também conhecido como "produto escalar"). Calculamos uma imagem por local de referência e fazemos a média do resultado para gerar uma imagem com valores de pixels do produto 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();

Pixels com um produto escalar próximo de 1 têm vetores de incorporação relativamente semelhantes (ângulo entre eles próximo de 0), enquanto produtos escalares mais próximos de -1 indicam uma divergência maior entre vetores (ortogonais à direção oposta). Podemos visualizar os resultados adicionando a imagem da distância média ao 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: semelhança de pixels ao redor de um ponto de referência. As áreas mais claras são mais semelhantes.

Extrair correspondências de local

Na próxima etapa, vamos definir um limite e extrair os locais que contêm o objeto de destino. Todos os pixels com silos de grãos terão vetores de embedding muito semelhantes ao vetor de embedding de referência, e o ângulo entre eles será próximo de 1. Definimos um limite para encontrar todos esses pixels na região. Encontrar o limite certo depende do objeto e da escala. Teste diferentes valores para ver qual funciona melhor para seu aplicativo.

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

O resultado é uma imagem binária com pixels com valores de similaridade menores que o limite. Agora convertemos a imagem resultante em 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 um site com uma correspondência aos locais de referência. Podemos usar o centroide para representar o local correspondente.

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

Exportar correspondências para um recurso (opcional)

A vetorização é uma operação que consome muita memória e computação no Earth Engine. Para evitar Tempo limite de computação excedido ou Erro de bloco ao visualizar os resultados, é recomendável exportar os resultados como um recurso. Depois que o recurso é exportado, ele pode ser importado para o script e visualizado. Esse método também garante que você possa dimensionar a pesquisa em grandes áreas sem 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
});

Inicie as tarefas de exportação e aguarde a conclusão antes de continuar. Quando a tarefa de exportação for concluída, vamos importar as correspondências de volta para nosso código.

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

Visualizar as correspondências

Se você extraiu as correspondências de forma interativa ou exportou para uma coleção de recursos, agora terá uma variável predictedMatches com as correspondências previstas para os locais de referência na área de pesquisa. Vamos visualizar esses dados.

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

validar os resultados

Para avaliar os resultados, aumente o zoom em cada correspondência prevista para ver se há um silo de grãos nesse local. Você vai notar que há muitas correspondências que identificaram corretamente os silos de grãos.


Figura: sites identificados corretamente com silos de grãos

Os resultados também têm alguns falsos positivos. Se você observar, as correspondências têm muitas características semelhantes ao nosso local de referência e, portanto, têm vetores de incorporação semelhantes.


Figura: correspondências de falsos positivos

Para melhorar os resultados, ajuste os locais de referência e o limite selecionado.

Teste o script completo deste tutorial no editor de código do Earth Engine.