Menggunakan ScriptProcessor untuk menghitung Normalized Difference Vegetation Index (NDVI) menggunakan Sentinel-2 data satelit - Amazon SageMaker

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Menggunakan ScriptProcessor untuk menghitung Normalized Difference Vegetation Index (NDVI) menggunakan Sentinel-2 data satelit

Contoh kode berikut menunjukkan kepada Anda cara menghitung indeks vegetasi perbedaan yang dinormalisasi dari area geografis tertentu menggunakan gambar geospasial yang dibuat khusus dalam notebook Studio Classic dan menjalankan beban kerja skala besar dengan Amazon Processing menggunakan dari Python. SageMaker ScriptProcessor SageMakerSDK

Demo ini juga menggunakan instance notebook Amazon SageMaker Studio Classic yang menggunakan kernel geospasial dan jenis instans. Untuk mempelajari cara membuat instance notebook geospasial Studio Classic, lihatMembuat notebook Amazon SageMaker Studio Classic menggunakan gambar geospasial.

Anda dapat mengikuti demo ini di instance notebook Anda sendiri dengan menyalin dan menempelkan cuplikan kode berikut:

Dengan search_raster_data_collection Anda dapat menanyakan koleksi data raster yang didukung. Contoh ini menggunakan data yang ditarik dari Sentinel-2 satelit. Area minat (AreaOfInterest) yang ditentukan adalah pedesaan Iowa utara, dan rentang waktu (TimeRangeFilter) adalah 1 Januari 2022 hingga 30 Desember 2022. Untuk melihat koleksi data raster yang tersedia dalam Wilayah AWS penggunaan list_raster_data_collections Anda. Untuk melihat contoh kode menggunakan iniAPI, lihat ListRasterDataCollectionsdi Panduan SageMaker Pengembang Amazon.

Dalam contoh kode berikut Anda menggunakan yang ARN terkait dengan Sentinel-2 pengumpulan data raster,arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8.

search_raster_data_collectionAPIPermintaan membutuhkan dua parameter:

  • Anda perlu menentukan Arn parameter yang sesuai dengan pengumpulan data raster yang ingin Anda kueri.

  • Anda juga perlu menentukan RasterDataCollectionQuery parameter, yang mengambil Python kamus.

Contoh kode berikut berisi pasangan kunci-nilai yang diperlukan untuk RasterDataCollectionQuery parameter yang disimpan ke variabel. search_rdc_query

search_rdc_query = { "AreaOfInterest": { "AreaOfInterestGeometry": { "PolygonGeometry": { "Coordinates": [[ [ -94.50938680498298, 43.22487436936203 ], [ -94.50938680498298, 42.843474642037194 ], [ -93.86520004156142, 42.843474642037194 ], [ -93.86520004156142, 43.22487436936203 ], [ -94.50938680498298, 43.22487436936203 ] ]] } } }, "TimeRangeFilter": {"StartTime": "2022-01-01T00:00:00Z", "EndTime": "2022-12-30T23:59:59Z"} }

Untuk membuat search_raster_data_collection permintaan, Anda harus menentukan ARN Sentinel-2 pengumpulan data raster:arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8. Anda juga harus meneruskan kamus Python yang telah ditentukan sebelumnya, yang menentukan parameter kueri.

## Creates a SageMaker Geospatial client instance sm_geo_client= session.create_client(service_name="sagemaker-geospatial") search_rdc_response1 = sm_geo_client.search_raster_data_collection( Arn='arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8', RasterDataCollectionQuery=search_rdc_query )

Hasil ini tidak API bisa dipaginasi. Untuk mengumpulkan semua gambar satelit yang dikembalikan oleh search_raster_data_collection operasi, Anda dapat menerapkan while loop. Ini memeriksa NextToken dalam API tanggapan:

## Holds the list of API responses from search_raster_data_collection items_list = [] while search_rdc_response1.get('NextToken') and search_rdc_response1['NextToken'] != None: items_list.extend(search_rdc_response1['Items']) search_rdc_response1 = sm_geo_client.search_raster_data_collection( Arn='arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8', RasterDataCollectionQuery=search_rdc_query, NextToken=search_rdc_response1['NextToken'] )

APIRespons mengembalikan daftar URLs di bawah Assets kunci yang sesuai dengan pita gambar tertentu. Berikut ini adalah versi respons yang terpotong. API Beberapa pita gambar telah dihapus untuk kejelasan.

