I have some Earth Engine code that extracts surface reflectance pixels from Landsat scenes.

var imageCollection = ee.ImageCollection("LANDSAT/LC08/C01/T1_SR");
var myfc = ee.FeatureCollection("users/adrianom/Meadow_17174");

// Function to cloud mask from the pixel_qa band of Landsat 8 SR data.
function maskL8sr(image) {
  // Bits 3 and 5 are cloud shadow and cloud, respectively.
  var cloudShadowBitMask = 1 << 3;
  var cloudsBitMask = 1 << 5;

  // Get the pixel QA band.
  var qa = image.select('pixel_qa');

  // Both flags should be set to zero, indicating clear conditions.
  var mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0)

  // Return the masked image, scaled to reflectance, without the QA bands.
  return image.updateMask(mask).divide(10000)
      .copyProperties(image, ["system:time_start"]);

var ic = imageCollection.map(maskL8sr)
                        .select(['B2', 'B3', 'B4', 'B5', 'B6', 'B7'], 
                                ['Blue', 'Green', 'Red', 'NIR', 'SWIR1', 'SWIR2']);

var extractPixelsFromPolygons = function(feature){
  var ic_filtered = ic.filter(ee.Filter.calendarRange(2015, 2015, 'year'))
                      .filter(ee.Filter.calendarRange(12, 12, 'month'))
  // Is this the right way to align???                   
  var proj = ic_filtered.first().projection();
  var latlon = ee.Image.pixelLonLat().reproject(proj);
  var coords = latlon.select(['longitude', 'latitude'])
      reducer: ee.Reducer.toList(),
      geometry: feature.geometry(),
      scale: 30
  var lat = ee.List(coords.get("latitude"));
  var lon = ee.List(coords.get("longitude"));
  var point_list = lon.zip(lat);
  var pixelCoords = ee.Geometry.MultiPoint(point_list);  
  var valuesAndCoords = ic_filtered.map(function(img){
    var pixelValues = img.reduceRegion({
      reducer: ee.Reducer.toList(),
      geometry: pixelCoords,
      scale: 30
    // Fields derived from "myfc" 
    var metaDictionary = ee.Dictionary({
      "Time/Date": ee.Date(img.get('system:time_start')),
      "UniqueID": feature.get('UniqueID'),
      "Area_m2": feature.get('Area_m2'),
      "Area_km2": feature.get('Area_km2'),
      "Landsat_ID": img.id()
    var pixels_and_coords_dict = metaDictionary.combine(coords).combine(pixelValues);
    var new_feature = ee.Feature(null, pixels_and_coords_dict);

var fc = myfc.map(extractPixelsFromPolygons).flatten().sort('UniqueID');

It filters the Landsat image collection by year, month, and by a geometry object. It then takes this image collection and grabs the first image's projection and uses this information to create a two-band image: one band representing latitude and the other longitude (I do this to essentially align all the Landsat pixels in different scenes together so that the coordinates are the exact same for each scene extraction). I use this image to get the pixel coordinates of my geometry object. I take these coordinates and use them to extract the pixel information from the Landsat scene. Finally, I export the coordinates, the pixel values, and some attributes from my polygon as a CSV. This works fine and dandy (feel free to try it yourself). However, I encountered what I believe to be a projection-related issue. When exporting the pixel values and their respective coordinates, take a look at the fourth feature in my feature collection that gets printed to the console. I noticed that I was extracting 254 pairs of coordinates, but only extracting 252 pixel values. They should be the same number: one pair of coordinates for one pixel value. Does anyone know how to fix this?


I figured it out. The changeProj() method in the ee.Image family of functions fixes my issue.

  • 1
    How does it fix your issue? – Kadir Şahbaz Sep 29 '20 at 21:11
  • It aligns pixel coordinates from one Landsat scene to the other. This way, my coordinates always remain constant. – Adriano Matos Sep 30 '20 at 22:05

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.