1

I seek help to understand why colors that I specified in Google Earth Engine (GEE) do not appear in raster objects in R. Let me explain the processes that I have been going through. The following script is basically creating a landcover image for each county in the States. As you see, I have specified colors for visParam (i.e., landcoverVis) and used visualize(). I have geotif files as I expected. I attached an image below. (I cut the image with a polygon data.)

GEE code

// Step 1: Import and subset USGS National Land Cover Database

var foo = ee.Image('USGS/NLCD/NLCD2016').select('landcover');

// Step 2: Make a visualizing variable (Set up visParam details)

var landcoverVis = {
  min: 0.0,
  max: 95.0,
  palette: ['466b9f', // Open water
            'd1def8', // Perennial ice/snow
            'dec5c5', // Developed, open space: areas with a mixture of some constructed materials, but mostly vegetation in the form of lawn grasses
            'd99282', // Developed, low intensity: areas with a mixture of constructed materials and vegetation.
            'eb0000', // Developed, medium intensity: areas with a mixture of constructed materials and vegetation. 
            'ab0000', // Developed high intensity: highly developed areas where people reside or work in high numbers.
            'b3ac9f', // Barren land (rock/sand/clay)
            '68ab5f', // Deciduous forest:
            '1c5f2c', // Evergreen forest
            'b5c58f', // Mixed forest: Neither deciduous nor evergreen species are greater than 75% of total tree cover.
            'af963c', // Alaska only areas dominated by shrubs less than 20 centimeters tall with shrub canopy typically greater than 20% of total vegetation. 
            'ccb879', // Shrub/scrub:   This class includes true shrubs, young trees in an early successional stage, or trees stunted from environmental conditions.
            'd1d182', // Sedge/herbaceous: Alaska only areas dominated by sedges and forbs
            'dfdfc2', // Grassland/herbaceous: areas dominated by gramanoid or herbaceous vegetation
            'a3cc51', // Lichens: Alaska only areas dominated byLichens: Alaska only areas dominated by fruticose or foliose lichens or foliose lichens
            '82ba9e', // Moss: Alaska only areas dominated by mosses
            'dcd939', // Pasture/hay: areas of grasses, legumes, or grass-legume mixtures planted for livestock grazing or the production of seed or hay crops
            'ab6c28', // Cultivated crops: areas used for the production of annual crops, such as corn, soybeans, vegetables, tobacco, and cotton, and also perennial woody crops such as orchards and vineyards.
            'b8d9eb', // Woody wetlands
            '6c9fb8'  // Emergent herbaceous wetlands 
            ],
  bands:['landcover']};

// Use visualize() in order to add RGB values to an image. Otherwise, I will not see
// any colors in exported images. Here, I use the data from 2016 (foo)

var myimage = foo.visualize(landcoverVis);

// Specify a state name here.

var state = 'Delaware';

// Subset Feature Collection including polygon data.
// I have an imported shapefile of USA from GADM in my system.
// This feature collection is called usa.

var mystate = usa.filter(ee.Filter.eq("NAME_1", state));

// To image collection

var colFunc = function(feat) {
var county = feat.get("NAME_2");
var clipped = myimage.clip(feat).set("county", county);
return clipped;
};

var imcol = ee.ImageCollection(mystate.map(colFunc));

// Exporting images

var featlist = mystate.getInfo()['features'];
print('Feature list', featlist);

for (var f in featlist) {
  var feat = ee.Feature(featlist[f]);
  var county = feat.get("NAME_2");
  var countyName = county.getInfo();

Export.image.toDrive({
image: myimage.toFloat(),
description: state.replace(' ', '') + countyName.replace(new RegExp(" ", "g", "")),
folder: "my_earth_engine",
fileNamePrefix: state + "_" + countyName,
region: feat.geometry().bounds(), // I am specifying bbox.
scale: 30,
crs: "EPSG:4326",
maxPixels: 150000000 // This is enough to get all county images
});
}

enter image description here

My challenge

However, I realized that colors in the geotif files are not matching with the original GEE colors when I processed them in R. In my R script, I am basically counting the number of pixel for each color. I get a data frame like one below.