{ 'Assets': { 'aot': { 'Href': 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/15/T/UH/2022/12/S2A_15TUH_20221230_0_L2A/AOT.tif' }, 'blue': { 'Href': 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/15/T/UH/2022/12/S2A_15TUH_20221230_0_L2A/B02.tif' }, 'swir22-jp2': { 'Href': 's3://sentinel-s2-l2a/tiles/15/T/UH/2022/12/30/0/B12.jp2' }, 'visual-jp2': { 'Href': 's3://sentinel-s2-l2a/tiles/15/T/UH/2022/12/30/0/TCI.jp2' }, 'wvp-jp2': { 'Href': 's3://sentinel-s2-l2a/tiles/15/T/UH/2022/12/30/0/WVP.jp2' } }, 'DateTime': datetime.datetime(2022, 12, 30, 17, 21, 52, 469000, tzinfo = tzlocal()), 'Geometry': { 'Coordinates': [ [ [-95.46676936182894, 43.32623760511659], [-94.11293433656887, 43.347431265475954], [-94.09532154452742, 42.35884880571144], [-95.42776890002203, 42.3383710796791], [-95.46676936182894, 43.32623760511659] ] ], 'Type': 'Polygon' }, 'Id': 'S2A_15TUH_20221230_0_L2A', 'Properties': { 'EoCloudCover': 62.384969, 'Platform': 'sentinel-2a' } }

Di bagian berikutnya, Anda membuat file manifes menggunakan 'Id' kunci dari API respons.

Buat file manifes masukan menggunakan Id kunci dari search_raster_data_collection API respons

Saat menjalankan pekerjaan pemrosesan, Anda harus menentukan input data dari Amazon S3. Tipe data input dapat berupa file manifes, yang kemudian menunjuk ke file data individual. Anda juga dapat menambahkan awalan ke setiap file yang ingin diproses. Contoh kode berikut mendefinisikan folder tempat file manifes Anda akan dihasilkan.

Gunakan SDK untuk Python (Boto3) untuk mendapatkan bucket default dan peran eksekusi ARN yang terkait dengan instance notebook Studio Classic Anda:

sm_session = sagemaker.session.Session() s3 = boto3.resource('s3') # Gets the default excution role associated with the notebook execution_role_arn = sagemaker.get_execution_role() # Gets the default bucket associated with the notebook s3_bucket = sm_session.default_bucket() # Can be replaced with any name s3_folder = "script-processor-input-manifest"

Selanjutnya, Anda membuat file manifes. Ini akan menyimpan gambar satelit yang ingin Anda proses ketika Anda menjalankan pekerjaan pemrosesan Anda nanti di langkah 4. URLs

# Format of a manifest file manifest_prefix = {} manifest_prefix['prefix'] = 's3://' + s3_bucket + '/' + s3_folder + '/' manifest = [manifest_prefix] print(manifest)

Contoh kode berikut mengembalikan S3 URI tempat file manifes Anda akan dibuat.

[{'prefix': 's3://sagemaker-us-west-2-111122223333/script-processor-input-manifest/'}]

Semua elemen respons dari respons search_raster_data_collection tidak diperlukan untuk menjalankan pekerjaan pemrosesan.

Cuplikan kode berikut menghapus elemen yang tidak perlu'Properties','Geometry', dan. 'DateTime' Pasangan 'Id' kunci-nilai,'Id': 'S2A_15TUH_20221230_0_L2A', berisi tahun dan bulan. Contoh kode berikut mem-parsing data tersebut untuk membuat kunci baru di Python kamusdict_month_items. Nilai adalah aset yang dikembalikan dari SearchRasterDataCollection kueri.

# For each response get the month and year, and then remove the metadata not related to the satelite images. dict_month_items = {} for item in items_list: # Example ID being split: 'S2A_15TUH_20221230_0_L2A' yyyymm = item['Id'].split("_")[2][:6] if yyyymm not in dict_month_items: dict_month_items[yyyymm] = [] # Removes uneeded metadata elements for this demo item.pop('Properties', None) item.pop('Geometry', None) item.pop('DateTime', None) # Appends the response from search_raster_data_collection to newly created key above dict_month_items[yyyymm].append(item)

