Im using the geemap package (which adapts gee functionalities from gee for python) Firstly, I created an image collection:
#Select and Filter Sentinel 2 L2A Image
sentImages = ee.ImageCollection('COPERNICUS/S2') \
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 10)) \
.filterDate("2020-01-02", "2020-01-30") \
.filterBounds(geometry)
sentmosaic = sentImages.mosaic()
sentImage = sentmosaic.clip(geometry)
print("Sentinel 2 Scene", sentImage)
Further, Im performing the PCA analysis:
Map = geemap.Map()
# PCA Code
def getPrincipalComponents(centered, scale, region):
# Collapse the bands of the image into a 1D array per pixel.
arrays = centered.toArray()
print('PCA applying on', centered)
# Compute the covariance of the bands within the region.
covar = arrays.reduceRegion({
'reducer': ee.Reducer.centeredCovariance(),
'geometry': geometry,
'scale': scale,
'maxPixels': 1e9
})
# Get the 'array' covariance result and cast to an array.
# This represents the band-to-band covariance within the region.
covarArray = ee.Array(covar.get('array'))
# Perform an eigen analysis and slice apart the values and vectors.
eigens = covarArray.eigen()
# This is a P-length vector of Eigenvalues.
eigenValues = eigens.slice(1, 0, 1)
# This is a PxP matrix with eigenvectors in rows.
eigenVectors = eigens.slice(1, 1)
# Convert the array image to 2D arrays for matrix computations.
arrayImage = arrays.toArray(1)
# Left multiply the image array by the matrix of eigenvectors.
principalComponents = ee.Image(eigenVectors).matrixMultiply(arrayImage)
# Turn the square roots of the Eigenvalues into a P-band image.
sdImage = ee.Image(eigenValues.sqrt()) \
.arrayProject([0]).arrayFlatten([getNewBandNames('sd')])
# Turn the PCs into a P-band image, normalized by SD.
return principalComponents \
.arrayProject([0]) \
.arrayFlatten([getNewBandNames('pc')]) \
.divide(sdImage)
# Sentinel-2 True Color Map
TrueColor = {
'bands': ["B4", "B3", "B2"],
'min': 0,
'max': 3000,
'gamma':1.5
}
Map.addLayer(sentImage, TrueColor, "Sentinel 2 True Color")
# Sentinel-2 False Color Map
FalseColor = {
'bands': ["B11", "B12", "B8"],
'min': 0,
'max': 3000,
'gamma':1.5
}
Map.addLayer(sentImage, FalseColor, "Sentinel 2 False Color")
# Sentinel - 2 PCA
# Display the input imagery and the region in which to do the PCA.
sentbands = ['B2','B3','B4','B8','B11','B12']
region = sentImage.geometry()
image = sentImage.select(sentbands)
# Set some information about the input to be used later.
scale = 30
bandNames = image.bandNames()
# Mean center the data to enable a faster covariance reducer
# and an SD stretch of the principal components.
meanDict = image.reduceRegion({
'reducer': ee.Reducer.mean(),
'geometry': roi,
'scale': scale,
'maxPixels': 1000000000
})
means = ee.Image.constant(meanDict.values(bandNames))
centered = image.subtract(means)
# This helper function returns a list of new band names.
def getNewBandNames(prefix):
seq = ee.List.sequence(1, bandNames.length())
def func_rci(b):
return ee.String(prefix).cat(ee.Number(b).int())
return seq.map(func_rci)
pcImage = getPrincipalComponents(centered, scale, region)
# Plot each PC as a new layer
Map.addLayer(pcImage, {'bands': ['pc4', 'pc5', 'pc3'], 'min': -2, 'max': 2}, 'Sentinel 2 - PCA')
But, Im getting the following error:
EEException: Invalid argument for ee.Reducer(): ({'reducer': <ee.Reducer object at 0x00000261415B0F48>, 'geometry': ee.Geometry({
"functionInvocationValue": {
"functionName": "Feature.geometry",
"arguments": {
"feature": {
"functionInvocationValue": {
"functionName": "Feature",
"arguments": {
"geometry": {
"functionInvocationValue": {
"functionName": "GeometryConstructors.Polygon",
"arguments": {
"coordinates": {
"constantValue": [
[
[
-52.035679,
-21.745825
],
[
-52.035679,
-21.53033
],
[
-51.770479,
-21.53033
],
[
-51.770479,
-21.745825
],
[
-52.035679,
-21.745825
]
]
]
},
"geodesic": {
"constantValue": false
}
}
}
}
}
}
}
}
}
}), 'scale': 30, 'maxPixels': 1000000000},). Must be a ComputedObject.
I already tried to change the geometry type for feature and did not work. Anyone has any idea? I also already tried to decrease the time range of image collection but it is not working as well.
Thank you very much, best wishes.
Ana
I think the problem may be with trying to concatenate a string with a number. This solved it for me:
Best