2

I would like to count the number of pixels that are fully covered by a given region/geometry. How can I do that? Using standard reducer, I can get:

  • ee.Reducer.count() will just count the number of pixels whose centroid is included in the geometry. In the example, 6.
  • ee.Reducer.histogram() will do a weighted count of the number of pixels that have at least 0.5% covered by the geometry. Here 6.31
  • ee.Reducer.histogram().unweighted() does some strange stuff I don't get. Here 11

But none of these solutions counts the number of fully covered pixels, here 2. How can I do that?

enter image description here

Code

Available at: https://code.earthengine.google.com/615a60459b5a025eca34e3e42cf78496?noload=true

var rectangle = ee.Geometry.Polygon(
        [[[-92.53867, 40.18690],[-92.53867, 40.18638],[-92.53750, 40.18638],[-92.53750, 40.18690]]], null, false);
var CDL_2015 = ee.Image('USDA/NASS/CDL/2018')
  .select('cropland')

//count
var hist_1 = CDL_2015.gt(0).reduceRegion({
  reducer: ee.Reducer.histogram().combine({
  reducer2: ee.Reducer.histogram().unweighted(),
  outputPrefix: "_unweighted",
  sharedInputs: true}),
  geometry: rectangle,
  scale: 30,
  maxPixels: 1e9
})
print(hist_1)

var hist_2 = CDL_2015.gt(0).reduceRegion({
  reducer: ee.Reducer.histogram(),
  geometry: rectangle,
  scale: 30,
  maxPixels: 1e9
})
print(hist_2)

var count = CDL_2015.gt(0).reduceRegion({
  reducer: ee.Reducer.count(),
  geometry: rectangle,
  scale: 30,
  maxPixels: 1e9
})
print(count)


//////////////////
// Visu
/////////////////

Map.centerObject(rectangle)
Map.addLayer(CDL_2015.clip(rectangle.buffer(20)), {}, "CDL_2015")
Map.addLayer(ee.FeatureCollection(rectangle).style({width: 3, color: "blue", fillColor: "#00000000"}), {}, "CLU_here")

2 Answers 2

3

When applying ee.Image.clip(), partial pixels will have decimal values, between 0 and 1. You can use this to mask your image before reducing.

var mask = CDL_2015
  .clip(rectangle).mask()
  .eq(1) // Partial pixels will have value < 1. Mask them out

var masked = CDL_2015.updateMask(mask)

var hist_1 = masked.gt(0).reduceRegion({
  reducer: ee.Reducer.histogram().unweighted(),
  geometry: rectangle,
  scale: 30
})

https://code.earthengine.google.com/87e6c55c2020c71841853543ca18e2ae?noload=true

1
  • perfect, thanks! I tried to also visualize the layer with the coverage values, trying to plot mask or masked, but to no avail. How would you plot that? Thanks!!
    – Matifou
    Commented Apr 1, 2020 at 16:14
1

If you have a image projected with rectangle pixels, such as your CDL image, you will 99.9% of the cases be right when you use the count() reducer, with a slightly contracted geometry. This reducer indeed incorporates all the pixels which contain their center within the geometry. To make sure no redundant pixels are contained in the geometry, subtract half the scale from the geometry you apply the reduction on. That's easily done using buffer(-halfPixel). In the case of your image, the scale is 30m, so we contract the geometry by 15m:

var count = CDL_2015.gt(0).reduceRegion({
  reducer: ee.Reducer.count(),
  geometry: rectangle.buffer(-15), // subtract half the scale from geometry
  scale: 30,
  maxPixels: 1e9
})

Hope it works! Link with another test.

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.