

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Accesso alla raccolta dei dati raster di Sentinel-2 e creazione di un processo di osservazione della terra per eseguire la segmentazione del suolo
<a name="geospatial-demo"></a>

Questo tutorial basato su Python utilizza l'SDK per Python (Boto3) e un notebook Amazon Studio Classic. SageMaker Per completare correttamente questa demo, assicurati di disporre delle autorizzazioni AWS Identity and Access Management (IAM) necessarie per utilizzare geospatial e Studio Classic. SageMaker SageMaker geospatial richiede la presenza di un utente, gruppo o ruolo che possa accedere a Studio Classic. È inoltre necessario disporre di un ruolo di esecuzione dell' SageMaker IA che specifichi il responsabile del servizio SageMaker geospaziale nella sua politica di fiducia. `sagemaker-geospatial.amazonaws.com` 

[Per ulteriori informazioni su questi requisiti, consulta SageMaker i ruoli IAM geospaziali.](sagemaker-geospatial-roles.md)

Questo tutorial mostra come utilizzare l'API SageMaker geospaziale per completare le seguenti attività:
+ Trovare le raccolte dei dati raster disponibili con `list_raster_data_collections`.
+ Cercare una raccolta dei dati raster specificata utilizzando `search_raster_data_collection`.
+ Creare un processo di osservazione della terra (EOJ) utilizzando `start_earth_observation_job`.

## Utilizzare `list_raster_data_collections` per trovare le raccolte dei dati disponibili
<a name="demo-use-list-rdc"></a>

SageMaker geospatial supporta più raccolte di dati raster. Per ulteriori informazioni sulle raccolte dei dati disponibili, consulta [Raccolte dati](geospatial-data-collections.md).

