嵌入提供了一个独特的机会,可使用地球观测数据查找相似的位置和特征。通过将参考位置的嵌入向量与嵌入图片的所有其他像素的嵌入向量进行比较,我们可以找到与参考位置具有相似属性的位置。在实践中,这使我们能够轻松找到感兴趣区域中的对象或特定类型的地点。
在本教程中,我们将尝试查找某个区域中的所有谷仓。谷物筒仓或谷物仓是通常用于批量存储谷物的高大结构。它们通常出现在农场或加工厂。使用传统的遥感方法很难绘制这些结构,并且需要训练自定义对象检测模型。由于筒仓具有独特的形状和结构,并且通常由相似的材料制成,因此在卫星嵌入图像中,它们将由独特的嵌入向量表示,从而使我们能够通过简单的相似度搜索来定位它们。
谷物筒仓(图片来源:维基百科)
选择搜索区域
在本教程中,我们将绘制堪萨斯州富兰克林县的谷仓地图。我们应用过滤条件,然后选择相应县的多边形。
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');
图:所选地区
选择参考位置
我们首先标记一个或多个谷仓的位置。在代码编辑器中,您可以使用卫星底图,以便轻松定位对象。
// Use the satellite basemap
Map.setOptions('SATELLITE');
找到感兴趣的对象的位置后,使用“绘图工具”中的“添加标记”工具放置一个点,将其标记为参考位置。
图:添加参考位置
即使只有一个位置,通常也足够了,但多提供几个示例有助于减少误报(在本例中,是指被识别为谷仓但实际上不是谷仓的位置)。我们将几何图形的类型更改为 FeatureCollection,以便添加多个参考点。点击几何图形旁边的修改图层属性按钮。将图层名称更改为 samples
,并将导入类型设置为 FeatureCollection
。点击“确定”。
图:配置样本层
返回到主代码编辑器窗口,在几个更具代表性的位置添加点。
图:添加更多参考位置
在本教程中,我们选择了 3 个参考位置。这些文件将用于从卫星嵌入图片中提取嵌入向量。
选择时间段
选择要运行搜索的年份。
var year = 2024;
var startDate = ee.Date.fromYMD(year, 1, 1);
var endDate = startDate.advance(1, 'year');
过滤和镶嵌卫星嵌入数据集
我们加载卫星嵌入数据集,过滤出所选年份的图片,并创建镶嵌图。
var embeddings = ee.ImageCollection('GOOGLE/SATELLITE_EMBEDDING/V1/ANNUAL');
var mosaic = embeddings
.filter(ee.Filter.date(startDate, endDate))
.mosaic();
从样本中提取嵌入向量
我们在参考位置对镶嵌图进行采样,以获得与这些点相关联的嵌入向量。我们还需要选择要提取和比较嵌入向量的规模。卫星嵌入的一项非常实用的属性是,它们被设计为可线性组合,这意味着它们可以聚合或分层,同时保留距离关系和可解释的含义。如果我们对 2x2 像素进行空间平均,结果表示较大低分辨率像素的嵌入。卫星嵌入的原始分辨率为 10 米,对于识别谷仓等小型物体,这是一个不错的比例。但如果您想寻找较大的物体或网站,则可以使用较大的值(即 20 米、1, 000 米)来匹配粗略比例下的对象。
// 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
});
计算相似度
通过计算两个嵌入向量之间的点积,我们可以计算出它们的相似度。点积会将两个向量的大小和它们之间的夹角缩减为一个数字,而在我们的示例中,嵌入向量是单位长度向量,因此结果只是向量之间的夹角。
我们只需将两个 64 维单位长度的嵌入向量相乘,然后将乘积相加,即可得到向量之间夹角的余弦值(也称为“点积”)。我们针对每个参考位置计算 1 张图片,并取结果的平均值,以获得像素值为点积的图片。
// 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();
点积接近 1 的像素具有相对相似的嵌入向量(它们之间的角度接近 0),而点积接近 -1 则表示向量之间的差异较大(正交于相反方向)。我们可以通过将平均距离图片添加到地图中来直观呈现结果。
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);
图:参考点周围像素的相似度 - 越亮的区域越相似
提取匹配的地点
在下一步中,我们需要定义一个阈值,并提取包含目标对象的位置。所有包含谷仓的像素的嵌入向量都将与参考嵌入向量非常相似,并且它们之间的角度将接近 1。我们定义了一个阈值,用于查找区域内的所有此类像素。合适的阈值取决于您要查找的对象和比例。您可以尝试不同的值,看看哪个值最适合您的应用。
// Apply a threshold
var threshold = 0.90;
var similarPixels = meanDistance.gt(threshold);
结果是像素相似度值小于阈值的二元图像。现在,我们将生成的图片转换为多边形。
// 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
});
每个多边形都代表一个与参考位置匹配的网站。我们可以使用形心来表示匹配的位置。
// Extract the centroids of vectorized polygons
var predictedMatches = polygons.map(function(f) {
return f.centroid({maxError:1});
});
将匹配项导出到媒体资源(可选)
矢量化是 Earth Engine 中一种内存和计算密集型操作。为避免在可视化结果时出现计算超时或图块错误,最好将结果导出为资源。导出素材资源后,您可以将其导入脚本并进行可视化处理。此方法还可确保您能够毫无问题地在较大区域内扩展搜索范围。
// 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
});
启动导出任务,并等待其完成,然后再继续操作。导出任务完成后,我们会将匹配项重新导入到代码中。
// Use the exported asset
var predictedMatches = ee.FeatureCollection(matchesExportFcPath);
直观呈现匹配结果
无论您是以交互方式提取匹配项,还是将其导出到要素集合,现在都会有一个 predictedMatches
变量,其中包含搜索区域内参考位置的预测匹配项。让我们直观地了解一下。
Map.addLayer(predictedMatches, {color: 'cyan'} , 'Predicted Matches');
验证结果
如需评估结果,您可以放大每个预测的匹配项,看看相应位置是否有谷仓。您会看到,许多匹配项都正确识别了谷仓。
图:正确识别出带有谷仓的网站
结果中也存在一些误报。如果您仔细观察,会发现匹配项与参考位置有许多相似的特征,因此具有相似的嵌入向量。
图:假正例匹配
为了改进结果,您可以调整参考位置和所选阈值。