GoogleEarthエンジンサービス膨大な量の空間情報を無料で扱う機会を提供します。たとえば、ほんの数分で、100万枚の宇宙画像の合成モザイク(合成画像)を取得できます。 Landsat 8の各シーン(スペクトルチャネルのセット)が圧縮形式で1 GBを占めると仮定すると、この要求は約1PBの情報量を処理します。そして、これらすべてが無料で、迅速に、そしていつでも利用できます。しかし、無料アカウントのGEEでは、小さなデータセットのみを処理およびエクスポートできるという意見(間違った意見)があります。実際、この印象は、サービスのドキュメントを読まなくてもGEEでプログラミングを開始できるという事実によってのみ引き起こされますが、ドキュメントを読まないと大量のデータを抽出することはできません。次に、ラスターのベクトル化の問題に対する3つの異なる解決策を検討し、2つの異なる方法で、ジオハッシュを計算するサーバー側のGEE関数を記述します。
( , )? — ! , . ( — , , , - ), ( - , ). , . , , ( , , , - ). , . , — , , 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). , — , .