1

I need to determine the Modis pixels that enter whole within the polygons contained within a feature collection.

I also need to determine those who don't fully enter.

Apologies for English

This is the script

https://code.earthengine.google.com/2c58d1f0e127f0d002ed20cf6872fe05

  • Please share your code in plain text. It cannot be accessed without a Google account and besides you cannot guarantee that it will be there forever. – Stefan Jan 24 at 21:46
  • Your fusionTables are not shared, so even though I can load the code I cannot see the Map layers. Permission denied for Fusion Table – Sean Roulet Jan 24 at 22:13
1

Interesting question. As your feature collection was not shared, I made one myself by drawing four polygons and adding them as import feature.

I believe the solution of Sean Roulet works pretty well, but it will still identify some pixels partly not inside your feature collection as inside, while they are actually not fully inside.

Therefore I used reduceToVectors. Following the method below, you will make a feature collection getting only the pixels which are fully inside your import feature collection. A disadvantage is that this will easily run out of memory if your area is large.

// make unique vectors from the pixels in the feature collection giving each pixel a random value
var randomImage = ee.Image.random().multiply(100000).toInt().reproject(image.projection())
// give an additional buffer around the area of intrest of the scale to include all pixels
var bufferWidth = 1; // set to 1 (include a buffer of scale size) or higher to lower the buffer
var buffered = poligonos.map(function(polygon){return polygon.buffer(image.projection().nominalScale().divide(bufferWidth))})
var toVectors = randomImage.reduceToVectors(ee.Reducer.countEvery(), buffered);

// calculate the pixels perfectly inside the feature collection of interest
var allVectors = poligonos.map(function(feature){
  // get the geometry of the individual features
  var geom = feature.geometry();
  // map over the pixel polygons
  var pixelPoligonos = toVectors.map(function(pixelPolygon){
    var pixelGeometry = pixelPolygon.geometry();
    return ee.Feature(pixelGeometry, {containedIn: pixelGeometry.containedIn(geom, 1)})
                                    .copyProperties(pixelPolygon)
  })
  return ee.Feature(pixelPoligonos)
}).flatten();

// remove duplicates. First sort on the pixels which are insie to not loose those
var insideAndOutside = allVectors.sort('containedIn', false).distinct(ee.SelectorSet('label')).limit(toVectors.size());
// seperate the polygons inside and outside the area of interest
var outside = insideAndOutside.filter(ee.Filter.eq('containedIn', false));
print('outside', outside)
var inside = insideAndOutside.filter(ee.Filter.eq('containedIn', true));
print('inside', inside)
// add the polygons to the map
Map.addLayer(outside.draw('red'), {}, 'pixels outside as features')
Map.addLayer(inside.draw('green'), {}, 'pixels inside as features')

// clip the images to the feature collections and show on the map
var pixelsInside = image.clipToCollection(inside);
var pixelsOutside = image.clipToCollection(outside);

Map.addLayer(pixelsInside , {palette: ['green']}, 'pixels inside')
Map.addLayer(pixelsOutside , {palette: ['red']}, 'pixels outside')

Note that you will need to determine a 'bufferWidth', which you can set at 1 to determine also pixels only for a little part inside your feature collection. Set it higher (2-3) if you are mainly interested in the pixels actually fully inside your feature collection.

Link to full code.

  • thank you both scripts work correctly Luckily the area studied is not large. Sorry for not uploading the FeatureCollection correctly – Andres Alejandro Leszczuk Jan 25 at 10:42
  • @Kuik I have gone through your script and had a question about the "buffer" you include more pixels than your area of interest, but given that you only want the pixels completely within the feature, this isn't a necessary step. Am I correct? Or is there another reason for it that I haven't gleaned? – Sean Roulet Feb 19 at 18:50
  • No that is not necesarry if you are only interested in the pixels fully inside, but is needed if you also want to show the pixels outside (just a visualization purpose). See the explanation below the code in my answer. – Kuik Feb 20 at 8:51
0

I have modified your code without the fusion table, and with my own polygon.

// Upload the fusion table
//var poligonos = ee.FeatureCollection("ft:14t4ks454i_xmiCRc4Z074_uiYvYYTW9WJ4jKbiAD");

