2

I have made a basic unsupervised k-means clusterer function in Earth Engine that creates two classes, which is what I want. While the function does apply consistent labels when run multiple times the labels are not consistent between images, i.e. sometimes clusters based on lower values are labeled 1, and sometimes they are labeled 0 (can be seen in code below, where features are black in one image and white in another). I need to run the clusterer on each image in the collection.

Is there any way to force the naming structure for the result to be linked to the image value it is based on? I know that sounds a lot like supervised classification, but I want to be able to run this without input training data and come out with the same naming scheme in each image.

Link to sample code

Reproduced here:

var input = ee.ImageCollection('COPERNICUS/S1_GRD')
 .filterBounds(geometry)
 .filterDate('2015-10-01', '2016-05-10')
 .filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'HV'))
 ;

var cluster= function(img){
  var training = img.select('HH').sample({region: trainer, scale:10, numPixels:1000});
  var clusterer = ee.Clusterer.wekaKMeans(2).train(training);
  var result = img.cluster(clusterer, 'kMean');
  return result;
};

var clustered= input.map(cluster);
var clust = clustered.toBands();
print(clust)

Map.addLayer(clust, {bands: ['S1A_EW_GRDM_1SDH_20151024T120105_20151024T120209_008294_00BB14_F72B_kMean'], min:0, max:1}, 'One scheme')
Map.addLayer(clust, {bands: ['S1A_EW_GRDM_1SDH_20151216T120911_20151216T121016_009067_00D054_ADF1_kMean'], min:0, max:1}, 'Other scheme')
1

You are training a new ee.Clusterer for each image, which is likely to produce different results because each image's sample will have a different distribution. Try training a ee.Clusterer on a single image that has a representative distribution and then apply it to all the other images.

For instance, here I've just selected the first image in the collection to train the ee.Clusterer, which gets called in the cluster function and is applied to each image.

var training = input.first().select('HH').sample({region: trainer, scale:10, numPixels:1000});
var clusterer = ee.Clusterer.wekaKMeans(2).train(training);

var cluster= function(img){
  var result = img.cluster(clusterer, 'kMean');
  return result;
};

var clustered= input.map(cluster);
var clust = clustered.toBands();
print(clust)

Map.addLayer(clust, {bands: ['S1A_EW_GRDM_1SDH_20151024T120105_20151024T120209_008294_00BB14_F72B_kMean'], min:0, max:1}, 'One scheme')
Map.addLayer(clust, {bands: ['S1A_EW_GRDM_1SDH_20151216T120911_20151216T121016_009067_00D054_ADF1_kMean'], min:0, max:1}, 'Other scheme')
1
  • Thanks for the update, but I need to have the training done in each image because of the sensor quality / image properties. I will update my question to be more specific about this.
    – Masjo
    Feb 6 '20 at 13:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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