我一直在使用Sam Murphy的代码对Google Earth Engine中的Sentinel-2图像进行大气校正。一切顺利,并且对于单个图像运行非常快。我想做的是将以下代码映射到图像集合上:
output = image.select('QA60')
for band in ['B1','B2','B3','B4','B5','B6','B7','B8','B8A','B9','B10','B11','B12']:
print(band)
output = output.addBands(surface_reflectance(band))
我认为我需要一个双重映射函数(以避免在这里使用for循环),但是还没有在GEE中看到任何Python示例。
到目前为止,这是我想出的:
def atcorrector(image):
qa = image.select('QA60')
bands = ee.List(['B1','B2','B3','B4','B5','B6','B7','B8','B8A','B9','B10','B11','B12'])
def mapper(bands):
return qa.map(addBands(surface_reflectance(bands)))
return qa
ImageCollection.map(atcorrector)
但是,这并不能返回所有波段的图像,因此我觉得我的嵌套函数无法正常工作。我是python的新手,因此感谢所有帮助!
旁注:我已经尝试过Sam的second repository来对图像集进行大气校正,但是它运行得太慢了,我希望使用提议的map函数作为“服务器端”计算,我有大量要处理的图像。
PS:以下是surface_reflectance
函数的代码,摘自Sam Murphy的存储库。它调用了他的定制课程之一,称为“大气”。用于大气校正的模型是Py6S模型。
# Package requirement
from Py6S import *
import datetime
import math
import os
import sys
sys.path.append(os.path.join(os.path.dirname(os.getcwd()),'bin'))
from atmospheric import Atmospheric #Custom-defined class by Sam
import ee
ee.Initialize()
## The Sentinel-2 image collection
studyarea = ee.Geometry.Rectangle(7.8399,59.9273,8.2299,60.1208)#region of interest
S2 = ee.ImageCollection('COPERNICUS/S2').filterBounds(studyarea)\
.filterDate('2016-06-01', '2016-06-10').sort('system:time_start')
## define metadata
info = S2one.getInfo()['properties']
scene_date = datetime.datetime.utcfromtimestamp(info['system:time_start']/1000)# i.e. Python uses seconds, EE uses milliseconds
solar_z = info['MEAN_SOLAR_ZENITH_ANGLE']
SRTM = ee.Image('USGS/GMTED2010') # Make sure that your study area is covered by this elevation dataset
alt = SRTM.reduceRegion(reducer=ee.Reducer.mean(), geometry=studyarea.centroid()).get('be75').getInfo() # insert correct name for elevation variable from dataset
km = alt/1000 # i.e. Py6S uses units of kilometers
date = ee.Date(START_DATE)
# the following three variables are called on from the Atmospheric class Sam defined in his GitHub
h2o = Atmospheric.water(studyarea,date).getInfo()
o3 = Atmospheric.ozone(studyarea,date).getInfo()
aot = Atmospheric.aerosol(studyarea,date).getInfo()
## Create the 6S Object
s = SixS() # Instantiate
# Atmospheric constituents
s.atmos_profile = AtmosProfile.UserWaterAndOzone(h2o,o3)
s.aero_profile = AeroProfile.Continental
s.aot550 = aot
# Earth-Sun-satellite geometry
s.geometry = Geometry.User()
s.geometry.view_z = 0 # always NADIR (I think..)
s.geometry.solar_z = solar_z # solar zenith angle
s.geometry.month = scene_date.month # month and day used for Earth-Sun distance
s.geometry.day = scene_date.day # month and day used for Earth-Sun distance
s.altitudes.set_sensor_satellite_level()
s.altitudes.set_target_custom_altitude(km)
# Extract spectral response function for given band name
def spectralResponseFunction(bandname):
bandSelect = {
'B1':PredefinedWavelengths.S2A_MSI_01,
'B2':PredefinedWavelengths.S2A_MSI_02,
'B3':PredefinedWavelengths.S2A_MSI_03,
'B4':PredefinedWavelengths.S2A_MSI_04,
'B5':PredefinedWavelengths.S2A_MSI_05,
'B6':PredefinedWavelengths.S2A_MSI_06,
'B7':PredefinedWavelengths.S2A_MSI_07,
'B8':PredefinedWavelengths.S2A_MSI_08,
'B8A':PredefinedWavelengths.S2A_MSI_09,
'B9':PredefinedWavelengths.S2A_MSI_10,
'B10':PredefinedWavelengths.S2A_MSI_11,
'B11':PredefinedWavelengths.S2A_MSI_12,
'B12':PredefinedWavelengths.S2A_MSI_13,
}
return Wavelength(bandSelect[bandname])
# Converts top of atmosphere reflectance to at-sensor radiance
def toa_to_rad(bandname):
ESUN = info['SOLAR_IRRADIANCE_'+bandname]
solar_angle_correction = math.cos(math.radians(solar_z))# solar exoatmospheric spectral irradiance
doy = scene_date.timetuple().tm_yday
d = 1 - 0.01672 * math.cos(0.9856 * (doy-4))# Earth-Sun distance (from day of year)
multiplier = ESUN*solar_angle_correction/(math.pi*d**2)# conversion factor
rad = toa.select(bandname).multiply(multiplier)# at-sensor radiance
return rad
# Calculate surface reflectance from at-sensor radiance given waveband name
def surface_reflectance(bandname):
s.wavelength = spectralResponseFunction(bandname) # run 6S for this waveband
s.run()
# extract 6S outputs
Edir = s.outputs.direct_solar_irradiance #direct solar irradiance
Edif = s.outputs.diffuse_solar_irradiance #diffuse solar irradiance
Lp = s.outputs.atmospheric_intrinsic_radiance #path radiance
absorb = s.outputs.trans['global_gas'].upward #absorption transmissivity
scatter = s.outputs.trans['total_scattering'].upward #scattering transmissivity
tau2 = absorb*scatter #total transmissivity
# radiance to surface reflectance
rad = toa_to_rad(bandname)
ref = rad.subtract(Lp).multiply(math.pi).divide(tau2*(Edir+Edif))
return ref
答案 0 :(得分:0)
要根据需要应用surface_reflectance
函数,只需按如下所示修改代码:
def atcorrector(image):
qa = image.select('QA60')
for band in ['B1','B2','B3','B4','B5','B6','B7','B8','B8A','B9','B10','B11','B12']:
print(band)
qa = qa.addBands(surface_reflectance(band))
return qa
ImageCollection.map(atcorrector)
如您所见,此代码仅复制您为单个图像制作的代码。 for
循环可以在Python API中正常工作(在JavaScript API中,我不建议您使用此循环)。如果您不想使用for
循环,只需稍微更改一下代码即可:
def atcorrector(image):
qa = image.select('QA60')
bands = ee.List(['B1','B2','B3','B4','B5','B6','B7','B8','B8A','B9','B10','B11','B12'])
def mapper(band):
qa = qa.addBands(surface_reflectance(band))
return band
bands.map(mapper)
return qa
ImageCollection.map(atcorrector)
map
的{{1}}函数(或任何具有ee.List
函数的ee
对象)可以代替map
循环。
希望这会有所帮助。