Contoh kode ini mengunggah dict_month_items ke Amazon S3 JSON sebagai objek menggunakan .upload_file()APIoperasi:

## key_ is the yyyymm timestamp formatted above ## value_ is the reference to all the satellite images collected via our searchRDC query for key_, value_ in dict_month_items.items(): filename = f'manifest_{key_}.json' with open(filename, 'w') as fp: json.dump(value_, fp) s3.meta.client.upload_file(filename, s3_bucket, s3_folder + '/' + filename) manifest.append(filename) os.remove(filename)

Contoh kode ini mengunggah manifest.json file induk yang menunjuk ke semua manifes lain yang diunggah ke Amazon S3. Ini juga menyimpan jalur ke variabel lokal:s3_manifest_uri. Anda akan menggunakan variabel itu lagi untuk menentukan sumber data input saat Anda menjalankan pekerjaan pemrosesan di langkah 4.

with open('manifest.json', 'w') as fp: json.dump(manifest, fp) s3.meta.client.upload_file('manifest.json', s3_bucket, s3_folder + '/' + 'manifest.json') os.remove('manifest.json') s3_manifest_uri = f's3://{s3_bucket}/{s3_folder}/manifest.json'

Sekarang setelah Anda membuat file manifes masukan dan mengunggahnya, Anda dapat menulis skrip yang memproses data Anda dalam pekerjaan pemrosesan. Ini memproses data dari citra satelit, menghitungNDVI, dan kemudian mengembalikan hasilnya ke lokasi Amazon S3 yang berbeda.

Tulis skrip yang menghitung NDVI

Amazon SageMaker Studio Classic mendukung penggunaan perintah sihir %%writefile sel. Setelah menjalankan sel dengan perintah ini, isinya akan disimpan ke direktori Studio Classic lokal Anda. Ini adalah kode khusus untuk menghitungNDVI. Namun, berikut ini dapat berguna ketika Anda menulis skrip Anda sendiri untuk pekerjaan pemrosesan:

  • Dalam wadah pekerjaan pemrosesan Anda, jalur lokal di dalam wadah harus dimulai dengan/opt/ml/processing/. Dalam contoh ini, input_data_path = '/opt/ml/processing/input_data/' dan processed_data_path = '/opt/ml/processing/output_data/' ditentukan dengan cara itu.

  • Dengan Amazon SageMaker Processing, skrip yang menjalankan pekerjaan pemrosesan dapat mengunggah data yang diproses langsung ke Amazon S3. Untuk melakukannya, pastikan peran eksekusi yang terkait dengan ScriptProcessor instans Anda memiliki persyaratan yang diperlukan untuk mengakses bucket S3. Anda juga dapat menentukan parameter output saat menjalankan pekerjaan pemrosesan Anda. Untuk mempelajari lebih lanjut, lihat .run()APIoperasi di Amazon SageMaker Python SDK. Dalam contoh kode ini, hasil pemrosesan data diunggah langsung ke Amazon S3.

  • Untuk mengelola ukuran Amazon yang EBScontainer dilampirkan ke pemrosesan Anda, gunakan parameternya. volume_size_in_gb Ukuran default kontainer adalah 30 GB. Anda juga dapat secara opsional menggunakan library Python Garbage Collector untuk mengelola penyimpanan di wadah Amazon Anda. EBS

    Contoh kode berikut memuat array ke dalam wadah pekerjaan pemrosesan. Saat array membangun dan mengisi memori, pekerjaan pemrosesan macet. Untuk mencegah kerusakan ini, contoh berikut berisi perintah yang menghapus array dari wadah pekerjaan pemrosesan.

%%writefile compute_ndvi.py import os import pickle import sys import subprocess import json import rioxarray if __name__ == "__main__": print("Starting processing") input_data_path = '/opt/ml/processing/input_data/' input_files = [] for current_path, sub_dirs, files in os.walk(input_data_path): for file in files: if file.endswith(".json"): input_files.append(os.path.join(current_path, file)) print("Received {} input_files: {}".format(len(input_files), input_files)) items = [] for input_file in input_files: full_file_path = os.path.join(input_data_path, input_file) print(full_file_path) with open(full_file_path, 'r') as f: items.append(json.load(f)) items = [item for sub_items in items for item in sub_items] for item in items: red_uri = item["Assets"]["red"]["Href"] nir_uri = item["Assets"]["nir"]["Href"] red = rioxarray.open_rasterio(red_uri, masked=True) nir = rioxarray.open_rasterio(nir_uri, masked=True) ndvi = (nir - red)/ (nir + red) file_name = 'ndvi_' + item["Id"] + '.tif' output_path = '/opt/ml/processing/output_data' output_file_path = f"{output_path}/{file_name}" ndvi.rio.to_raster(output_file_path) print("Written output:", output_file_path)

