0

I am trying to run this code and keep getting the error: "Classified objects: Layer error: Collection.geometry: Unable to perform this geometry operation. Please specify a non-zero error margin". I assume it's because I the composite I used has some masked elements but I am not sure. The pixel-based classification works but not the OBIA.

My code is below:


//Apply criteria
var images = collection.filterBounds(counties)
.filterDate('2022-04-01', '2022-09-15')
.filterMetadata('CLOUDY_PIXEL_PERCENTAGE','less_than', 5)
.sort("CLOUD_COVERAGE_ASSESSMENT")
.map(maskS2clouds)
.median()
.clip(counties);

//Add visual parameters to the map - bands: natural colors
var imageVisParam = {bands:['B4', 'B3', 'B2'], min:[0.10,0.10,0.10], max:[0.5,0.5,0.5]}
Map.addLayer(images,imageVisParam,'Counties_clip');

//Calculate the ndvi

var ndvi = images.expression(
   ' ((NIR - RED) / (NIR + RED))', {
     'NIR': images.select('B8'),
      'RED': images.select('B4'),
     
  }).rename('nd');

print(ndvi);

images = images.addBands(ndvi)
print(images)

//var ndvi = images.normalizedDifference(['B4', 'B8']).rename('NDVI')

//var threshndvi = ndvi.gte(-0.057).and(ndvi.lte(0.004))
var threshndvi = ndvi.gte(-0.057).and(ndvi.lte(0.1))
var ndviVis = {min:0,max:1,palette:['white','green']}
Map.addLayer(ndvi, ndviVis, "ndvi_treshold")

// Create a binary mask 
var mask = threshndvi.eq(1);

// Update the composite mask with the mask.
var maskedcomposite = images.updateMask(mask);
Map.addLayer(maskedcomposite, imageVisParam, "masked composite",true)

//Pixel-based classification

var SampleSize = 256 
// You can reset SampleSize to other number; 
// The max here should be 2500, since you have only two class and so each of them could be half of 5000

var landcover_labels = 'landcover'

//combination of feature collections
var combinedRoads = roads.merge(roads2).merge(roads3).merge(roads4);

var combinedGeometry = geometry.merge(polygons_DL)

var geometryCollection = combinedGeometry.limit(10);

var GeometryArea = ee.FeatureCollection.
                    randomPoints(geometryCollection, SampleSize).map(function(i){
  return i.set({'landcover': 1})})
  
var Nonfracking = ee.FeatureCollection.
                    randomPoints(nonfracking, SampleSize).map(function(i){
  return i.set({'landcover': 2})})

var RoadArea = ee.FeatureCollection.
                    randomPoints(combinedRoads, SampleSize).map(function(i){
  return i.set({'landcover': 3})})

// Train the feature collection containing my training sites (polygons)
var trainingpoints = GeometryArea.merge(RoadArea).merge(Nonfracking);

print(trainingpoints)

//var newfc = geometry.merge(nonfracking).merge(roads2)
  var bands = ['nd'];
    var training = maskedcomposite.select(bands).sampleRegions({
    collection: trainingpoints, 
    properties: ['landcover'], 
    scale: 20,
    geometries:true
    });
    
print(training,'training')

// Add a random column and split the GCPs into training and validation set
var gcp = training.randomColumn()
print(gcp,'gcp')

// We take the recommended ratio of 70% training, 30% validation
var trainingGcp = gcp.filter(ee.Filter.gt('random', 0.3));
var validationGcp = gcp.filter(ee.Filter.lte('random', 0.3));

var classifier = ee.Classifier.smileRandomForest(50).train(trainingGcp, landcover_labels, bands
  //features: trainingGcp, landcover_labels, bands
  //classProperty: 'landcover', 
  //inputProperties: bands
  );

var classified = maskedcomposite.select(bands).classify(classifier);

Map.addLayer(classified, 
{min: 0, max: 1, palette: ['#1e82ff', '#1c8b08', '#88ff72','#88ff72','#c2b2bc','#fbff2a','#008800']}, 
'classification');

//Object-based classification
var seeds = ee.Algorithms.Image.Segmentation.seedGrid(36);

print(maskedcomposite,'MC')

var snic = ee.Algorithms.Image.Segmentation.SNIC({
  image: images, 
  compactness: 0,
  connectivity: 8,
  neighborhoodSize: 64,
  size: 3,
  seeds: seeds
});

print(snic,"snic");

Map.addLayer(snic.randomVisualizer(),{}, 'snic');

var clusters_snic = snic.select("clusters");
Map.addLayer(clusters_snic.randomVisualizer(),{}, 'clusters_snic');
print(clusters_snic,"clusters_snic");

// Compute per-cluster stdDev.
var stdDev = images.addBands(clusters_snic).reduceConnectedComponents(ee.Reducer.stdDev(), 'clusters', 256)
Map.addLayer(stdDev, {min:0, max:0.1}, 'StdDev', false)

// Area, Perimeter, Width and Height
var area = ee.Image.pixelArea().addBands(clusters_snic).reduceConnectedComponents(ee.Reducer.sum(), 'clusters', 256)
Map.addLayer(area, {min:50000, max: 500000}, 'Cluster Area', false)

var minMax = clusters_snic.reduceNeighborhood(ee.Reducer.minMax(), ee.Kernel.square(1));
var perimeterPixels = minMax.select(0).neq(minMax.select(1)).rename('perimeter');
Map.addLayer(perimeterPixels, {min: 0, max: 1}, 'perimeterPixels');

var perimeter = perimeterPixels.addBands(clusters_snic)
    .reduceConnectedComponents(ee.Reducer.sum(), 'clusters', 256);
Map.addLayer(perimeter, {min: 100, max: 400}, 'Perimeter size', false);

var sizes = ee.Image.pixelLonLat().addBands(clusters_snic).reduceConnectedComponents(ee.Reducer.minMax(), 'clusters', 256)
var width = sizes.select('longitude_max').subtract(sizes.select('longitude_min')).rename('width')
var height = sizes.select('latitude_max').subtract(sizes.select('latitude_min')).rename('height')
Map.addLayer(width, {min:0, max:0.02}, 'Cluster width', false)
Map.addLayer(height, {min:0, max:0.02}, 'Cluster height', false)


var objectPropertiesImage = ee.Image.cat([
  snic.select('nd_mean'),
  stdDev,
  area,
  perimeter,
  width,
  height
]).float();

print(objectPropertiesImage, 'opi')

var training_obia = objectPropertiesImage.addBands(classified.select('landcover'))
    .updateMask(seeds)
    .sample(geometry, 5)
var classifier = ee.Classifier.smileRandomForest(10).train(training_obia, 'landcover')
Map.addLayer(objectPropertiesImage.classify(classifier), {min:0, max:254}, 'Classified objects')

1 Answer 1

0

Could you share a link to the full code ("Get Link" in the Code Editor)? The issue may be happening before the code pasted here, for example when the FeatureCollection is constructed; maxError is sometimes required depending on projection and geometries in the collection.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.