I need some help in understanding image reducing with kernels. I have a code that generates a band of NDVI stdDev 3X3 kernel. When I map the layer the outcome is an image with empty pixels with a colored frame. Why is that? Why isn't the whole pixel colored? When I inspect the pixel I get a value of 0 but when I zoom out and inspect the pixel I get a numbered value. Why isn't every pixel colored and with a value like a regular NDVI image?

// Set up basic variables (NDVI).
var shpfile_name     = 'Tzora_Field_10_4_polygons_3857_Buffer-2'; // Shapefile name (from Assets).
var folder           = ''
var image_collection = "COPERNICUS/S2_SR"//image collection.
var first_date       = '2021-04-16' // First date in image collection
var last_date        = '2021-12-29' // Last date in image collection
var user_account     = 'users/yonatangoldwasser/'
var fc_ID            = 'Group'; // Field name of column with plot names.
var min_v            = 0.05
var max_v            = 0.75
var Name             = 'Corn Field 10-4 Tzora'
// Load raster data (COPERNICUS/S2_SR).
// Load vector data (shapefile).
var fc = ee.FeatureCollection(user_account+folder+shpfile_name).sort('Group');
var S2 = ee.ImageCollection(image_collection)
        .filterDate(first_date, last_date)
        .filterMetadata('CLOUDY_PIXEL_PERCENTAGE', 'less_than', 18);

print(fc)           // CRS must be WGS84 (for the shapefile)          

//Image Expression for calculating NDVI----------------------------------------------
var band_1 = 'B4'
var band_2 = 'B8'

var addNDVI = function(image) {
  var NDVI = image.expression(
    'B4': image.select('B4'),
    'B8': image.select('B8'),

  //NDVI index
  return image.addBands(NDVI.add(ee.Image(0.0)));
  //Add 0.0 value to NDVI (currently not in use)

// Calculate NDVIfor images in the Image collection 
var S2_withNDVI = ee.ImageCollection(S2).map(addNDVI);          
// Compute 3X3 standard deviation kernel (SD) as texture of the NDVI.
var addTexture_3X3_stdDev = function(image) {
var texture = image.select('NDVI').reduceNeighborhood({
reducer: ee.Reducer.stdDev().unweighted(),
kernel: ee.Kernel.square(1),
return image.addBands(texture.add(ee.Image(0.0)));
var S2_Analysis = ee.ImageCollection(S2_Analysis).map(addTexture_3X3_stdDev);
// Show images of NDVI (over image collection) on GEE. 
var count = S2_Analysis.size(); 
print ('size of collection imageSet', count);
var imageSetCollection = S2_Analysis.toList(count)
var ID = imageSetCollection.id


  var image = ee.Image(imageSetCollection.get(img))
Map.addLayer(image.select("NDVI_3X3_stdDev"), {min: 0, max: 0.006, palette: palette})

1 Answer 1


I couldn't reproduce your example, Earth Engine didn't find your assets, but maybe your problem is related to this other question: Statistics of Image Neighborhood in Google Earth Engine

The fact is that earth engine computes kernel reductions according to zoom level. In your case, it will compute in a 3x3 pixel square, but as far as I know, when EE is doing this it actually doesn't know what is an image pixel, it uses the pixels from your screen computer (or something related).

What I do to overcome that is to set the scale unit in the kernel to meters and then use a multiple of the pixel resolution from the data (which we usually know). Your kernel would look something like this: ee.Kernel.square(30,'meters')

But maybe I got wrong your point. Let me know if I'm helping in some way.

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.