Extract gridded data from GEE - r

I would like to extract data from certain satellite images (e.g. average night lights) in GEE for square grids in a given country in order to analyse the data in R. The square grids are supposed to be rather small (100x100m²). What is the most efficient way to accomplish that?
My current approach would be to create a suitable shapefile in R, upload that to GEE, extract the data and download the results. Unfortunately it's computationally very intensive to do this for such small grids (and currently I'm not sure GEE allows me to do that). Is there a more efficient alternative to get to my goal?

Here's how you can export an ee.Image for the desired region at a different scale.
// Example night lights image
var nl = ee.ImageCollection('NOAA/VIIRS/DNB/MONTHLY_V1/VCMCFG').first().select(0);
// All countries
var countries = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017');
// For example
var brazil = countries.filter(ee.Filter.eq('country_na', 'Brazil'));
Map.addLayer(brazil)
// Desired output resolution in meters.
var scale = 100;
// export the image at the desired scale
Export.image.toDrive({ image: nl,
region: brazil,
scale: scale });

Related

Mapping how many points are within a radius of every location in R

In R, I am trying to create a choropleth map. I have built a database of businesses, some are part of chains (e.g. McDonalds) and others are independent. I want to calculate how many businesses are within 30km of each point on the map, but treat the different locations of chains as a single business.
For example, if you a point is:
5km from a McDonalds,
10km from Taco Bell
15km from Chick-Fil-A
20km from KFC
25km from McDonalds
35km from Five Guys
The colour will show that there are 4 fast food outlets within 30km.
I am happy to use any R package but I am mostly familiar with tmaps and ggplot2 maps.
At this stage the best approach I can think of is to create polygons for each chain and stack them as transparent layers of the same colour. I don't think this would be very efficient and wouldn't create a very nice looking choropleth.
The other answers I could find were either counting points (e.g https://gis.stackexchange.com/questions/229066/counting-how-many-times-a-point-is-inside-a-set-of-intersecting-polygons-in-r) or for GIS software.
EDIT:
I have managed to create a 30km radius from every location of every chain (using rgeos gIntersection). I now have a series of polygons.
To solve my question the additional thing I need to do is create polygons for where:
Only one polygon covers the area,
Two polygons covers the area,
etc.
To try to visual is this I used the answer from https://gis.stackexchange.com/questions/229066/counting-how-many-times-a-point-is-inside-a-set-of-intersecting-polygons-in-r
In the linked question they are trying to count how many polygons cover the numbered points (the image on the right). What I am trying to do is to create the image on the left, where there are polygons of no overlap (1), two overlapping polygons (2) and so on.
I think what you are trying to accomplish would be best approached using a raster approach rather than a chloropleth. To make a chorlopleth, you define a set of (generally irregular) polygons, summarize something within each polygon, then color the polygons based on the attributes. This would be a good approach if you wanted to say how many fast food resteraunts are within each state or county, or how many fast food joints per capita by state.
From your description, however, you are looking for how many fast food joints within a set radius for all points. This is more of a raster question, since you can represent your data on a regular grid.
The raster package is a good start for working with raster data and works well with the sf package.
You need to determine what density you need to accomplish your goal, then use this to determine the resolution of your raster. Once you've got that you can use raster::rasterize() to summarize your (I'm assuming) point data.
I'm assuming you have an object that has the locations of each restaurant, I'll call this object "points".
library(raster)
library(sf)
# create raster template with 30km resolution (I'm assuming your projection is in meters)
raster_template = raster((extent(points),
resolution = 30000,
crs = st_crs(points)
)
# rasterize your point data
r = rasterize(points, raster_template, fun = "count")
This should create a grid where each cell has the number of points within each 30km cell. You should then be able to plot the raster, but may want to either clip or mask it to just show parts that are within New Zealand

Spectral separability analysis Google Earth Engine

I need to carry out a classification using Sentinel 2 images, and for this, I need to perform a spectral separability analysis to select the best bands and vegetation indexes to use. So, I need to calculate the Mean and Standard deviation of the training sites. I tried using this code but the result is not useful
// Get the Mean of the bands of the image for the polygons of the Vegetation class
var MeanTraining = Image.reduceRegions({
collection: Vegetation, // Vegetation is a FeatureCollection of polygons
reducer: ee.reducer.mean(),
scale:30
});
This code calculate the Mean and Standard deviation of each polygon delimited in the class vegetation, instead of a global value for the class. So after run this code I get many Means and SD for vegetation Class. Does anyone know how to get a the Mean and Standard deviation for a ee.FeatureCollection?
I have found the error in the Script
At the moment to define the vector (Vegetation) it is necessary to use geometry instead of collection. So following is the right Script
// Get the Mean of the bands of the image for the polygons of the Vegetation class
var MeanTraining = Image.reduceRegions({
geometry: Vegetation,
reducer: ee.Reducer.mean(),
scale:30
});

Google Earth Engine: Extract band values from pixel in each image of a collection?

sorry for the basic question, I'm a GEE beginner.
Essentially, what I want to do it extract the value of a certain band in a pixel from each image in a collection, and put it into an array.
I understand how to do this if the output is to a chart, e.g.:
print(ui.Chart.image.series(with_ndvi.select("nd"),area));
Where with_ndvi is my image collection, "nd" is the band I'm interested in, and area is a point feature.
However, I need to get these values into an array, because I need to perform a calculation on each value.
Is there an easy funciton to map over a collection to extract the values as numbers to work with?
Thanks for any help.
In general, in order to get particular values out of an image, you use reduceRegion. Since you have a single point, there isn't exactly any reduction, but the same operation can be used to get the mean, median, maximum, etc. from an area and you need to choose a reducer to perform the operation. (ui.Chart.image.series defaults to the mean reducer if you don't specify otherwise).
I constructed this example from the images used in the Normalized Difference example script:
var imageCollection = ee.ImageCollection('MODIS/006/MOD09GA')
.filterDate('2019-01-01', '2019-01-31');
var ndviCollection = imageCollection.map(function (img) {
var ndImage = img.normalizedDifference(['sur_refl_b02', 'sur_refl_b01']);
return ee.Feature(area, ndImage.reduceRegion(ee.Reducer.mean(), area));
});
print(ndviCollection);
Runnable example link
Here, ndviCollection is a FeatureCollection where each feature has the original point as geometry (useful if you have multiple points of interest, but otherwise you could make it be null instead) and the NDVI at that point as a property named nd.
If you absolutely need a list of numbers rather than a feature collection, you can obtain that:
print(ndviCollection
.toList(100) // set this number to the maximum number of elements you expect
.map(function (feature) {
return ee.Feature(feature).get('nd');
}));
but you should not do this if you can avoid it as lists are always kept in memory as a whole rather than processed in a streaming fashion. Instead, perform your computations on the feature collection using map and/or reduceColumns.

