I am trying to do an unsupervised classification in GEE using Sentinel-2 drone imagery for training and classification and high-resolution drone data as a visual reference. When I define my training dataset, I get the following error message:
K-means Unsupervised classifier: Layer error: No data was found in training input.
All the code below, which contains a successful supervised classification (the unsupervised classification is at the very bottom). My GEE script is here: https://code.earthengine.google.com/e6ff079a2b440208c4309d87e0d3f501
//Here I try land classification using sentinel 2 imagery to train
//and drone imagery as a visual reference
//Load s2 data
var s2 = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED")
var pointKT = ee.Geometry.Point([92.1635,21.2127]);
Map.centerObject(pointKT);
Map.addLayer(campBoundaries, {}, "Camp Boundaries");
// Mask out the black background from Camp 4
var mask = Camp4.select('b1').neq(1).and(Camp4.select('b2').neq(1)).and(Camp4.select('b3').neq(1));
var Camp4Masked = Camp4.updateMask(mask);
// Function to remove the b4 band if it exists
var removeExtraBand = function(image) {
var bands = image.bandNames();
return bands.contains('b4') ? image.select(['b1', 'b2', 'b3']) : image;
};
//Apply the function to drone2019
var drone2019Uniform = drone2019.map(removeExtraBand);
//Load the 2019 imagery as a mosiac.
var mosiacDrone2019 = drone2019Uniform.mosaic();
// Combine the rest of the camps and the masked Camp 4 as a mosiac. Then map it.
var combinedMosaic = ee.ImageCollection([mosiacDrone2019, Camp4Masked]).mosaic();
Map.addLayer(combinedMosaic, {}, 'NPM Drone Imagery 2019 (Released July 2019)');
//Date range.
var startDate= '2018-10-01'; // Start date for the drone period
var endDate = '2019-05-01'; // End date for the drone period
//Note I added more months of data to improve quality due to cloud cover
//Cloud cover mask
function cloudMask(KTimage){
var scl = KTimage.select('SCL'); //Scene classification layer.
var mask = scl.eq(3).or(scl.gte(7).and(scl.lte(10)));
return KTimage.updateMask(mask.eq(0));
}
var KTimage = s2
.filterBounds(pointKT)
.filterDate(startDate,endDate)
.map(cloudMask)
.median();
//Get a preliminary map
Map.addLayer(KTimage, {
bands:['B4','B3','B2'],
min:0,
max: [3000]
},'True Colour April-May');
//NDVI
var ndvi = KTimage.normalizedDifference(['B8','B4']);
var vegPalette = ['red', 'white', 'green'];
//Masked NDVI layer
Map.addLayer(ndvi, {
min: -1,
max: 1,
palette: vegPalette
}, 'NDVI April-May');
///////////////////////////////////////////////////////////////////////////
//Classification process begins:
// Combine training feature collections.
var trainingFeatures = ee.FeatureCollection([
vegetation, bare, settlement, water
]).flatten();
// Define prediction bands.
// Left some bands out (aerosols, clouds, etc. See documentation)
var predictionBands = [
'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8',
'B8A', 'B11', 'B12'
];
// 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8',
// 'B8A', 'B9', 'B11', 'B12'
// Sample training points.
var classifierTraining = KTimage.select(predictionBands)
.sampleRegions({
collection: trainingFeatures,
properties: ['class'],
scale: 10
});
print(classifierTraining);
//////////////// CART Classifier ///////////////////
// Train a CART Classifier.
var classifier = ee.Classifier.smileCart().train({
features: classifierTraining,
classProperty: 'class',
inputProperties: predictionBands
});
// Classify the Landsat image.
var classified = KTimage.select(predictionBands).classify(classifier);
// Define classification image visualization parameters.
var classificationVis = {
min: 0,
max: 3,
palette: ['38761d', 'ffff52', 'ff0004', '0000ff']
};
// vegatation, bare soil, built-up, water.
// Add the classified image to the map.
Map.addLayer(classified, classificationVis, 'CART classified');
/////////////// Random Forest Classifier /////////////////////
// Train RF classifier.
var RFclassifier = ee.Classifier.smileRandomForest(50).train({
features: classifierTraining,
classProperty: 'class',
inputProperties: predictionBands
});
// Classify Landsat image.
var RFclassified = KTimage.select(predictionBands).classify(
RFclassifier);
// Add classified image to the map.
Map.addLayer(RFclassified, classificationVis, 'RF classified');
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
///////////////////////////////////////////////////////
/////Unsupervised Classification
///////////////////////////////////////////////////////
//Instead of selecting training points, this approach lets the algrithm find clusters in the data
//K means clusterer
var region = campBoundaries.geometry();
//Define the training dataset
var training = KTimage.sample({
region: region,
scale: 10,
numPixels: 1000,
tileScale: 4,
dropNulls: true
});
//Set up the clusterer and train it
var clusterer = ee.Clusterer.wekaKMeans(4).train(training);
//Cluster the input using the trained clusterer
var Kclassified = KTimage.cluster(clusterer)
//Display the clusters with random colours
Map.addLayer(Kclassified.randomVisualizer(),{},'K-means Unsupervised classifier')
//After classifying, mask settlements and farmland. Then export individual layers by class