1

I want to identify locations in an area of interest where the NDVI values are maximum and to achieve that I need to extract regions in NDVI image based on the range of values i.e 0-0.5 classA and 0.51-1 classB. So the output image will have two classes(calss A and B) and many regions based on the connectivity of the similar class pixels.

Following figure illustrates what I want to achieve.

enter image description here

  1. At first there is the image with raw values
  2. Image is classified into two classes based on the given ranges
  3. Then three regions are detected in image based on the connectivity of the similar class pixels
  4. Finally the pixels with the highest NDVI are extracted.

I need to automate this process for a very large therefore I am using Google Earth Engine. I have searched about this kind of regioning a lot but could not find anything specific to this. Is is possible to do this in Google Earth Engine or any function available in GEE or will I have to extract the data for the region of interest and then do all this by own?

2

You could try to use ee.Image.reduceConnectedComponents(). The problem there is that you have a maxSize, the maximum number of pixels a component can contain. If a component is larger than that, it gets masked. You can increase this value, but processing will get slower, and finally you will run out of memory. A workaround to this could be to split your classification into tiles, using GMeans(). Downside is that you will get artificial boundaries. Play with gridSize and maxSize to get something that works well enough.

var region = Map.getBounds(true)
var startDate = '2019-01-01'
var endDate = '2019-02-01'
var ndvi = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
  .filterBounds(region)
  .filterDate(startDate, endDate)
  .map(function (image) {
    return applyQABand(image).normalizedDifference(['B5', 'B4'])
  })
  .median()
  .rename('ndvi')

var classification = ee.Image([
    ndvi.lte(0.5).multiply(1), // Class A get value 1
    ndvi.gt(0.5).multiply(2) // Class A get value 2
  ])
  .reduce(ee.Reducer.sum())
  .rename('class')

var clusters = ee.Algorithms.Image.Segmentation
  .GMeans({
    image: classification,
    gridSize: 200
  })
  .rename('clusters')

var max = clusters.addBands(ndvi)
  .reduceConnectedComponents({
    reducer: ee.Reducer.max(),
    maxSize: 256
  })

Map.addLayer(ndvi, {min: 0, max: 1, palette: 'red,green'}, 'ndvi', false)
Map.addLayer(classification, {min: 1, max: 2, palette: 'red,green'}, 'classification', false)   
Map.addLayer(clusters.randomVisualizer(), null, 'clusters', false)   
Map.addLayer(max, {min: 0, max: 1, palette: 'red,green'}, 'max')

function applyQABand(image) {
  var cloudShadow = 1 << 3;
  var clouds = 1 << 5;
  var qa = image.select('pixel_qa');
  var mask = qa.bitwiseAnd(cloudShadow).eq(0)
    .and(qa.bitwiseAnd(clouds).eq(0));
  return image.updateMask(mask);
}

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

4
  • thanks, but how can I get the locations/pixels of every cluster where the maximum NDVI value occurs? – Ayaz49 Apr 6 '20 at 18:14
  • 1
    That depends on how you want them. It's usually a good idea to keep things as rasters as far as possible, as it can be problematic to turn rasters into features at scale. – Daniel Wiell Apr 6 '20 at 18:19
  • I want the location,max_ndvi value in JSON format. – Ayaz49 Apr 6 '20 at 18:48
  • 1
    You can do like this: code.earthengine.google.com/9ea3c5e11d5f00c91bc57743eac5174a, though it will not scale to a larger area. – Daniel Wiell Apr 6 '20 at 19:10

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.