Anda sekarang memiliki skrip yang dapat menghitungNDVI. Selanjutnya, Anda dapat membuat instance dari ScriptProcessor dan menjalankan pekerjaan Processing Anda.

Membuat sebuah instance dari ScriptProcessor kelas

Demo ini menggunakan ScriptProcessorkelas yang tersedia melalui Amazon SageMaker PythonSDK. Pertama, Anda perlu membuat instance dari kelas, dan kemudian Anda dapat memulai pekerjaan Processing Anda dengan menggunakan .run() metode.

from sagemaker.processing import ScriptProcessor, ProcessingInput, ProcessingOutput image_uri = '081189585635.dkr.ecr.us-west-2.amazonaws.com/sagemaker-geospatial-v1-0:latest' processor = ScriptProcessor( command=['python3'], image_uri=image_uri, role=execution_role_arn, instance_count=4, instance_type='ml.m5.4xlarge', sagemaker_session=sm_session ) print('Starting processing job.')

Ketika Anda memulai pekerjaan Processing Anda, Anda perlu menentukan ProcessingInputobjek. Dalam objek itu, Anda menentukan yang berikut:

  • Jalur ke file manifes yang Anda buat di langkah 2,s3_manifest_uri. Ini adalah sumber data input ke wadah.

  • Jalur ke tempat Anda ingin data input disimpan dalam wadah. Ini harus sesuai dengan jalur yang Anda tentukan dalam skrip Anda.

  • Gunakan s3_data_type parameter untuk menentukan input sebagai"ManifestFile".

s3_output_prefix_url = f"s3://{s3_bucket}/{s3_folder}/output" processor.run( code='compute_ndvi.py', inputs=[ ProcessingInput( source=s3_manifest_uri, destination='/opt/ml/processing/input_data/', s3_data_type="ManifestFile", s3_data_distribution_type="ShardedByS3Key" ), ], outputs=[ ProcessingOutput( source='/opt/ml/processing/output_data/', destination=s3_output_prefix_url, s3_upload_mode="Continuous" ) ] )

Contoh kode berikut menggunakan .describe()metode untuk mendapatkan rincian pekerjaan Processing Anda.

preprocessing_job_descriptor = processor.jobs[-1].describe() s3_output_uri = preprocessing_job_descriptor["ProcessingOutputConfig"]["Outputs"][0]["S3Output"]["S3Uri"] print(s3_output_uri)

Memvisualisasikan hasil Anda menggunakan matplotlib

Dengan pustaka Python Matplotlib, Anda dapat memplot data raster. Sebelum Anda memplot data, Anda perlu menghitung NDVI menggunakan gambar sampel dari Sentinel-2 satelit. Contoh kode berikut membuka array gambar menggunakan .open_rasterio() API operasi, dan kemudian menghitung NDVI menggunakan band nir dan red gambar dari Sentinel-2 data satelit.

# Opens the python arrays import rioxarray red_uri = items[25]["Assets"]["red"]["Href"] nir_uri = items[25]["Assets"]["nir"]["Href"] red = rioxarray.open_rasterio(red_uri, masked=True) nir = rioxarray.open_rasterio(nir_uri, masked=True) # Calculates the NDVI ndvi = (nir - red)/ (nir + red) # Common plotting library in Python import matplotlib.pyplot as plt f, ax = plt.subplots(figsize=(18, 18)) ndvi.plot(cmap='viridis', ax=ax) ax.set_title("NDVI for {}".format(items[25]["Id"])) ax.set_axis_off() plt.show()

Output dari contoh kode sebelumnya adalah citra satelit dengan NDVI nilai yang dilapis di atasnya. NDVINilai di dekat 1 menunjukkan banyak vegetasi yang ada, dan nilai mendekati 0 menunjukkan tidak ada vegetasi yang ditampilkan.

Citra satelit Iowa utara dengan NDVI hamparan di atasnya

Ini melengkapi demo penggunaanScriptProcessor.