R code

library(raster)
library(dplyr)

# myraster is a GEE image (geotif file)
foo <- as.data.frame(as(stack(myraster), Class = "SpatialPixelsDataFrame"),
                     stringsAsFactors = FALSE)

names(foo) <- c("red", "green", "blue", "long", "lat")

out <- mutate(foo,
              color = rgb(red = red, green = green, blue = blue, max = 255)) %>%
       count(color)

#                  county   color total_pixel
#1  Connecticut_Fairfield #3B7340      968925
#2  Connecticut_Fairfield #598854       10178
#3  Connecticut_Fairfield #6C9FB8       12181
#4  Connecticut_Fairfield #789C67      200293
#5  Connecticut_Fairfield #9CC860       11816
#6  Connecticut_Fairfield #A4AC92        5442
#7  Connecticut_Fairfield #B80000       69861
#8  Connecticut_Fairfield #B8D9EB      131863
#9  Connecticut_Fairfield #BBA454        3588
#10 Connecticut_Fairfield #C50000      199356
#11 Connecticut_Fairfield #C8AD32        2705
#12 Connecticut_Fairfield #D10000      294851
#13 Connecticut_Fairfield #D2C336       30306
#14 Connecticut_Fairfield #DDBBB8       86084
#15 Connecticut_Fairfield #DE0000      468398

Let me show you two sets of colors so that you can see original colors changed.

GEE original colors

enter image description here

Colors that I have in the sample image above

There are 15 colors in this image rather than 16. Other images have 16 colors.

enter image description here

I do not know when the original colors are converted to the new colors. There are four red colors while there are two in the original color set (in my eyes).

Is this change happening when I am downloading an image from GEE API to my computer or is this happening when I am importing the image to R using stack()?

Update

I looked into .toFloat() in image: myimage.toFloat() in as Spacedman suggested. I found that the three bands in myimage were already int8. There is no need to change this. So, I deleted .toFloat() and checked if there is any change in colors. However, this change did not lead to any improvement; the original colors were still converted.

The other update is that I found Reducing Land Cover Data Sets in Earth Engine, which shows an attempt to get pixel data for each US county. This seems like the way to go. But I doubt this works all the time. When I used .clip() method and tried to save geotif files I received error messages saying that the present GEE does not support multiple polygons. This may be only for the cases where users want to save images. (I will check if the method in the linked question works).

I still do not know why the original colors are converted to the new colors though.

  • Can you make a sample tiff available? – Spacedman Sep 16 at 13:32
  • @Spacedman I uploaded a sample geotif file here. Please let me know if there is any issue. – jazzurro Sep 16 at 15:09
  • The values of the three bands in that file are definitely the values corresponding to the colours in your second 4x4 swatch. This is clear from reading the TIFF into QGIS and R. It looks like you have a categorical raster in GEE and its losing that nature when you convert to float. Possibly its doing some scaling before saving the image. I don't have a GEE account (thought I did...) but are there any params to the .toFloat method? – Spacedman Sep 16 at 15:52
  • @Spacedman Thank you very much for the comment. I am still new to GEE. I searched a bit here and found this post and this post. They may have something to do with the present case. I do not see any params in .toFloat(). When I see data, the RGB bands seem to be all in int8. I wonder if I need to use .float() rather than .toFloat(). – jazzurro Sep 16 at 16:42
  • @Spacedman It is pretty late here. If you can leave any message here, I will check it tomorrow morning. Thank you for your support. – jazzurro Sep 16 at 16:42
1

After investing a few days, I finally found a solution. I want to leave it so that other GEE users will not be trapped in the same way. I learned users need to use .visualize() with visParams in the GEE tutorial and some questions. However, this is not the case when users export land cover images. In my code above, I had the following.

var myimage = foo.visualize(landcoverVis);

landcoverVis includes information for visParams. I was assigning colors to foo. But this was not the case. In this case, I just needed the following; there is no need to specify colors.

var myimage = foo.visualize({bands:['landcover']});

This change allowed me to have an image with the proper colors.

enter image description here

Colors in this image

enter image description here

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.