Harmonized Landsat Sentinel-2
북아메리카 Landsat-8 및 Sentinel-2 위성의 위성 이미지입니다.
HLS(Harmonized Landsat Sentinel-2) 제품에는 Landsat의 경우 2013년부터 현재까지, Sentinel-2의 경우 2015년부터 현재까지 30m 해상도로 일반적인 타일링 시스템에 맞춰 조정된 Landsat-8 및 Sentinel-2 위성의 데이터가 포함됩니다. HLS는 NASA(미국 항공 우주국)에서 관리합니다.
이 데이터 세트는 Ag-Analytics®에서 유지 관리합니다. 또한 Ag-Analytics®는 AOI(관심 영역) 다각형, 날짜 범위 및 기타 옵션을 허용하는 API를 제공하며 Normalized Difference Vegetation Index 및 기타 메트릭뿐만 아니라 개별 MSI 밴드에 대해 처리된 이미지와 클라우드 필터링 모자이크를 반환합니다.
이 데이터 세트는 매주 업데이트됩니다.
스토리지 리소스
데이터는 미국 동부 2 데이터 센터에 있는 다음 Blob 컨테이너의 Blob에 저장됩니다.
https://hlssa.blob.core.windows.net/hls
해당 컨테이너 내에서 데이터는 다음에 따라 정리됩니다.
<folder>/HLS.<product>.T<tileid>.<daynum>.<version>_<subdataset>.tif
folder
는 Landsat의 경우L309
이고 Sentinel-2의 경우S309
입니다.product
는 Landsat의 경우L30
이고 Sentinel-2의 경우S30
입니다.tileid
는 Sentinel-2 타일링 시스템의 4자 타일 코드입니다.daynum
은 4자리 연도와 1년 중의 3자리 날 수(001~365)입니다. 예를 들어 2019001은 2019년 1월 1일을 나타냅니다.version
는 항상v1.4
입니다.subdataset
는 2자이며, 1로 인덱싱된 문자열은 하위 데이터 세트를 나타냅니다(아래 참조).
위도/경도에서 타일 ID로의 매핑은 여기에서 확인할 수 있습니다. “데이터 액세스” 아래에서 제공되는 Notebook은 이 표를 사용하여 위도/경도별로 타일 ID를 조회하는 방법을 보여 줍니다. 타일 ID는 Ag-Analytics® API를 사용하여 찾을 수도 있습니다.
데이터는 다음과 같은 기본 타일에 대해 제공됩니다.
[‘10 U’,‘11 U’,‘12 U’,‘13 U’,‘14 U’,‘15 U’,‘16 U’,‘10 T’,‘11 T’,‘12 T’,‘13 T’,‘14 T’,‘15 T’,‘16 T’,‘17 T’,‘18 T’,‘19 T’,‘10 S’,‘11 S’,‘12 S’,‘13 S’,‘14 S’,‘15 S’,‘16 S’,‘17 S’,‘18 S’,‘12 R’,‘13 R’,‘14 R’,‘15 R’,‘16 R’,‘17 R’]
밴드는 다음과 같습니다.
밴드 이름 | OLI 밴드 번호 | MSI 밴드 번호 | L30 subdatasetnumber | S30 subdatasetnumber |
해안선 | 1 | 1 | 01 | 01 |
파랑 | 2 | 2 | 02 | 02 |
녹색 | 3 | 3 | 03 | 03 |
빨간색 | 4 | 4 | 04 | 04 |
빨간색 가장자리 1 | 5 | 05 | ||
빨간색 가장자리 2 | 6 | 06 | ||
빨간색 가장자리 3 | 7 | 07 | ||
넓은 NIR | 8 | 08 | ||
좁은 NIR | 5 | 8A | 05 | 09 |
SWIR 1 | 6 | 11 | 06 | 10 |
SWIR 2 | 7 | 12 | 07 | 11 |
수증기 | 9 | 12 | ||
권운 | 9 | 10 | 08 | 13 |
열적외선 1 | 10 | 09 | ||
열적외선 2 | 11 | 10 | ||
QA | 11 | 14 |
예를 들어 HLS.S30.T16TDL.2019206.v1.4_01.tif 파일 이름은 https://hlssa.blob.core.windows.net/hls/S309/HLS.S30.T16TDL.2019206.v1.4_03.tif 에 있으며, 2019년 206번째 날에 대한 데이터 세트 밴드 03(MSI 밴드 3, 녹색)에 대해 타일 16TDL(기본 타일 16T, 하위 타일 DL)의 Sentinel-2(S30) HLS 데이터를 나타냅니다.
또한 Blob 컨테이너를 드라이브로 탑재할 수 있게 해주는 BlobFuse 등을 통해 HLS 데이터에 액세스할 수 있는 읽기 전용 SAS(공유 액세스 서명) 토큰을 제공합니다.
st=2019-08-07T14%3A54%3A43Z&se=2050-08-08T14%3A54%3A00Z&sp=rl&sv=2018-03-28&sr=c&sig=EYNJCexDl5yxb1TxNH%2FzILznc3TiAnJq%2FPvCumkuV5U%3D
Linux용 탑재 지침은 여기에 있습니다.
HLS 데이터는 수백 테라바이트를 소비할 수 있으므로 대규모 처리는 이미지가 저장된 미국 동부 2 Azure 데이터 센터에서 최상으로 수행됩니다. 환경 과학 응용 분야에 HLS 데이터를 사용 중인 경우 컴퓨팅 요구 사항을 지원하려면 지구환경 AI(AI for Earth) 보조금 신청을 고려해 보세요.
연락처
이 데이터 세트에 대한 질문이 있는 경우 aiforearthdatasets@microsoft.com
으로 문의하세요.
알림
Microsoft는 Azure Open Datasets를 “있는 그대로” 제공합니다. Microsoft는 귀하의 데이터 세트 사용과 관련하여 어떠한 명시적이거나 묵시적인 보증, 보장 또는 조건을 제공하지 않습니다. 귀하가 거주하는 지역의 법규가 허용하는 범위 내에서 Microsoft는 귀하의 데이터 세트 사용으로 인해 발생하는 일체의 직접적, 결과적, 특별, 간접적, 부수적 또는 징벌적 손해 또는 손실을 비롯한 모든 손해 또는 손실에 대한 모든 책임을 부인합니다.
이 데이터 세트는 Microsoft가 원본 데이터를 받은 원래 사용 약관에 따라 제공됩니다. 데이터 세트에는 Microsoft가 제공한 데이터가 포함될 수 있습니다.
Access
Available in | When to use |
---|---|
Azure Notebooks | Quickly explore the dataset with Jupyter notebooks hosted on Azure or your local machine. |
Select your preferred service:
Azure Notebooks
# Standard-ish packages
import requests
import re
import numpy as np
import urllib
import io
import matplotlib.pyplot as plt
import pandas as pd
# Less standard, but all of the following are pip- or conda-installable
import rasterio
# pip install azure-storage-blob
from azure.storage.blob import ContainerClient
from osgeo import gdal,osr
# Storage locations are documented at http://aka.ms/ai4edata-hls
hls_container_name = 'hls'
hls_account_name = 'hlssa'
hls_account_url = 'https://' + hls_account_name + '.blob.core.windows.net/'
hls_blob_root = hls_account_url + hls_container_name
# This file is provided by NASA; it indicates the lat/lon extents of each
# hls tile.
#
# The file originally comes from:
#
# https://hls.gsfc.nasa.gov/wp-content/uploads/2016/10/S2_TilingSystem2-1.txt
#
# ...but as of 8/2019, there is a bug with the column names in the original file, so we
# access a copy with corrected column names.
hls_tile_extents_url = 'https://ai4edatasetspublicassets.blob.core.windows.net/assets/S2_TilingSystem2-1.txt'
# Load this file into a table, where each row is:
#
# Tile ID, Xstart, Ystart, UZ, EPSG, MinLon, MaxLon, MinLon, MaxLon
print('Reading tile extents...')
s = requests.get(hls_tile_extents_url).content
hls_tile_extents = pd.read_csv(io.StringIO(s.decode('utf-8')),delimiter=r'\s+')
print('Read tile extents for {} tiles'.format(len(hls_tile_extents)))
hls_container_client = ContainerClient(account_url=hls_account_url,
container_name=hls_container_name,
credential=None)
%matplotlib inline
def get_hls_tile(blob_url):
"""
Given a URL pointing to an HLS image in blob storage, load that image via GDAL
and return both data and metadata.
"""
formatted_gdal_bloburl='/{}/{}'.format('vsicurl',blob_url)
tile_open = gdal.Open(formatted_gdal_bloburl)
data = tile_open.GetRasterBand(1)
ndv,xsize,ysize = data.GetNoDataValue(),tile_open.RasterXSize,tile_open.RasterYSize
projection = osr.SpatialReference()
projection.ImportFromWkt(tile_open.GetProjectionRef())
datatype = data.DataType
datatype = gdal.GetDataTypeName(datatype)
data_array = data.ReadAsArray()
return ndv,xsize,ysize,projection,data_array
def list_available_tiles(prefix):
"""
List all blobs in an Azure blob container matching a prefix.
We'll use this to query tiles by location and year.
"""
files = []
generator = hls_container_client.list_blobs(name_starts_with=prefix)
for blob in generator:
files.append(blob.name)
return files
def lat_lon_to_hls_tile_id(lat,lon):
"""
Get the hls tile ID for a given lat/lon coordinate pair.
"""
found_matching_tile = False
for i_row,row in hls_tile_extents.iterrows():
found_matching_tile = lat >= row.MinLat and lat <= row.MaxLat \
and lon >= row.MinLon and lon <= row.MaxLon
if found_matching_tile:
break
if not found_matching_tile:
return None
else:
return row.TilID
# Specify a location and year of interest
lat = 47.6101; lon = -122.2015 # Bellevue, WA
year = '2019'
daynum = '109' # 1-indexed day-of-year
folder = 'S309' # 'S309' for Sentinel, 'L309' for Landsat
product = 'S30' # 'S30' for Sentinel, 'L30' for Landsat
year = '2019'
tile_id = lat_lon_to_hls_tile_id(lat,lon)
assert tile_id is not None, 'Invalid lat/lon'
prefix = folder + '/HLS.' + product + '.T' + tile_id + '.' + year
print('Finding tiles with prefix {}'.format(prefix))
matches = list_available_tiles(prefix)
assert len(matches) > 0, 'No matching tiles'
blob_name = matches[0]
print('Found {} matching tiles, using file {}'.format(len(matches),blob_name))
lat = 47.6101; lon = -122.2015 # Bellevue, WA
year = '2019'
daynum = '001' # 1-indexed day-of-year
folder = 'S30' # 'S30' for Sentinel, 'L30' for Landsat
product = 'S30' # 'S30' for Sentinel, 'L30' for Landsat
band = '01'
tile_id = '10TET' # See hls.gsfc.nasa.gov/wp-content/uploads/2016/10/S2_TilingSystem2-1.txt
version = 'v1.4' # Currently always v1.4
blob_name = folder + '/HLS.' + product + '.T' + tile_id + '.' + year + daynum + '.' + version \
+ '_' + band + '.tif'
print('Using file {}'.format(blob_name))
gdal.SetConfigOption('GDAL_HTTP_UNSAFESSL', 'YES')
blob_url = hls_blob_root + '/' + blob_name
print('Reading tile from {}'.format(blob_url))
ndv,xsize,ysize,projection,data_array = get_hls_tile(blob_url)
print('No-data value: {}'.format(ndv))
print('\nSize: {},{}'.format(xsize,ysize))
print('\nProjection:\n{}'.format(projection))
# Bands 2, 3, and 4 are B, G, and R in Sentinel-2 HLS images
base_url = '/vsicurl/' + hls_blob_root + '/' + blob_name
band2_url = re.sub('_(\d+).tif','_02.tif',base_url)
band3_url = re.sub('_(\d+).tif','_03.tif',base_url)
band4_url = re.sub('_(\d+).tif','_04.tif',base_url)
print('Reading bands from:\n{}\n{}\n{}'.format(band2_url,band3_url,band4_url))
band2 = rasterio.open(band2_url)
band3 = rasterio.open(band3_url)
band4 = rasterio.open(band4_url)
norm_value = 2000
image_data = []
for band in [band4,band3,band2]:
band_array = band.read(1)
band_array = band_array / norm_value
image_data.append(band_array)
band.close()
rgb = np.dstack((image_data[0],image_data[1],image_data[2]))
np.clip(rgb,0,1,rgb)
plt.imshow(rgb)
rgb_urls = [band4_url, band3_url, band2_url]
thumbnail_data = []
# url = rgb_urls[0]
for url in rgb_urls:
# From:
#
# https://automating-gis-processes.github.io/CSC/notebooks/L5/read-cogs.html
with rasterio.open(url) as raster:
# List of overviews from largest to smallest
oviews = raster.overviews(1)
# Retrieve the second-largest thumbnail
decimation_level = oviews[1]
h = int(raster.height/decimation_level)
w = int(raster.width/decimation_level)
thumbnail_channel = raster.read(1, out_shape=(1, h, w)) / norm_value
thumbnail_data.append(thumbnail_channel)
rgb = np.dstack((thumbnail_data[0],thumbnail_data[1],thumbnail_data[2]))
np.clip(rgb,0,1,rgb)
plt.imshow(rgb)