Как перебрать и загрузить каждое изображение в коллекции изображений из Python API Google Earth Engine

Я новичок в Google Earth Engine и пытался понять, как использовать Python API Google Earth Engine. Я могу создать коллекцию изображений, но, видимо, getdownloadurl() Метод работает только на отдельных изображениях. Поэтому я пытаюсь понять, как перебирать и загружать все изображения в коллекции.

Вот мой основной код. Я подробно описал это для какой-то другой работы, которую я делаю.

import ee
ee.Initialize()
col = ee.ImageCollection('LANDSAT/LC08/C01/T1')
col.filterDate('1/1/2015', '4/30/2015')
pt = ee.Geometry.Point([-2.40986111110000012, 26.76033333330000019])
buff = pt.buffer(300)
region = ee.Feature.bounds(buff)
col.filterBounds(region)

Поэтому я вытащил коллекцию Landsat, отфильтрованную по дате и геометрии буфера. Поэтому в коллекции должно быть что-то вроде 7-8 изображений (со всеми полосами).

Однако я не мог заставить итерацию работать над коллекцией.

например:

for i in col:
    print(i)

Ошибка указывает TypeError: 'ImageCollection' object is not iterable

Так что, если коллекция не повторяется, как я могу получить доступ к отдельным изображениям?

Как только у меня появится изображение, я смогу использовать обычный

path = col[i].getDownloadUrl({
    'scale': 30,
    'crs': 'EPSG:4326',
    'region': region
})

4 ответа

Это хорошая идея для использования ee.batch.Export за это. Также рекомендуется избегать смешения функций клиента и сервера ( ссылка). По этой причине цикл for можно использовать, так как Export это функция клиента Вот простой пример для начала:

import ee
ee.Initialize()

rectangle = ee.Geometry.Rectangle([-1, -1, 1, 1])
sillyCollection = ee.ImageCollection([ee.Image(1), ee.Image(2), ee.Image(3)])

# This is OK for small collections
collectionList = sillyCollection.toList(sillyCollection.size())
collectionSize = collectionList.size().getInfo()
for i in xrange(collectionSize):
    ee.batch.Export.image.toDrive(
        image = ee.Image(collectionList.get(i)).clip(rectangle), 
        fileNamePrefix = 'foo' + str(i + 1), 
        dimensions = '128x128').start()

Обратите внимание, что преобразование коллекции в список таким способом также опасно для больших коллекций ( ссылка). Тем не менее, это, вероятно, самый масштабируемый метод, если вам действительно нужно скачать.

Вот мое решение:

import ee
ee.Initialize()
pt = ee.Geometry.Point([-2.40986111110000012, 26.76033333330000019])
region = pt.buffer(10)

col = ee.ImageCollection('LANDSAT/LC08/C01/T1')\
        .filterDate('2015-01-01','2015-04-30')\
        .filterBounds(region)

bands = ['B4','B5'] #Change it!

def accumulate(image,img):
  name_image = image.get('system:index')
  image = image.select([0],[name_image])
  cumm = ee.Image(img).addBands(image)
  return cumm

for band in bands:
  col_band = col.map(lambda img: img.select(band)\
                               .set('system:time_start', img.get('system:time_start'))\
                               .set('system:index', img.get('system:index')))
  #  ImageCollection to List           
  col_list = col_band.toList(col_band.size())

  #  Define the initial value for iterate.
  base = ee.Image(col_list.get(0))
  base_name = base.get('system:index')
  base = base.select([0], [base_name])

  #  Eliminate the image 'base'.
  new_col = ee.ImageCollection(col_list.splice(0,1))

  img_cummulative = ee.Image(new_col.iterate(accumulate,base))

  task = ee.batch.Export.image.toDrive(
      image = img_cummulative.clip(region),
      folder = 'landsat',
      fileNamePrefix = band,
      scale = 30).start()  

  print('Export Image '+ band+ ' was submitted, please wait ...')

img_cummulative.bandNames().getInfo()

Воспроизводимый пример вы можете найти здесь: https://colab.research.google.com/drive/1Nv8-l20l82nIQ946WR1iOkr-4b_QhISu

У меня аналогичная проблема, и я не смог решить ее с помощью представленных решений. Затем я разработал пример кода для этой цели. Он перебирает коллекцию изображений на стороне клиента, тогда на него не влияют ограничения (только на стороне сервера) .map()или же .iterate().

Скачать код и посмотреть его объяснение можно здесь

Он в основном трансформирует ImageCollectionв список (ic.toList()). Затем он выполняет стандартный цикл, и для каждого отдельного изображения можно преобразовать его обратно в ee.Image(list.get(i)), а затем обработать одно за другим все изображения в коллекции.

В вашем конкретном случае для загрузки каждого изображения функция, которая будет вызываться в цикле, может быть: getDOwnloadURL()или же getThumbURL():

      var url = imgNew.getDownloadURL({
    region: geometry,
  });

var thumbURL = imgNew.getThumbURL({region: geometry,dimensions: 512, format: 'png'});

Вы могли бы использовать ee.ImageCollection.iterate() с функцией, которая получает изображение и добавляет его в список.

import ee

def accumluate_images(image, images):
    images.append(image)
    return images

for img in col.iterate(accumulate_images, []):
    url = img.getDownloadURL(dict(scale=30, crs='EPSG:4326', region=region))

К сожалению, я не могу протестировать этот код, поскольку у меня нет доступа к API, но это может помочь вам найти решение.

Другие вопросы по тегам