One giant Multipolygon per class isn't going to scale very well, but it's not hard to produce that.
var geometry = ee.Geometry.Rectangle([29.1796875, 32.02670629333615, 32.607421875, 29.993002284551075]);
var landcover = ee.Image('MCD12Q1/MCD12Q1_005_2001_01_01').select('Land_Cover_Type_1');
// Run reduceToVectors per class by masking all other classes.
var classes = ee.List([0, 1, 2, 3, 4, 5, 6, 7, 8])
.map(function(n) {
var classImage = landcover.eq(ee.Number(n));
var vectors = classImage.updateMask(classImage)
.reduceToVectors({
reducer: ee.Reducer.countEvery(),
geometry: geometry,
scale: 30,
maxPixels: 1e8})
.geometry();
return ee.Feature(vectors, {"class": n});
});
var result = ee.FeatureCollection(classes);
Map.addLayer(result);
But you'd be better off with 1 feature per polygon. In both cases, each feature will have a "label" identifying the class.
var geometry = ee.Geometry.Rectangle([29.1796875, 32.02670629333615, 32.607421875, 29.993002284551075]);
var landcover = ee.Image('MCD12Q1/MCD12Q1_005_2001_01_01').select('Land_Cover_Type_1');
var classes = landcover.reduceToVectors({
reducer: ee.Reducer.countEvery(),
geometry: geometry,
scale: 30,
maxPixels: 1e8
});
var result = ee.FeatureCollection(classes);
Map.addLayer(result);
Here is an article by the Earth Engine team that does a little explaining on morphological operations within Earth Engine
Fo your case, you may be able to get away with using image.focal_mode()
(or some combination of morphological ops) for a straightforward clean up of your classes, the Earth Engine team provide a great example of how to do this for land cover image cleanup.
However, it sounds like you may want to do some more advanced neighborhood operations by using a filter weight. Here is an example of how you can use weights to clean up a land cover classification:
// Force projection of 500 meters/pixel, which is the native MODIS resolution.
var SCALE = 500;
// Load a 2001 MODIS land cover image and
// select the classification band of interest.
var lc = ee.Image('MODIS/051/MCD12Q1/2001_01_01')
.select(['Land_Cover_Type_1']);
// Smooth with a mode filter.
// and force operations to be done at native scale
var mode = lc.focal_mode().reproject('EPSG:4326', null, SCALE);
// Weighted smoothing
// using a 3x3 window
// euclidean distance weighting from corners
var weights = [[1,2,1],
[2,3,2],
[1,2,1]];
// create a 3x3 kernel with the weights
// kernel W and H must equal weight H and H
var kernel = ee.Kernel.fixed(3,3,weights);
// apply mode on neightborhood using weights
// and force operations to be done at native scale
var weighted_mode = lc.reduceNeighborhood({
reducer: ee.Reducer.mode(),
kernel: kernel
}).reproject('EPSG:4326', null, SCALE);
// Define display paramaters with appropriate colors for the MODIS
// land cover classification image.
var PALETTE = [
'aec3d4', // water
'152106', '225129', '369b47', '30eb5b', '387242', // forest
'6a2325', 'c3aa69', 'b76031', 'd9903d', '91af40', // shrub, grass, savannah
'111149', // wetlands
'cdb33b', // croplands
'cc0013', // urban
'33280d', // crop mosaic
'd7cdcc', // snow and ice
'f7e084', // barren
'6f6f6f' // tundra
].join(',');
var vis_params = {min: 0, max: 17, palette: PALETTE};
// Display each step of the computation.
Map.setCenter(-121.9122, 37.7299, 10);
Map.addLayer(lc, vis_params, 'IGBP classification');
Map.addLayer(mode, vis_params, 'Mode');
Map.addLayer(weighted_mode, vis_params, 'Weighted Mode')
As you can see, you just create a kernel using whichever weights you want as a list and then apply it on the image using .reduceNeighborhood()
. I hope this helps!
Best Answer
You're not doing anything wrong, it's just that S2 images have a lot of bands and taking the median() of them generates double valued pixels, so the tiles being passed back and forth between servers end up too large. When this occurs, you increase the tileScale, to tell the system to use smaller tiles.
See https://developers.google.com/earth-engine/debugging#scaling-errors for more information on tileScale.