Pixel values Google Earth Engine

In Google Earth Engine, is it possible to obtain the pixel values of an image?
The following code displays the details of the image and we can see that the image has 10980*10980 pixels for the bands 2,3 and 4. How can we obtain the pixel value of band 3 at the (x,y) pixel or a specific (lat,lon)?
var im1 = ee.Image('COPERNICUS/S2/20160422T084804_20160422T123809_T36TVK')
print(im1)
// Image
var im1 = ee.Image('COPERNICUS/S2/20160422T084804_20160422T123809_T36TVK')
// Point
var p = ee.Geometry.Point(32.3, 40.3)
// Extract the data
var data = im1
.select("B3")
.reduceRegion(ee.Reducer.first(),p,10)
.get("B3")
// Convert to Number for further use
var dataN = ee.Number(data)
// Show data
print(dataN)
// Add Layers
Map.centerObject(im1)
Map.addLayer(im1,{bands:["B4","B3","B2"],min:0,max:5000})
Map.addLayer(p)
You can also use the inspector tool, next to the console tab on the right upper area of the interface. After clicking on a location on the map you will see the values of each band for each map layer displayed for that pixel corresponding to that location.
Another note, if you need the value of a pixel for all images in an ImageCollection, for example, is that you can turn the ImageCollection into an image using:
image_with_bands = original_image_name.toBands()
Then when you do a reduceRegion and the .getInfo() (or .get() for Java), you get a list of all of the values for all of the bands, where the bands are named by the original band name with an _ and then the date! Another good tool for this kind of calculation is the geemap package, which has a lot of these tools ready to go.

Finding the image boundary

While I use R quite a bit, just started an image analysis project and I am using the EBImage package. I need to collect a lot of data from circular/elliptical images. The built-in function computeFeatures gives the maximum and minimum radius. But I need all of the radii it computes.
Here is the code. I have read the image, thresholded and filled.
actual.image = readImage("xxxx")
image = actual.image[,2070:4000]
image1 = thresh(image)
image1 = fillHull(image1)
As there are several objects in the image, I used the following to label
image1 = bwlabel(image1)
I generated features using the built in function
features = data.frame(computeFeatures(image1,image))
Now, computeFeatures gives max radius and min radius. I need all the radii of all the objects it has computed for my analysis. At least if I get the coordinates of boundaries of all objects, I can compute the radii through some other code.
I know images are stored as matrices and can come up with a convoluted way to find the boundaries and then compute radii. But, was wondering if there a more elegant method?
You could try extracting each object + some padding, and plotting the x and y axis intensity profiles for each object. The intensity profiles is simply the sum of rows / columns which can be computed using rowSums and colSums in R
Then you could find where it dropps by splitting each intensity profiles in half and computing the nearest minimum value.
Maybe an example would help clear things up:
Hopefully this makes sense

Resources