// add to map the fusion table called poligonos
//Map.addLayer(poligonos,false,"Poligonos");
var geometry = /* color: #d63000 */ee.Geometry.Polygon(
    [[[-58.05947726385625, -29.22519320620489],
      [-58.05982058661016, -29.25080754028011],
      [-58.02574580328496, -29.251032199059082],
      [-58.02600329535039, -29.22489358543161]]]);

// call de colection MODIS Q1A13, and add filter from date
var imagen = ee.ImageCollection('MODIS/006/MYD13Q1')
        .filter(ee.Filter.date('2018-01-01', '2018-05-01'));

// select the ndvi atributte 
var ndvi = imagen.select(['NDVI']);

// settings visual parameters
var ndviVis = {
  min: 0.0,
  max: 8000.0,
  palette: [
    'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901',
    '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01',
    '012E01', '011D01', '011301'
  ],
};

// create mosaic and print in console
var mosaic = ndvi.mosaic();
print(mosaic,'mosaico');

// cut mosaic with poligonos
var imagen1 = mosaic.clip(geometry);

// add to map
Map.addLayer(imagen1,ndviVis,'ndvi');
print(geometry)

//var polygon = ee.Geometry.Polygon(poligonos.select(['features']));
var polygon = geometry.coordinates();
//print(poligonos);
print(polygon);

var image = ee.Image(imagen.first()).select(['NDVI'])
print(image,'Imagen first')
Map.addLayer(image.clip(geometry), ndviVis)
// generate a new image containing lat/lon of the pixel and reproject it to MODIS projection
// genera una nueva imagen que contiene la latitud y longitud del pixel y luego reproyecta esto
// a la proyeccion de modis
var coordsImage = ee.Image.pixelLonLat().reproject(image.projection());


// extract lat/lon coordinates as a list
var coordsList = coordsImage.reduceRegion({
  reducer: ee.Reducer.toList(2), 
  //geometry: Map.getBounds(true)
  geometry: geometry
}).values().get(0);

coordsList = ee.List(coordsList);

print(coordsList, 'Lista de puntos');

// convert coordinates to points and add to map
var coordsPoints = coordsList.map(function(xy) {
  var geom = ee.Algorithms.GeometryConstructors.Point(xy);
  return ee.Feature(geom, {});
});

coordsPoints = ee.FeatureCollection(coordsPoints);

Map.addLayer(coordsPoints,{},'puntos');

// Create a list of points on pixels that are inside the 125M of the geometry (the modis pixel is 250M) but (as in this case, the polygon doesn't follow the MODIS pixels, so there might be an issue with identifying the ones that are perfectly inside.

// buffer inwards

var geometrySmaller = geometry.buffer(-125)

// add smaller geometry to the map
Map.addLayer(geometrySmaller,{},"geometrySmaller")

// extract lat/lon coordinates as a list
var coordsList2 = coordsImage.reduceRegion({
  reducer: ee.Reducer.toList(2), 
  geometry: geometrySmaller
}).values().get(0);

coordsList2 = ee.List(coordsList2);

 print(coordsList2, 'Lista de puntos Inside');

// convert coordinates to points and add to map
 var coordsPoints2 = coordsList2.map(function(xy) {
  var geom = ee.Algorithms.GeometryConstructors.Point(xy);
  return ee.Feature(geom, {});
});
// create a feature collection of the points inside
coordsPoints2 = ee.FeatureCollection(coordsPoints2);


Map.addLayer(coordsPoints2,{color: '00FFFF'},'puntos Inside');

Now you have 2 lists.

  • coordsList of the pixels that are partially or totally inside.
  • coordsList2 of the pixels totally inside the geometry
  • Thank you for your prompt response, your contribution plus that of "Kuik" managed to show me what I needed. – Andres Alejandro Leszczuk Jan 25 at 10:47
  • This is the complete code, I have already published the feature collection link – Andres Alejandro Leszczuk Jan 25 at 11:13
  • As you have pointed out that Kuik's is the correct one, I would suggest you upvote his answer (the Up triangle). So that Kuik gets the kudos deserved. – Sean Roulet Jan 25 at 12:15
  • Ok, i am triying but i have less than 15 in reputation, I am not allowed to give you the vote. You know another way to hit it with the triangle up? – Andres Alejandro Leszczuk Jan 25 at 12:24
  • I hadn't realised there was a limit to up voting. When you have been around a bit, your reputation points will go up. When it happens, remember to return and give Kuik the upvote. – Sean Roulet Jan 25 at 12:30

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.