在 Google Earth Engine 中对 imageCollection 中的每个图像执行 PCA

Performing PCA per image over imageCollection in Google Earth Engine

我需要对图像的每个图像执行 PCA collection。然后,我只想保留 Principle component axis 1,并将其作为一个 band 添加到我图像中的每个图像 collection。最终,我想导出一个 .csv 文件,其中 GPS 采样位置位于 headers 行,图像 ID 为列 headers,平均主分量轴 1 为值。这样做背后的想法是,我想要一个代理(光谱异质性)用于 R 中的进一步统计分析。

这是我目前的代码:

//Create an test image to extract information to be used during PCA
var testImage =ee.Image('LANDSAT/LC08/C01/T1_SR/LC08_168080_20130407')
.select(['B2', 'B3', 'B4', 'B5', 'B6', 'B7'],
        ['Blue', 'Green', 'Red', 'NIR', 'SWIR1', 'SWIR2']);

// Define variables for PCA
var region = Extent;
var scale = testImage.projection().nominalScale();
var bandNames = testImage.bandNames();
Map.centerObject(region);

// Function for performing PCA
function doPCA(image){
  // This code is from https://code.earthengine.google.com/7249153a8a0f5c79eaf562ed45a7adad
var meanDict = image.reduceRegion({
    reducer: ee.Reducer.mean(),
    geometry: region,
    scale: scale,
    maxPixels: 1e9
});
var means = ee.Image.constant(meanDict.values(bandNames));
var centered = image.subtract(means);

// This helper function returns a list of new band names.
var getNewBandNames = function(prefix) {
  var seq = ee.List.sequence(1, bandNames.length());
  return seq.map(function(b) {
    return ee.String(prefix).cat(ee.Number(b).int());
  });
};

// [START principal_components]
var getPrincipalComponents = function(centered, scale, region) {
  var arrays = centered.toArray();
  var covar = arrays.reduceRegion({
    reducer: ee.Reducer.centeredCovariance(),
    geometry: region,
    scale: scale,
    maxPixels: 1e9
  });
  var covarArray = ee.Array(covar.get('array'));
  var eigens = covarArray.eigen();
  var eigenValues = eigens.slice(1, 0, 1);
  var eigenVectors = eigens.slice(1, 1);
  var arrayImage = arrays.toArray(1);
  var principalComponents = ee.Image(eigenVectors).matrixMultiply(arrayImage);
  var sdImage = ee.Image(eigenValues.sqrt())
    .arrayProject([0]).arrayFlatten([getNewBandNames('sd')]);
  return principalComponents
    .arrayProject([0])
    .arrayFlatten([getNewBandNames('pc')])
    .divide(sdImage);
};
var pcImage = getPrincipalComponents(centered, scale, region);
return (pcImage);
}

// map PCA function over collection
var PCA = LandsatCol.map(function(image){return doPCA(image)});
print('pca', PCA);

Extent 是我的投资回报率,而 LandsatCol 是预处理图像 collection。尝试将 PCA 映射到图像 collection(代码的倒数第二行)时,此处的代码会产生错误。错误内容为:"Array: Parameter 'values' is required".

关于如何处理这个问题有什么建议吗?以及如何在图像上添加主成分轴 1 作为每个图像的波段 collection?

我明白了。错误 "Array: Parameter 'values' is required" 与稀疏矩阵有关,稀疏矩阵是执行 PCA 时过滤、裁剪和指定区域的产物。 Earth Engine 无法处理稀疏矩阵。

这是工作代码。 LandsatCol 是我的预处理图片集。

// Display AOI
var point = ee.Geometry.Point([30.2261, -29.458])
Map.centerObject(point,10);

// Prepairing imagery for PCA
var Preped = LandsatCol.map(function(image){
  var orig = image;
  var region = image.geometry();
  var scale = 30;
  var bandNames = ['Blue', 'Green', 'Red', 'NIR', 'SWIR1', 'SWIR2'];
  var meanDict = image.reduceRegion({
    reducer: ee.Reducer.mean(),
    geometry: region,
    scale: scale,
    maxPixels: 1e9
  });
  var means = ee.Image.constant(meanDict.values(bandNames));
  var centered = image.subtract(means);
  var getNewBandNames = function(prefix) {
  var seq = ee.List.sequence(1, 6);
  return seq.map(function(b) {
    return ee.String(prefix).cat(ee.Number(b).int());
    });
  };

  // PCA function
  var getPrincipalComponents = function(centered, scale, region) {
    var arrays = centered.toArray();
    var covar = arrays.reduceRegion({
      reducer: ee.Reducer.centeredCovariance(),
      geometry: region,
      scale: scale,
      maxPixels: 1e9
    });
    var covarArray = ee.Array(covar.get('array'));
    var eigens = covarArray.eigen();
    var eigenValues = eigens.slice(1, 0, 1);
    var eigenVectors = eigens.slice(1, 1);
    var arrayImage = arrays.toArray(1);
    var principalComponents = ee.Image(eigenVectors).matrixMultiply(arrayImage);
    var sdImage = ee.Image(eigenValues.sqrt())
    .arrayProject([0]).arrayFlatten([getNewBandNames('sd')]);
    return principalComponents.arrayProject([0])
    .arrayFlatten([getNewBandNames('pc')])
    .divide(sdImage);
    };

  var pcImage = getPrincipalComponents(centered, scale, region);
  return ee.Image(image.addBands(pcImage));
});
print("PCA imagery: ",Preped);