1

I am trying to classify the Bostanliq area of Uzbekistan. Everything is fine unless my final result does not give Forest even though I collected many samples for that class of land.

My code:

var countries = ee.FeatureCollection("FAO/GAUL/2015/level2");
var dem = ee.ImageCollection('JAXA/ALOS/AW3D30/V3_2');
var elevation = dem.select('DSM');
var uzbekistan = countries.filter(ee.Filter.eq('ADM0_NAME','Uzbekistan'));

var bostanliq =uzbekistan.filter(ee.Filter.eq('ADM2_NAME','Bostanlik district'));
Map.addLayer(bostanliq, {}, "Bostanliq");

                                    ///2013///
var landsat8 = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
    .filterDate('2014-05-01', '2015-06-01');

// Applies scaling factors.
function applyScaleFactors(image) {
  var opticalBands = image.select('SR_B.').multiply(0.0000275).add(-0.2);
  var thermalBands = image.select('ST_B.*').multiply(0.00341802).add(149.0);
  return image.addBands(opticalBands, null, true)
              .addBands(thermalBands, null, true);
}

var landsat8 = landsat8.map(applyScaleFactors);

var landsat_median = landsat8.median()
                            .clip(bostanliq)
                            .select(['SR_B1', 'SR_B2', 'SR_B3',
                            'SR_B4', 'SR_B5', 'SR_B7', 'SR_B6']);

var visualization = {
  bands: ['SR_B4', 'SR_B3', 'SR_B2'],
  min: 0.0,
  max: 0.3,
};

Map.addLayer(landsat_median,visualization, "Landsat 2013");

var gcp2013 =water.merge(glaciers).merge(urban).merge(rocks).merge(bare_land).merge(forests).merge(rangelands).merge(agriculture);
// Add a random column and split the GCPs into training and validation set
var gcp2013 = gcp2013.randomColumn();

//70 % training, 30 % 
var trainingGcp2013 =gcp2013.filter(ee.Filter.lt('random',0.7));
var validationGcp2013 =gcp2013.filter(ee.Filter.gte('random',0.7));


var training2013 = landsat_median.sampleRegions({
  collection:gcp2013,
  properties: ['landcover'],
  scale:30,
  tileScale:16
});

var classifier = ee.Classifier.smileRandomForest(50).train({
  features: training2013,
  classProperty:'landcover',
  inputProperties:landsat_median.bandNames(),
});

var classified2013 =landsat_median.classify(classifier);
Map.addLayer(classified2013, {min:1, max:8, palette:['blue','white','red','yellow','#c48c10','green','#00ff00','#ff64fd']}, "Classified");

var test =classified2013.sampleRegions({
  collection:validationGcp2013,
  properties:['landcover'],
   tileScale: 16,
   scale: 30,
});

var testConfusionMatrix2013 = test.errorMatrix('landcover', 'classification');
// Printing of confusion matrix may time out. Alternatively, you can export it as CSV
print('Confusion Matrix', testConfusionMatrix2013);
print('Test Accuracy', testConfusionMatrix2013.accuracy());

Export.image.toDrive({
  image: classified2013,
  description: 'Classification_2013',
  scale: 30,
  folder:'PhD',
  region: bostanliq,
  maxPixels: 1e13,
});

https://code.earthengine.google.com/c8fff2d294868e4b88acf04ee0d5a425

enter image description here

2 Answers 2

2

Everything is not fine because there are several issues in your code.

1.- First of all, as well pointed out Padmanabha, you have to assign class values in corresponding order starting on 0 (water = 0, glaciers = 1 and so on). This can be easily fixed in above code with functions as:

water = water.map(function (feat){
  
  return feat.set('landcover', 0);
});

However, you can better do that fixing your original feature collections.

2.- According to above numeral, you need to fix merging order as:

var gcp2013 = water.merge(glaciers)
                   .merge(urban)
                   .merge(agriculture)
                   .merge(bare_land)
                   .merge(forests)
                   .merge(rangelands)
                   .merge(rocks);

instead of this:

var gcp2013 =water.merge(glaciers).merge(urban).merge(rocks).merge(bare_land).merge(forests).merge(rangelands).merge(agriculture);

3.- For better observing above changes, I used following visualization parameters for classified layer:

Map.addLayer(classified2013, {min:0, 
                              max:7, 
                              palette:['blue',    //water
                                       'white',   //glaciers
                                       'red',     //urban
                                       'yellow',  //agriculture
                                       'brown',   //bare_land
                                       'green',   //forests
                                       'pink',    //rangelands
                                       'gray'     //rocks
                                       ]}, "Classified");

After running complete code at GEE code editor, I got the result of following picture:

enter image description here

Now, forests apparently look OK, however, the shadow of the slopes in high mountain conditions are making that some parts of the glaciers are being classified as human settlements. You should review this anomaly.

You can improve training points with this another script by using a COPERNICUS Landcover product.

1

The problem was with class values in your sample. In GEE, class value starts with 0, whereas you have started with 1. If you notice the confusion matrix, it has 9 elements starting from 0. You can fix it by assigning class value of water = 0, glacier =1 and so on. Finally, you have to set the min to 0 and max to 7 in Map.addLayer(). Then you can clearly see the green forest areas.

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.