0

I am working on applying the Change Detection using the CCDC algorithm for individual polygons in Google Earth Engine. My script functions correctly, but it runs quite slowly. I would like to know how I can increase its processing speed. Below is my current script:

// Define the coordinates for the MultiPolygon
var coordinates = [
  [
    [
      [176.633277937763, -38.52948922939942],
      [176.64701084791926, -38.52948922939942],
      [176.64701084791926, -38.517670864333496],
      [176.633277937763, -38.517670864333496],
      [176.633277937763, -38.52948922939942]  
    ]
  ],
  [
    [
      [176.51517491041926, -38.545602053961694],
      [176.53028111159114, -38.545602053961694],
      [176.53028111159114, -38.534860571938644],
      [176.51517491041926, -38.534860571938644],
      [176.51517491041926, -38.545602053961694]  
    ]
  ]
];

// Create the MultiPolygon geometry
var studyRegion = ee.Geometry.MultiPolygon(coordinates, null, false);
Map.centerObject(studyRegion);
Map.addLayer(studyRegion, {color: 'red'}, 'MultiPolygon');

// Sentinel-1 filtering
function get_s1_col(studyRegion, start_date, end_date) {
    return ee.ImageCollection('COPERNICUS/S1_GRD')
        .filter(ee.Filter.eq('instrumentMode', 'IW'))
        .filter(ee.Filter.eq('orbitProperties_pass', 'DESCENDING'))
        .filterDate(start_date, end_date)
        .filterBounds(studyRegion);
}

// Calculate VV/VH ratio
var calculateVVVHRatio = function(image) {
    var vv = image.select('VV').toFloat();
    var vh = image.select('VH').toFloat();
    var ratio = vh.subtract(vv).divide(vv.add(vh)).rename('VH_VV_ratio');
    return ee.Image.cat([vv, vh, ratio]).rename(['VV', 'VH', 'ratioVH_VV']);
};

// Clip each image in the collection
var clipCollection = function(image) {
    return image.clip(studyRegion);
};

// Process Sentinel-1 collection
var process_s1_collection = function(studyRegion, start_date, end_date) {
    return get_s1_col(studyRegion, start_date, end_date)
        .map(clipCollection)
        .map(calculateVVVHRatio);
};

// Process each polygon in the feature collection
var processPolygon = function(feature) {
    var polygon = feature.geometry();
    var s1_collection = process_s1_collection(polygon, '2021-01-01', '2024-02-04');

    var ccdParams = {
        breakpointBands: ['VH', 'VV', 'ratioVH_VV'],
        minObservations: 4,
        chiSquareProbability: 0.85,
        minNumOfYearsScaler: 0.5,
        dateFormat: 1,
        lambda: 2,
        maxIterations: 10000,
        collection: s1_collection
    };

    var ccdResults = ee.Algorithms.TemporalSegmentation.Ccdc(ccdParams);
    var change = ccdResults.select('tBreak');
    var changeProb = ccdResults.select('changeProb');

    var mask = change.gt(2024.0).and(change.lte(2024.0956284153006)).and(changeProb.eq(1));
    var magnitudes = ccdResults.select('ratioVH_VV_magnitude').arrayMask(mask);
    
    var negativeMagnitudes = magnitudes.arrayMask(magnitudes.lt(0));
    var maxAbsNegativeIndex = negativeMagnitudes.abs().arrayArgmax().arrayFlatten([['index']]);
    
    return negativeMagnitudes.arrayGet(maxAbsNegativeIndex).rename('maxNegativeMagnitude');
};

// Create an empty image collection to store results
var resultsCollection = ee.ImageCollection([]);
// Map over the feature collection and process each polygon
var processFeatureCollection = function(fc) {
  var results = fc.map(function(feature) {
    return ee.Image(processPolygon(feature)).set('polygon_id', feature.id());
  });
  
  return results;
};

// Define the feature collection
var featureCollection = ee.FeatureCollection(studyRegion);

// Process the feature collection
var processedResults = processFeatureCollection(featureCollection);
print(processedResults)

// Merge the results into a single image
var mergedResults = ee.ImageCollection(processedResults).mosaic();

// Export the merged result to Google Drive
Export.image.toDrive({
  image: mergedResults,
  description: 'Merged_CCDC_Results',
  scale: 10,
  maxPixels: 3784216672400,
  region: studyRegion
});

The link of my script here: https://code.earthengine.google.com/fdff2f56230da7825c1e03b46183b1a5

1 Answer 1

1

I ran your code and the task completed in 4 minutes. I tried these changes and the task completed in 5 minutes.

Following!

Final Optimized Workflow

  1. Convert MultiPolygon to FeatureCollection manually.
  2. Clip images before mapping calculations.
  3. Avoid mapping functions when only handling 2 polygons.
  4. Run CCDC on a composite image rather than a full collection.
  5. Reduce maxPixels in Export.image.toDrive().
// Convert MultiPolygon to FeatureCollection
var featureCollection = ee.FeatureCollection([
  ee.Feature(ee.Geometry.Polygon(coordinates[0][0])),
  ee.Feature(ee.Geometry.Polygon(coordinates[1][0]))
]);

// Function to process Sentinel-1 collection with efficient clipping
var process_s1_collection = function(studyRegion, start_date, end_date) {
    var clippedCollection = get_s1_col(studyRegion, start_date, end_date).map(clipCollection);
    return clippedCollection.map(calculateVVVHRatio);
};

// Process each polygon separately (Avoid unnecessary mapping)
var result1 = processPolygon(featureCollection.toList(2).get(0));
var result2 = processPolygon(featureCollection.toList(2).get(1));

var processedResults = ee.ImageCollection([result1, result2]);

// Merge results into one image
var mergedResults = processedResults.mosaic();

// Export with optimized maxPixels
Export.image.toDrive({
  image: mergedResults,
  description: 'Merged_CCDC_Results',
  scale: 10,
  maxPixels: 1e9,
  region: studyRegion
});

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.