Serviço Google Earth Engineoferece a oportunidade de trabalhar com grandes quantidades de informações espaciais gratuitamente. Por exemplo, em questão de minutos você pode obter um mosaico composto (imagem composta) de um milhão de imagens espaciais. Supondo que cada cena (conjunto de canais espectrais) do Landsat 8 ocupe 1 GB na forma compactada, esta solicitação processa um volume de informações de cerca de 1 PB. E tudo isso está disponível gratuitamente, de forma rápida e a qualquer momento. Mas existe uma opinião (errada) de que GEE em contas gratuitas permite processar e exportar apenas pequenos conjuntos de dados. Na verdade, essa impressão é causada apenas pelo fato de que você pode iniciar a programação em GEE sem nem mesmo ler a documentação do serviço, mas não será capaz de extrair muitos dados sem ler a documentação.A seguir, consideraremos três soluções diferentes para o problema de vetorizar rasters e, de duas maneiras diferentes, escreveremos uma função GEE do lado do servidor para calcular o geohash.

( , )? — ! , . ( — , , , - ), ( - , ). , . , , ( , , , - ). , . , — , , 128 , , , - . , ( , ), (, - Amazon AWS). . , , , . , , … , — , - , , ( ) , , ( - — , ). , , .
— Google Earth Engine. , — javascript (, , API ). . , , - . , , , , Google Drive ( ) (, GeoTIFF) Export.image.toDrive. , , , . — 21 10 Google Drive GeoJSON, 2. ( , ).
:
- , , :
var points_with_attributes = Image.reduceRegion({
reducer: ee.Reducer.toList(Image.bandNames().size()),
geometry: points
})
, , , . .
- , . :
var attributes = Image.reduceRegion({
reducer: ee.Reducer.toList(Image.bandNames().size()),
geometry: some_area
})
, . ? , . , . , ( , ). :
var latlon = ee.Image.pixelLonLat()
var points_with_attributes = image
.addBands(latlon)
.reduceRegion({
reducer: ee.Reducer.toList(),
geometry: some_area
});
ee.Image.pixelLonLat() , . , ( , GEE , , ). , , :
var latlon = ee.Image.pixelLonLat().reproject(image.projection())
var points_with_attributes = image
.addBands(latlon)
.reduceRegion({
reducer: ee.Reducer.toList(),
geometry: some_area
});
, :
var latlon = ee.Image.pixelLonLat()
var points_with_attributes = image
.addBands(latlon)
.add(image.select(0).add(0))
.reduceRegion({
reducer: ee.Reducer.toList(),
geometry: some_area
});
(, ), , . , , , ( ), . , () .
- , , , :
var latlon = ee.Image.pixelLonLat()
var points_with_attributes = image
.sample({
region: some_area,
geometries: true
});
"geometries" , .
, " ", - . , , GEE. , , . , ( ). GEE, , . , (z-curve). , , , GEE. ? , — . PostgreSQL/PostGIS, Google BigQuery . , -:
var geohash_accumulate = function(obj, list) {
// define common variables
var base32 = ee.String('0123456789bcdefghjkmnpqrstuvwxyz'); // (geohash-specific) Base32 map
// get previous state variables
var prev = ee.Dictionary(ee.List(list).get(-1));
var lat = ee.Number(prev.get('lat',0));
var lon = ee.Number(prev.get('lon',0));
var idx = ee.Number(prev.get('idx',0));
var bit = ee.Number(prev.get('bit',0));
var evenBit = ee.Number(prev.get('evenBit',1));
var geohash = ee.String(prev.get('geohash',''));
var latMin = ee.Number(prev.get('latMin',-90));
var latMax = ee.Number(prev.get('latMax',90));
var lonMin = ee.Number(prev.get('lonMin',-180));
var lonMax = ee.Number(prev.get('lonMax',180));
// calculate substep bit step idx
// bisect E-W longitude
var lonMid = ee.Number(ee.Algorithms.If(evenBit.gt(0), lonMin.add(lonMax).divide(2), 0) );
idx = ee.Number(ee.Algorithms.If(evenBit.gt(0).and(lon.gte(lonMid)), idx.multiply(2).add(1), idx) );
lonMin = ee.Number(ee.Algorithms.If(evenBit.gt(0).and(lon.gte(lonMid)), lonMid, lonMin) );
idx = ee.Number(ee.Algorithms.If(evenBit.gt(0).and(lon.lt(lonMid)), idx.multiply(2), idx) );
lonMax = ee.Number(ee.Algorithms.If(evenBit.gt(0).and(lon.lt(lonMid)), lonMid, lonMax) );
// bisect N-S latitude
var latMid= ee.Number(ee.Algorithms.If(evenBit.eq(0), latMin.add(latMax).divide(2), 0) );
idx = ee.Number(ee.Algorithms.If(evenBit.eq(0).and(lat.gte(latMid)), idx.multiply(2).add(1), idx) );
latMin = ee.Number(ee.Algorithms.If(evenBit.eq(0).and(lat.gte(latMid)), latMid, latMin) );
idx = ee.Number(ee.Algorithms.If(evenBit.eq(0).and(lat.lt(latMid)), idx.multiply(2), idx) );
latMax = ee.Number(ee.Algorithms.If(evenBit.eq(0).and(lat.lt(latMid)), latMid, latMax) );
// check position
evenBit = evenBit.not();
bit = bit.add(1);
geohash = ee.String(ee.Algorithms.If(bit.eq(5), geohash.cat(base32.slice(idx,ee.Number(idx).add(1))), geohash));
idx = ee.Number(ee.Algorithms.If(bit.eq(5), ee.Number(0), idx));
bit = ee.Number(ee.Algorithms.If(bit.eq(5), ee.Number(0), bit));
// return state
var curr = prev
.set('idx', idx )
.set('bit', bit )
.set('evenBit', evenBit)
.set('geohash', geohash)
.set('latMin', latMin )
.set('latMax', latMax )
.set('lonMin', lonMin )
.set('lonMax', lonMax );
return ee.List([curr]);
};
function geohash_encode(lat, lon, precision) {
var init = ee.Dictionary({lat: lat, lon: lon})
var state = ee.List.sequence(1,precision*5).iterate(geohash_accumulate, ee.List([init]))
return ee.String(ee.Dictionary(ee.List(state).get(-1)).get('geohash'))
}
// PostGIS check from https://postgis.net/docs/ST_GeoHash.html
print (ee.Algorithms.If(geohash_encode(48, -126, 20).compareTo('c0w3hf1s70w3hf1s70w3'),'Error','OK'));
// Google BigQuery check from https://cloud.google.com/bigquery/docs/reference/standard-sql/geography_functions#st_geohash
print (ee.Algorithms.If(geohash_encode(47.62, -122.35, 10).compareTo('c22yzugqw7'),'Error','OK'));
geohash_encode() geohash_accumulate() 5 . , GEE , . ? "calculate substep bit step idx" geohash_accumulate() ( , ). . , -, , , :
var geohash_accumulate = function(obj, list) {
// define common variables
var range4 = ee.List.sequence(0,4).map(function(val){return ee.Number(val).multiply(1/4)});
var range8 = ee.List.sequence(0,8).map(function(val){return ee.Number(val).multiply(1/8)});
// get previous state
var prev = ee.Dictionary(ee.List(list).get(-1))
var lat = ee.Number(prev.get('lat',0))
var lon = ee.Number(prev.get('lon',0))
var n = ee.Number(prev.get('n',0)).add(1)
var geohash = ee.String(prev.get('geohash',''))
var latMin = ee.Number(prev.get('latMin',-90))
var latMax = ee.Number(prev.get('latMax',90))
var lonMin = ee.Number(prev.get('lonMin',-180))
var lonMax = ee.Number(prev.get('lonMax',180))
// calculate step n
var base32 = ee.String(ee.Algorithms.If(n.mod(2).eq(1), '028b139c46df57eghksujmtvnqwyprxz', '0145hjnp2367kmqr89destwxbcfguvyz'));
var latRange = ee.List(ee.Number(ee.Algorithms.If(n.mod(2).eq(1), range4, range8)));
latRange = latRange.map(function(item){return ee.Number(item).multiply(latMax.subtract(latMin)).add(latMin)});
var lonRange = ee.List(ee.Number(ee.Algorithms.If(n.mod(2).eq(1), range8, range4)));
lonRange = lonRange.map(function(item){return ee.Number(item).multiply(lonMax.subtract(lonMin)).add(lonMin)});
var latIdx = latRange.indexOf(latRange.filter(ee.Filter.lte('item', lat)).get(-1));
latIdx = ee.Number(ee.Algorithms.If(latIdx.gte(latRange.size().add(-1)), latIdx.add(-1), latIdx));
var lonIdx = lonRange.indexOf(lonRange.filter(ee.Filter.lte('item', lon)).get(-1));
lonIdx = ee.Number(ee.Algorithms.If(lonIdx.gte(lonRange.size().add(-1)), lonIdx.add(-1), lonIdx));
var idx = lonIdx.multiply(latRange.size().add(-1)).add(latIdx);
// reset bounds
latMin = latRange.get(latIdx)
latMax = latRange.get(latIdx.add(1))
lonMin = lonRange.get(lonIdx)
lonMax= lonRange.get(lonIdx.add(1))
// define geohash symbol
var geohash = geohash.cat(base32.slice(idx,ee.Number(idx).add(1)));
// return state
var curr = prev
.set('n', n )
.set('geohash', geohash )
.set('latMin', latMin )
.set('latMax', latMax )
.set('lonMin', lonMin )
.set('lonMax', lonMax );
return ee.List([curr]);
};
function geohash_encode(lat, lon, precision) {
var init = ee.Dictionary({lat: lat, lon: lon})
var state = ee.List.sequence(1,precision).iterate(geohash_accumulate, ee.List([init]))
return ee.String(ee.Dictionary(ee.List(state).get(-1)).get('geohash'))
}
, , Javascript-, , .
. , , , . , GitHub ( GIS Snippets GEE). , — , .