GEE - Inspector and rendered classification disagree at max zoom — OBIA pipeline
I’m running an OBIA classification pipeline in GEE using SNIC segmentation and Random Forest. The problem:
At maximum zoom level, the rendered classification map in GEE shows different results than the Inspector tool reports for the same pixel locations. When I export the classification as GeoTIFF for QGIS, the exported image matches the wrong rendered map, not the Inspector values.
What I’ve tried:
* reproject({crs: 'EPSG:32734', scale: 0.5}) on features before classification
* reproject() on the classification output
* Adding projection: 'EPSG:32734' to sampleRegions — this fixed training sample extraction but not the rendering
How do I make the rendered/exported classification match what the Inspector reads? Is this a known issue with reduceConnectedComponents?
Best,
Ted
// ── LOAD ASSETS ──
var ms = ee.Image('projects/masters-thesis-496612/assets/26JUL13084732-M3DS-050587773010_01_P001');
var pan = ee.Image('projects/masters-thesis-496612/assets/26JUL13084732-P3DS-050587773010_01_P001');
var aoi = ee.FeatureCollection('projects/masters-thesis-496612/assets/AOI');
var aa_possible_terms = ee.FeatureCollection('projects/masters-thesis-496612/assets/aa_possible_terms');
var training_possible_terms = ee.FeatureCollection('projects/masters-thesis-496612/assets/training_possible_terms');
// ── PANSHARPENING ──
var ms_resampled = ms.resample('bilinear').reproject({crs: pan.projection()});
var ms_mean = ms_resampled.reduce(ee.Reducer.mean());
var ratio = pan.divide(ms_mean);
var pansharpened = ms_resampled.multiply(ratio);
pansharpened = pansharpened.rename(['b1','b2','b3','b4','b5','b6','b7','b8']);
// ── TRAINING POINTS ──
var nonMoundsLabelled = ee.FeatureCollection(non_mounds.geometries().map(function(geom) {
return ee.Feature(ee.Geometry(geom), {'class_id': 0});
}));
var allTraining = training_possible_terms.merge(nonMoundsLabelled);
// ── SEGMENTATION ──
var snic = ee.Algorithms.Image.Segmentation.SNIC({
image: pansharpened, size: 30, compactness: 0.1, connectivity: 8, neighborhoodSize: 2
});
var clusters = snic.select('clusters');
var edges = clusters.subtract(clusters.focal_min(1)).abs().gt(0);
// ── FEATURE EXTRACTION ──
var meanBands = pansharpened.addBands(clusters).reduceConnectedComponents({
reducer: ee.Reducer.mean(), labelBand: 'clusters'
});
var brightness = pansharpened.reduce(ee.Reducer.mean()).rename('brightness');
var bsi = pansharpened.expression(
'((b6 + b5) - (b8 + b2)) / ((b6 + b5) + (b8 + b2))',
{b2: pansharpened.select('b2'), b5: pansharpened.select('b5'),
b6: pansharpened.select('b6'), b8: pansharpened.select('b8')}
).rename('BSI');
var indices = brightness.addBands(bsi).addBands(clusters).reduceConnectedComponents({
reducer: ee.Reducer.mean(), labelBand: 'clusters'
});
var features = meanBands.addBands(indices);
// ── CLASSIFICATION ──
var trainingSamples = features.sampleRegions({
collection: allTraining, properties: ['class_id'], scale: 0.5, projection: 'EPSG:32734'
});
var rf = ee.Classifier.smileRandomForest(100).train({
features: trainingSamples, classProperty: 'class_id', inputProperties: features.bandNames()
});
var svm = ee.Classifier.libsvm().train({
features: trainingSamples, classProperty: 'class_id', inputProperties: features.bandNames()
});
var rfClassification = features.classify(rf);
var svmClassification = features.classify(svm);
// ── VISUALIZE ──
Map.setOptions('HYBRID');
Map.centerObject(aoi, 15);
Map.addLayer(pansharpened, {min: 0, max: 2000, bands: ['b5', 'b3', 'b2']}, 'Pansharpened');
Map.addLayer(edges.updateMask(edges), {palette: ['ff0000']}, 'Segments');
Map.addLayer(rfClassification.eq(1).selfMask(), {palette: ['ff0000']}, 'RF Mounds');
Map.addLayer(svmClassification.eq(1).selfMask(), {palette: ['0000ff']}, 'SVM Mounds');
Map.addLayer(training_possible_terms, {color: 'cyan'}, 'termitaries training');
print('Training points:');
print(allTraining.size());
print('RF trained!');
print('SVM trained!');
// ── LOAD ASSETS ──
var aoi = ee.FeatureCollection(
'projects/masters-thesis-496612/assets/AOI'
);
var aa_possible_terms = ee.FeatureCollection(
'projects/masters-thesis-496612/assets/aa_possible_terms'
);
// ── VISUALIZE ──
Map.setOptions('HYBRID');
// AOI
Map.addLayer(
aoi,
{color: 'yellow'},
'AOI'
);
// Possible terms
Map.addLayer(
aa_possible_terms,
{color: 'red'},
'aa_possible_terms'
);
//export
var non_mounds_fc = ee.FeatureCollection(non_mounds.coordinates().map(function(coord) {
return ee.Feature(ee.Geometry.Point(coord), {class_id: 0});
}));
Export.table.toDrive({
collection: non_mounds_fc,
description: 'non_mounds_round1',
folder: 'termite_thesis',
fileFormat: 'SHP'
});
Export.image.toDrive({
image: rfClassification,
description: 'rf_classification_round1_small',
folder: 'termite_thesis',
scale: 0.5,
crs: 'EPSG:32734',
region: training_area,
maxPixels: 1e13
});
Export.image.toDrive({
image: svmClassification,
description: 'svm_classification_round1_small',
folder: 'termite_thesis',
scale: 0.5,
crs: 'EPSG:32734',
region: training_area,
maxPixels: 1e13
});
gis.stackexchange.com