Spectral separability analysis Google Earth Engine - 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
});

Related

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.

Extract gridded data from GEE

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 });

How can I select the optimal radius value in order to obtain the best normal estmation results

I'm running a model-scene match between a set of point clouds in order to test the matching results.
The match is based on 3D features such as normals and point feature histogram.
I'm using the normal estimation of point cloud library (pcl) to compute the histogram after I'd resampled the point cloud of both model and scene.
My question is, how can I test the accuracy of selecting different radius values in the nearest-neighbor estimation step.
I need to use that values for normal estimation, resampling and histogram in objects such as cup/knife/hummer etc.
I tried to visualize those objects using the pcl visulizer with different radius values and choosing which one that gives correct normals (In terms of how perpendicular were the normals orientation to the surfaces).
But I think that this visual testing is not enough and I would like to know if there are some empiric ways to estimate the optimal radius value.
I would appreciate any suggestion or help ,share your thoughts :)
Thank you.
I think you should start from a ground test: create a point cloud from a mesh using the mesh normals (using CloudCompare for example), then load it twice: once with full data (including normals) and once without normals.
Rebuild normals using the search radius to be tested then you can directly compare de obtained normals with the one extracted from the mesh...

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

How to resample/rebin a spectrum?

In Matlab, I frequently compute power spectra using Welch's method (pwelch), which I then display on a log-log plot. The frequencies estimated by pwelch are equally spaced, yet logarithmically spaced points would be more appropriate for the log-log plot. In particular, when saving the plot to a PDF file, this results in a huge file size because of the excess of points at high frequency.
What is an effective scheme to resample (rebin) the spectrum, from linearly spaced frequencies to log-spaced frequencies? Or, what is a way to include high-resolution spectra in PDF files without generating excessively large files sizes?
The obvious thing to do is to simply use interp1:
rate = 16384; %# sample rate (samples/sec)
nfft = 16384; %# number of points in the fft
[Pxx, f] = pwelch(detrend(data), hanning(nfft), nfft/2, nfft, rate);
f2 = logspace(log10(f(2)), log10(f(end)), 300);
Pxx2 = interp1(f, Pxx, f2);
loglog(f2, sqrt(Pxx2));
However, this is undesirable because it does not conserve power in the spectrum. For example, if there is a big spectral line between two of the new frequency bins, it will simply be excluded from the resulting log-sampled spectrum.
To fix this, we can instead interpolate the integral of the power spectrum:
df = f(2) - f(1);
intPxx = cumsum(Pxx) * df; % integrate
intPxx2 = interp1(f, intPxx, f2); % interpolate
Pxx2 = diff([0 intPxx2]) ./ diff([0 F]); % difference
This is cute and mostly works, but the bin centers aren't quite right, and it doesn't intelligently handle the low-frequency region, where the frequency grid may become more finely sampled.
Other ideas:
write a function that determines the new frequency binning and then uses accumarray to do the rebinning.
Apply a smoothing filter to the spectrum before doing interpolation. Problem: the smoothing kernel size would have to be adaptive to the desired logarithmic smoothing.
The pwelch function accepts a frequency-vector argument f, in which case it computes the PSD at the desired frequencies using the Goetzel algorithm. Maybe just calling pwelch with a log-spaced frequency vector in the first place would be adequate. (Is this more or less efficient?)
For the PDF file-size problem: include a bitmap image of the spectrum (seems kludgy--I want nice vector graphics!);
or perhaps display a region (polygon/confidence interval) instead of simply a segmented line to indicate the spectrum.
I would let it do the work for me and give it the frequencies from the start. The doc states the freqs you specify will be rounded to the nearest DFT bin. That shouldn't be a problem since you are using the results to plot. If you are concerned about the runtime, I'd just try it and time it.
If you want to rebin it yourself, I think you're better off just writing your own function to do the integration over each of your new bins. If you want to make your life easier, you can do what they do and make sure your log bins share boundaries with your linear ones.
Solution found: https://dsp.stackexchange.com/a/2098/64
Briefly, one solution to this problem is to perform Welch's method with a frequency-dependent transform length. The above link is to a dsp.SE answer containing a paper citation and sample implementation. A disadvantage of this technique is that you can't use the FFT, but because the number of DFT points being computed is greatly reduced, this is not a severe problem.
If you want to resample an FFT at a variable rate (logarithmically), then the smoothing or low pass filter kernel will need to be variable width as well to avoid aliasing (loss of sample points). Just use a different width Sync interpolation kernel for each plot point (Sync width approximately the reciprocal of the local sampling rate).

Resources