Questa demo utilizza i dati satellitari raccolti dai satelliti [Sentinel-2 GeoTIFF ottimizzati per il cloud](https://registry.opendata.aws/sentinel-2-l2a-cogs/). Questi satelliti forniscono una copertura globale della superficie terrestre ogni cinque giorni. Oltre a raccogliere immagini della superficie terrestre, i satelliti Sentinel-2 raccolgono anche dati su diverse bande spettrali.

Per cercare un'area di interesse (AOI), hai bisogno dell'ARN associato ai dati satellitari Sentinel-2. Per trovare le raccolte di dati disponibili e quelle associate ARNs nella tua Regione AWS, utilizza l'operazione API. `list_raster_data_collections`

Poiché la risposta può essere impaginata, devi utilizzare l'operazione `get_paginator` affinché restituisca tutti i dati pertinenti:

```
import boto3
import sagemaker
import sagemaker_geospatial_map
import json 

## SageMaker Geospatial  is currently only avaialable in US-WEST-2  
session = boto3.Session(region_name='us-west-2')
execution_role = sagemaker.get_execution_role()

## Creates a SageMaker Geospatial client instance 
geospatial_client = session.client(service_name="sagemaker-geospatial")

# Creates a resusable Paginator for the list_raster_data_collections API operation 
paginator = geospatial_client.get_paginator("list_raster_data_collections")

# Create a PageIterator from the paginator class
page_iterator = paginator.paginate()

# Use the iterator to iterate throught the results of list_raster_data_collections
results = []
for page in page_iterator:
    results.append(page['RasterDataCollectionSummaries'])

print(results)
```

Questo è un esempio di risposta JSON dall'operazione API `list_raster_data_collections`. La risposta è troncata per includere solo la raccolta dei dati (Sentinel-2) utilizzata in questo esempio di codice . Per ulteriori dettagli su una specifica raccolta dei dati raster, usa `get_raster_data_collection`:

```
{
    "Arn": "arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8",
    "Description": "Sentinel-2a and Sentinel-2b imagery, processed to Level 2A (Surface Reflectance) and converted to Cloud-Optimized GeoTIFFs",
    "DescriptionPageUrl": "https://registry.opendata.aws/sentinel-2-l2a-cogs",
    "Name": "Sentinel 2 L2A COGs",
    "SupportedFilters": [
        {
            "Maximum": 100,
            "Minimum": 0,
            "Name": "EoCloudCover",
            "Type": "number"
        },
        {
            "Maximum": 90,
            "Minimum": 0,
            "Name": "ViewOffNadir",
            "Type": "number"
        },
        {
            "Name": "Platform",
            "Type": "string"
        }
    ],
    "Tags": {},
    "Type": "PUBLIC"
}
```

Dopo aver eseguito l'esempio di codice precedente, otterrai l'ARN della raccolta dei dati raster Sentinel-2, `arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8`. Nella [sezione successiva](#demo-search-raster-data), puoi eseguire query sulla raccolta dei dati Sentinel-2 utilizzando l'API `search_raster_data_collection`.

## Ricerca nella raccolta dei dati raster di Sentinel-2 utilizzando `search_raster_data_collection`
<a name="demo-search-raster-data"></a>

Nella sezione precedente, hai utilizzato `list_raster_data_collections` per ottenere l'ARN per la raccolta dei dati di Sentinel-2. Ora puoi usare quell'ARN per cercare la raccolta dei dati su una determinata area di interesse (AOI), intervallo temporale, proprietà e bande UV disponibili.

Per chiamare l'API `search_raster_data_collection` devi inoltrare un Python dizionario al parametro `RasterDataCollectionQuery`. Questo esempio utilizza `AreaOfInterest`, `TimeRangeFilter`, `PropertyFilters` e `BandFilter`. Per semplicità, puoi specificare il dizionario Python usando la variabile **search\_rdc\_query** per contenere i parametri di query della ricerca:

```
search_rdc_query = {
    "AreaOfInterest": {
        "AreaOfInterestGeometry": {
            "PolygonGeometry": {
                "Coordinates": [
                    [
                        # coordinates are input as longitute followed by latitude 
                        [-114.529, 36.142],
                        [-114.373, 36.142],
                        [-114.373, 36.411],
                        [-114.529, 36.411],
                        [-114.529, 36.142],
                    ]
                ]
            }
        }
    },
    "TimeRangeFilter": {
        "StartTime": "2022-01-01T00:00:00Z",
        "EndTime": "2022-07-10T23:59:59Z"
    },
    "PropertyFilters": {
        "Properties": [
            {
                "Property": {
                    "EoCloudCover": {
                        "LowerBound": 0,
                        "UpperBound": 1
                    }
                }
            }
        ],
        "LogicalOperator": "AND"
    },
    "BandFilter": [
        "visual"
    ]
}
```

In questo esempio, esegui una query su un oggetto `AreaOfInterest` che include [Lago Mead](https://en.wikipedia.org/wiki/Lake_Mead) nello Utah. Inoltre, Sentinel-2 supporta diversi tipi di bande di immagini. Per misurare la variazione della superficie dell'acqua, è sufficiente la banda `visual`.

Dopo aver creato i parametri di query, puoi utilizzare l'API `search_raster_data_collection` per effettuare la richiesta. 

Il seguente esempio di codice implementa una richiesta API `search_raster_data_collection`. Questa API non supporta l'impaginazione tramite l'API `get_paginator`. Per assicurarsi che sia stata restituita la risposta API completa, l'esempio di codice utilizza un ciclo `while` per verificarne l'`NextToken`esistenza. L'esempio di codice viene quindi utilizzato `.extend()` per aggiungere l'immagine satellitare URLs e altri metadati di risposta a. `items_list` 

Per ulteriori informazioni`search_raster_data_collection`, consulta [SearchRasterDataCollection](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_geospatial_SearchRasterDataCollection.html)*Amazon SageMaker AI API Reference*.

```
search_rdc_response = 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
)


## items_list is the response from the API request. 
items_list = []

## Use the python .get() method to check that the 'NextToken' exists, if null returns None breaking the while loop 
while search_rdc_response.get('NextToken'):
    items_list.extend(search_rdc_response['Items'])
    search_rdc_response = 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_response['NextToken']
    )

## Print the number of observation return based on the query
print (len(items_list))
```

Di seguito è riportato un esempio di risposta JSON alla tua query. La risposta è stata troncata per maggiore chiarezza. Nella coppia chiave-valore `Assets` viene restituito solo il **"BandFilter": ["visual"]** specificato nella richiesta:

```
{
    'Assets': {
        'visual': {
            'Href': 'https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/15/T/UH/2022/6/S2A_15TUH_20220623_0_L2A/TCI.tif'
        }
    },
    'DateTime': datetime.datetime(2022, 6, 23, 17, 22, 5, 926000, tzinfo = tzlocal()),
    'Geometry': {
        'Coordinates': [
            [
                [-114.529, 36.142],
                [-114.373, 36.142],
                [-114.373, 36.411],
                [-114.529, 36.411],
                [-114.529, 36.142],
            ]
        ],
        'Type': 'Polygon'
    },
    'Id': 'S2A_15TUH_20220623_0_L2A',
    'Properties': {
        'EoCloudCover': 0.046519,
        'Platform': 'sentinel-2a'
    }
}
```

Ora che hai i risultati della tua query, puoi visualizzarli nella sezione successiva utilizzando `matplotlib`. Questo serve a verificare che i risultati provengano dalla regione geografica corretta. 

## Visualizzazione di `search_raster_data_collection` utilizzando `matplotlib`
<a name="demo-geospatial-visualize"></a>

Prima di iniziare il processo di osservazione della terra (EOJ), puoi visualizzare un risultato della query con`matplotlib`. Il seguente esempio di codice prende il primo elemento, `items_list[0]["Assets"]["visual"]["Href"]`, dalla variabile `items_list` creata nell'esempio di codice precedente e stampa un'immagine utilizzando `matplotlib`.

```
# Visualize an example image.
import os
from urllib import request
import tifffile
import matplotlib.pyplot as plt

image_dir = "./images/lake_mead"
os.makedirs(image_dir, exist_ok=True)

image_dir = "./images/lake_mead"
os.makedirs(image_dir, exist_ok=True)

image_url = items_list[0]["Assets"]["visual"]["Href"]
img_id = image_url.split("/")[-2]
path_to_image = image_dir + "/" + img_id + "_TCI.tif"
response = request.urlretrieve(image_url, path_to_image)
print("Downloaded image: " + img_id)

tci = tifffile.imread(path_to_image)
plt.figure(figsize=(6, 6))
plt.imshow(tci)
plt.show()
```

Dopo aver verificato che i risultati siano nella regione geografica corretta, puoi avviare il processo di osservazione della terra (EOJ) nella fase successiva. Si utilizza il processo EOJ per identificare i corpi idrici dalle immagini satellitari utilizzando un processo chiamato segmentazione del suolo.

## Avvio di un processo di osservazione della terra (EOJ) che esegue la segmentazione del suolo su una serie di immagini satellitari
<a name="demo-start-eoj"></a>

SageMaker geospatial fornisce diversi modelli pre-addestrati che puoi utilizzare per elaborare dati geospaziali da raccolte di dati raster. Per ulteriori informazioni sui modelli preaddestrati disponibili e sulle operazioni personalizzate, consulta [Tipi di operazioni](geospatial-eoj-models.md).

Per calcolare la variazione della superficie dell'acqua, devi identificare quali pixel delle immagini corrispondono all'acqua. La segmentazione della copertura del suolo è un modello di segmentazione semantica supportato dall'API `start_earth_observation_job`. I modelli di segmentazione semantica associano un'etichetta a ogni pixel di ogni immagine. Nei risultati, a ogni pixel viene assegnata un'etichetta basata sulla mappatura delle classi del modello. Di seguito è riportata la mappatura delle classi per il modello di segmentazione del suolo:

```
{
    0: "No_data",
    1: "Saturated_or_defective",
    2: "Dark_area_pixels",
    3: "Cloud_shadows",
    4: "Vegetation",
    5: "Not_vegetated",
    6: "Water",
    7: "Unclassified",
    8: "Cloud_medium_probability",
    9: "Cloud_high_probability",
    10: "Thin_cirrus",
    11: "Snow_ice"
}
```

Per avviare un processo di osservazione della terra, usa l'API `start_earth_observation_job`. Quando invii la richiesta, devi specificare quanto segue:
+ `InputConfig`(*dict*): utilizzato per specificare le coordinate dell'area in cui desideri cercare e altri metadati associati alla tua ricerca.
+ `JobConfig`(*dict*): utilizzato per specificare il tipo di operazione EOJ eseguita sui dati. Questo esempio usa **LandCoverSegmentationConfig**.
+ `ExecutionRoleArn`(*stringa*) — L'ARN del ruolo di esecuzione SageMaker AI con le autorizzazioni necessarie per eseguire il processo.
+ `Name`(*string*): un nome per il processo di osservazione della terra.

Il `InputConfig` è un Python dizionario. Utilizza la seguente variabile **eoj\_input\_config** per contenere i parametri di query della ricerca. Usa questa variabile quando effettui la richiesta API `start_earth_observation_job`.

```
# Perform land cover segmentation on images returned from the Sentinel-2 dataset.
eoj_input_config = {
    "RasterDataCollectionQuery": {
        "RasterDataCollectionArn": "arn:aws:sagemaker-geospatial:us-west-2:378778860802:raster-data-collection/public/nmqj48dcu3g7ayw8",
        "AreaOfInterest": {
            "AreaOfInterestGeometry": {
                "PolygonGeometry": {
                    "Coordinates":[
                        [
                            [-114.529, 36.142],
                            [-114.373, 36.142],
                            [-114.373, 36.411],
                            [-114.529, 36.411],
                            [-114.529, 36.142],
                        ]
                    ]
                }
            }
        },
        "TimeRangeFilter": {
            "StartTime": "2021-01-01T00:00:00Z",
            "EndTime": "2022-07-10T23:59:59Z",
        },
        "PropertyFilters": {
            "Properties": [{"Property": {"EoCloudCover": {"LowerBound": 0, "UpperBound": 1}}}],
            "LogicalOperator": "AND",
        },
    }
}
```

Il `JobConfig` è un Python dizionario che viene utilizzato per specificare l'operazione EOJ che desideri eseguire sui tuoi dati:

```
eoj_config = {"LandCoverSegmentationConfig": {}}
```

Con gli elementi del dizionario ora specificati, puoi inviare la tua richiesta API `start_earth_observation_job` utilizzando il seguente esempio di codice:

```
# Gets the execution role arn associated with current notebook instance 
execution_role_arn = sagemaker.get_execution_role()

# Starts an earth observation job
response = sm_geo_client.start_earth_observation_job(
    Name="lake-mead-landcover",
    InputConfig=eoj_input_config,
    JobConfig=eoj_config,
    ExecutionRoleArn=execution_role_arn,
)
            
print(response)
```

L'avvio di un processo di osservazione della terra restituisce un ARN insieme ad altri metadati.

Per ottenere un elenco di tutti i processi di osservazione della terra in corso e correnti, utilizza l'API `list_earth_observation_jobs`. Per monitorare lo stato di un singolo processo di osservazione della Terra, utilizza l'API `get_earth_observation_job`. Per effettuare questa richiesta, utilizza l'ARN creato dopo aver inviato la richiesta EOJ. Per ulteriori informazioni, [GetEarthObservationJob](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_geospatial_GetEarthObservationJob.html)consulta *Amazon SageMaker AI API Reference*.

Per trovare i dati ARNs associati alla tua, EOJs usa l'operazione `list_earth_observation_jobs` API. Per ulteriori informazioni, [ListEarthObservationJobs](https://docs.aws.amazon.com//sagemaker/latest/APIReference/API_geospatial_ListEarthObservationJobs.html)consulta *Amazon SageMaker AI API Reference*.

```
# List all jobs in the account
sg_client.list_earth_observation_jobs()["EarthObservationJobSummaries"]
```

Di seguito è riportato un esempio di risposta JSON:

```
{
    'Arn': 'arn:aws:sagemaker-geospatial:us-west-2:111122223333:earth-observation-job/futg3vuq935t',
    'CreationTime': datetime.datetime(2023, 10, 19, 4, 33, 54, 21481, tzinfo = tzlocal()),
    'DurationInSeconds': 3493,
    'Name': 'lake-mead-landcover',
    'OperationType': 'LAND_COVER_SEGMENTATION',
    'Status': 'COMPLETED',
    'Tags': {}
}, {
    'Arn': 'arn:aws:sagemaker-geospatial:us-west-2:111122223333:earth-observation-job/wu8j9x42zw3d',
    'CreationTime': datetime.datetime(2023, 10, 20, 0, 3, 27, 270920, tzinfo = tzlocal()),
    'DurationInSeconds': 1,
    'Name': 'mt-shasta-landcover',
    'OperationType': 'LAND_COVER_SEGMENTATION',
    'Status': 'INITIALIZING',
    'Tags': {}
}
```

Dopo che lo stato del tuo processo EOJ cambia in `COMPLETED`, passa alla sezione successiva per calcolare la variazione della superficie del lago Mead's .

## Calcolo della variazione della superficie nel lago Mead
<a name="demo-geospatial-calc"></a>

Per calcolare la variazione della superficie del lago Mead, esporta innanzitutto i risultati del processo EOJ su Amazon S3 utilizzando `export_earth_observation_job`:

```
sagemaker_session = sagemaker.Session()
s3_bucket_name = sagemaker_session.default_bucket()  # Replace with your own bucket if needed
s3_bucket = session.resource("s3").Bucket(s3_bucket_name)
prefix = "export-lake-mead-eoj"  # Replace with the S3 prefix desired
export_bucket_and_key = f"s3://{s3_bucket_name}/{prefix}/"

eoj_output_config = {"S3Data": {"S3Uri": export_bucket_and_key}}
export_response = sm_geo_client.export_earth_observation_job(
    Arn="arn:aws:sagemaker-geospatial:us-west-2:111122223333:earth-observation-job/7xgwzijebynp",
    ExecutionRoleArn=execution_role_arn,
    OutputConfig=eoj_output_config,
    ExportSourceImages=False,
)
```

Per visualizzare lo stato del tuo processo di esportazione, utilizza `get_earth_observation_job`:

```
export_job_details = sm_geo_client.get_earth_observation_job(Arn=export_response["Arn"])
```

Per calcolare le variazioni del livello dell'acqua del Lago Mead, scarica le maschere di copertura del terreno sull'istanza del SageMaker notebook locale e scarica le immagini di origine dalla nostra query precedente. Nella mappatura delle classi per il modello di segmentazione del suolo, l'indice di classe dell'acqua è 6.

Per estrarre da un'immagine Sentinel-2 il file maschera relativo all’acqua, segui questa procedura. Innanzitutto, conta nell'immagine il numero di pixel contrassegnati come acqua (indice di classe 6). In secondo luogo, moltiplica il conteggio per l'area coperta da ciascun pixel. Le bande possono differire in termini di risoluzione spaziale. Per il modello di segmentazione della copertura del suolo, tutte le bande vengono sottocampionate con una risoluzione spaziale pari a 60 metri.

```
import os
from glob import glob
import cv2
import numpy as np
import tifffile
import matplotlib.pyplot as plt
from urllib.parse import urlparse
from botocore import UNSIGNED
from botocore.config import Config

# Download land cover masks
mask_dir = "./masks/lake_mead"
os.makedirs(mask_dir, exist_ok=True)
image_paths = []
for s3_object in s3_bucket.objects.filter(Prefix=prefix).all():
    path, filename = os.path.split(s3_object.key)
    if "output" in path:
        mask_name = mask_dir + "/" + filename
        s3_bucket.download_file(s3_object.key, mask_name)
        print("Downloaded mask: " + mask_name)

# Download source images for visualization
for tci_url in tci_urls:
    url_parts = urlparse(tci_url)
    img_id = url_parts.path.split("/")[-2]
    tci_download_path = image_dir + "/" + img_id + "_TCI.tif"
    cogs_bucket = session.resource(
        "s3", config=Config(signature_version=UNSIGNED, region_name="us-west-2")
    ).Bucket(url_parts.hostname.split(".")[0])
    cogs_bucket.download_file(url_parts.path[1:], tci_download_path)
    print("Downloaded image: " + img_id)

print("Downloads complete.")

image_files = glob("images/lake_mead/*.tif")
mask_files = glob("masks/lake_mead/*.tif")
image_files.sort(key=lambda x: x.split("SQA_")[1])
mask_files.sort(key=lambda x: x.split("SQA_")[1])
overlay_dir = "./masks/lake_mead_overlay"
os.makedirs(overlay_dir, exist_ok=True)
lake_areas = []
mask_dates = []

for image_file, mask_file in zip(image_files, mask_files):
    image_id = image_file.split("/")[-1].split("_TCI")[0]
    mask_id = mask_file.split("/")[-1].split(".tif")[0]
    mask_date = mask_id.split("_")[2]
    mask_dates.append(mask_date)
    assert image_id == mask_id
    image = tifffile.imread(image_file)
    image_ds = cv2.resize(image, (1830, 1830), interpolation=cv2.INTER_LINEAR)
    mask = tifffile.imread(mask_file)
    water_mask = np.isin(mask, [6]).astype(np.uint8)  # water has a class index 6
    lake_mask = water_mask[1000:, :1100]
    lake_area = lake_mask.sum() * 60 * 60 / (1000 * 1000)  # calculate the surface area
    lake_areas.append(lake_area)
    contour, _ = cv2.findContours(water_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    combined = cv2.drawContours(image_ds, contour, -1, (255, 0, 0), 4)
    lake_crop = combined[1000:, :1100]
    cv2.putText(lake_crop, f"{mask_date}", (10,50), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 0, 0), 3, cv2.LINE_AA)
    cv2.putText(lake_crop, f"{lake_area} [sq km]", (10,100), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 0, 0), 3, cv2.LINE_AA)
    overlay_file = overlay_dir + '/' + mask_date + '.png'
    cv2.imwrite(overlay_file, cv2.cvtColor(lake_crop, cv2.COLOR_RGB2BGR))

# Plot water surface area vs. time.
plt.figure(figsize=(20,10))
plt.title('Lake Mead surface area for the 2021.02 - 2022.07 period.', fontsize=20)
plt.xticks(rotation=45)
plt.ylabel('Water surface area [sq km]', fontsize=14)
plt.plot(mask_dates, lake_areas, marker='o')
plt.grid('on')
plt.ylim(240, 320)
for i, v in enumerate(lake_areas):
    plt.text(i, v+2, "%d" %v, ha='center')
plt.show()
```

Utilizzando `matplotlib`, puoi visualizzare i risultati su un grafico. Il grafico mostra che la superficie del lago Mead è diminuita da gennaio 2021 a luglio 2022.

![Un istogramma che mostra che la superficie del lago Mead è diminuita da gennaio 2021 a luglio 2022](http://docs.aws.amazon.com/it_it/sagemaker/latest/dg/images/lake-mead-decrease.png)
