La transformación de componentes principales (PC) (también conocida como transformación de Karhunen-Loeve) es una rotación espectral que toma datos de imágenes correlacionados espectralmente y genera datos no correlacionados. La transformación de PC logra esto mediante la diagonalización de la matriz de correlación de la banda de entrada a través del análisis de Eigen. Para hacerlo en Earth Engine, usa un reductor de covarianza en una imagen de array y el comando eigen()
en el array de covarianza resultante.
Considera la siguiente función para ese propósito (un ejemplo de esta en la aplicación está disponible como una secuencia de comandos del Editor de código y un notebook de Colab).
var getPrincipalComponents = function(centered, scale, region) { // Collapse the bands of the image into a 1D array per pixel. var arrays = centered.toArray(); // Compute the covariance of the bands within the region. var covar = arrays.reduceRegion({ reducer: ee.Reducer.centeredCovariance(), geometry: region, scale: scale, maxPixels: 1e9 }); // Get the 'array' covariance result and cast to an array. // This represents the band-to-band covariance within the region. var covarArray = ee.Array(covar.get('array')); // Perform an eigen analysis and slice apart the values and vectors. var eigens = covarArray.eigen(); // This is a P-length vector of Eigenvalues. var eigenValues = eigens.slice(1, 0, 1); // This is a PxP matrix with eigenvectors in rows. var eigenVectors = eigens.slice(1, 1); // Convert the array image to 2D arrays for matrix computations. var arrayImage = arrays.toArray(1); // Left multiply the image array by the matrix of eigenvectors. var principalComponents = ee.Image(eigenVectors).matrixMultiply(arrayImage); // Turn the square roots of the Eigenvalues into a P-band image. var sdImage = ee.Image(eigenValues.sqrt()) .arrayProject([0]).arrayFlatten([getNewBandNames('sd')]); // Turn the PCs into a P-band image, normalized by SD. return principalComponents // Throw out an an unneeded dimension, [[]] -> []. .arrayProject([0]) // Make the one band array image a multi-band image, [] -> image. .arrayFlatten([getNewBandNames('pc')]) // Normalize the PCs by their SDs. .divide(sdImage); };
import ee import geemap.core as geemap
def get_principal_components(centered, scale, region): # Collapse bands into 1D array arrays = centered.toArray() # Compute the covariance of the bands within the region. covar = arrays.reduceRegion( reducer=ee.Reducer.centeredCovariance(), geometry=region, scale=scale, maxPixels=1e9, ) # Get the 'array' covariance result and cast to an array. # This represents the band-to-band covariance within the region. covar_array = ee.Array(covar.get('array')) # Perform an eigen analysis and slice apart the values and vectors. eigens = covar_array.eigen() # This is a P-length vector of Eigenvalues. eigen_values = eigens.slice(1, 0, 1) # This is a PxP matrix with eigenvectors in rows. eigen_vectors = eigens.slice(1, 1) # Convert the array image to 2D arrays for matrix computations. array_image = arrays.toArray(1) # Left multiply the image array by the matrix of eigenvectors. principal_components = ee.Image(eigen_vectors).matrixMultiply(array_image) # Turn the square roots of the Eigenvalues into a P-band image. sd_image = ( ee.Image(eigen_values.sqrt()) .arrayProject([0]) .arrayFlatten([get_new_band_names('sd')]) ) # Turn the PCs into a P-band image, normalized by SD. return ( # Throw out an an unneeded dimension, [[]] -> []. principal_components.arrayProject([0]) # Make the one band array image a multi-band image, [] -> image. .arrayFlatten([get_new_band_names('pc')]) # Normalize the PCs by their SDs. .divide(sd_image) )
La entrada de la función es una imagen con una media cero, una escala y una región sobre la que se realizará el análisis. Ten en cuenta que las imágenes de entrada primero deben convertirse en una imagen de array de 1D y, luego, reducirse con ee.Reducer.centeredCovariance()
. El array que muestra esta reducción es la matriz simétrica de covarianza-varianza de la entrada.
Usa el comando eigen()
para obtener los valores propios y los vectores propios de la matriz de covarianza. La matriz que muestra eigen()
contiene los valores propios en la posición 0 del eje 1. Como se muestra en la función anterior, usa slice()
para separar los valores propios y los vectores propios. Cada elemento a lo largo del eje 0 de la matriz de eigenVectors es un vector propio. Al igual que en el ejemplo de gorro con borlas (TC), realiza la transformación multiplicando la matriz arrayImage
por los autovectores.
En este ejemplo, cada multiplicación de vectores propios genera un PC.