Share via


Zelfstudie: De Microsoft Planetary Computer Pro API's gebruiken om gegevens op te nemen en te visualiseren

STAC-verzamelingen (SpatioTemporal Asset Catalog) worden in een GeoCatalog gebruikt om gerelateerde spatiotemporale assets te indexeren en op te slaan. In deze end-to-end handleiding maakt u een nieuwe STAC-collectie, neemt u Sentinel-2-afbeeldingen op in de collectie, en bevraagt u deze afbeeldingen via de API's van GeoCatalog.

In deze handleiding leert u:

  • Zal je eigen STAC-verzameling maken binnen een Planetary Computer Pro GeoCatalog.
  • Satellietbeelden opnemen in die verzameling van het Europees Ruimteagentschap
  • Configureer de verzameling zodat de afbeeldingen in de verzameling kunnen worden gevisualiseerd in de webinterface van Planetary Computer Pro
  • Query's uitvoeren op gegevens uit de STAC-verzameling met behulp van de STAC-API van Planetary Computer Pro

In deze zelfstudie worden mogelijkheden getoond en uitgelegd via codefragmenten, voor een interactieve ervaring in de stijl van een notebook, downloadt u deze zelfstudie als een Jupyter-notebook.

Vereiste voorwaarden

Voordat u deze zelfstudie uitvoert, hebt u een Planetary Computer Pro GeoCatalog nodig die is geïmplementeerd in uw Azure-abonnement. U hebt ook een omgeving nodig om dit notebook uit te voeren en de benodigde pakketten te installeren. We raden u aan deze zelfstudie uit te voeren via een azure Machine Learning Virtual Machine of de notebookintegratie van Visual Studio Code in een virtuele Python-omgeving. Dit notebook moet echter worden uitgevoerd waar u Jupyter-notebooks kunt uitvoeren, mits aan de volgende vereisten wordt voldaan:

  • Python 3.10 of hoger
  • Azure CLI is geïnstalleerd en u hebt az login uitgevoerd om u aan te melden bij uw Azure-account
  • De noodzakelijke vereisten die worden vermeld in de sectie Handleidingopties zijn geïnstalleerd

Een Jupyter-notebook openen in Azure Machine Learning of VS Code

Aanmelden bij Azure met de Azure CLI

Met de volgende opdracht wordt u in Azure aangemeld met behulp van de Azure CLI. Voer de opdracht uit en volg de instructies om u aan te melden.

!az login

Zelfstudieopties selecteren

Voordat u deze zelfstudie uitvoert, hebt u inzendertoegang nodig tot een bestaand GeoCatalog-exemplaar. Voer de URL in van uw GeoCatalog-exemplaar in de variabele geocatalog_url. In deze handleiding maakt u een verzameling voor Sentinel-2-afbeeldingen geleverd door de Europese Ruimtevaartorganisatie (ESA) die momenteel is opgeslagen in de Planetary Computer Data Catalog van Microsoft.

# URL for your given GeoCatalog
geocatalog_url = (
    "<GEOCATALOG_URL>"
)
geocatalog_url = geocatalog_url.rstrip("/")  # Remove trailing slash if present

api_version = "2025-04-30-preview"

# User selections for demo

# Collection within the Planetary Computer
pc_collection = "sentinel-2-l2a"

# Bounding box for AOI
bbox_aoi = [-22.455626, 63.834083, -22.395201, 63.880750]

# Date range to search for imagery
param_date_range = "2024-02-04/2024-02-11"

# Maximum number of items to ingest
param_max_items = 6

De vereiste pakketten importeren

Voordat u een STAC-verzameling kunt maken, moet u enkele Python-pakketten importeren en helperfuncties definiëren om het vereiste toegangstoken op te halen.

pip install pystac-client azure-identity requests pillow
# Import the required packages
import json
import random
import string
import time
from datetime import datetime, timedelta, timezone
from io import BytesIO
from typing import Any, Optional, Dict

import requests
from azure.identity import AzureCliCredential
from IPython.display import Markdown as md
from IPython.display import clear_output
from PIL import Image
from pystac_client import Client

# Function to get a bearer token for the  Planetary Computer Pro API
MPC_APP_ID = "https://geocatalog.spatio.azure.com"

_access_token = None
def getBearerToken():
    global _access_token
    if not _access_token or datetime.fromtimestamp(_access_token.expires_on) < datetime.now() + timedelta(minutes=5):
        credential = AzureCliCredential()
        _access_token = credential.get_token(f"{MPC_APP_ID}/.default")

    return {"Authorization": f"Bearer {_access_token.token}"}

# Method to print error messages when checking response status
def raise_for_status(r: requests.Response) -> None:
    try:
        r.raise_for_status()
    except requests.exceptions.HTTPError as e:
        try:
            print(json.dumps(r.json(), indent=2))
        except:
            print(r.content)
        finally:
            raise

Een STAC-verzameling maken

Een JSON voor de STAC-verzameling definiëren

Vervolgens definieert u een STAC-verzameling als een JSON-item. Gebruik voor deze zelfstudie een bestaande STAC-verzameling JSON voor de Sentinel-2-l2a-verzameling binnen de Planetaire Computer van Microsoft. Aan uw verzameling wordt een willekeurige id en titel toegewezen, zodat deze niet conflicteert met andere bestaande verzamelingen.

# Load example STAC collection JSON

response = requests.get(
    f"https://planetarycomputer.microsoft.com/api/stac/v1/collections/{pc_collection}"
)
raise_for_status(response)
stac_collection = response.json()

collection_id = pc_collection + "-tutorial-" + str(random.randint(0, 1000))

# Genereate a unique name for the test collection
stac_collection["id"] = collection_id
stac_collection["title"] = collection_id

# Determine the storage account and container for the assets
pc_storage_account = stac_collection.pop("msft:storage_account")
pc_storage_container = stac_collection.pop("msft:container")
pc_collection_asset_container = (
    f"https://{pc_storage_account}.blob.core.windows.net/{pc_storage_container}"
)

# View your STAC collection JSON
stac_collection

Bij het maken van een verzameling in GeoCatalog kan een JSON-verzameling geen activa op verzamelingsniveau (zoals een miniatuur van een verzameling) hebben die aan de verzameling zijn gekoppeld, dus verwijder eerst die bestaande assets (u hoeft de miniatuur later niet meer toe te voegen).

# Save the thumbnail url
thumbnail_url = stac_collection['assets']['thumbnail']['href']

# Remove the assets field from the JSON (you'll see how to add this back later)
print("Removed the following items from the STAC Collection JSON:")
stac_collection.pop('assets')
# Create a STAC collection by posting to the STAC collections API

collections_endpoint = f"{geocatalog_url}/stac/collections"

response = requests.post(
    collections_endpoint,
    json=stac_collection,
    headers=getBearerToken(),
    params={"api-version": api_version}
)

if response.status_code==201:
    print("STAC Collection created named:",stac_collection['title'])
else:
    raise_for_status(response)

Open uw GeoCatalog-webinterface en u ziet dat uw nieuwe verzameling wordt vermeld op het tabblad Verzamelingen.

Miniatuur van de Access-collectie

Vervolgens wilt u een miniatuur toevoegen aan onze verzameling die samen met onze verzameling moet worden weergegeven. Gebruik voor deze demo de miniatuur van de bestaande Sentinel-2-verzameling in de Planetaire Computer van Microsoft.

# Read thumbnail for your collection

thumbnail_response = requests.get(thumbnail_url)
raise_for_status(thumbnail_response)
img = Image.open(BytesIO(thumbnail_response.content))
img

Miniatuur toevoegen aan uw Planetary Computer Pro GeoCatalog

Nadat u de miniatuur hebt gelezen, kunt u deze toevoegen aan onze verzameling door deze samen met de vereiste asset-json te plaatsen op het API-eindpunt van uw GeoCatalogs-verzameling.

# Define the GeoCatalog collections API endpoint
collection_assets_endpoint = f"{geocatalog_url}/stac/collections/{collection_id}/assets"

# Read the example thumbnail from this collection from the Planetary Computer
thumbnail = {"file": ("lulc.png", thumbnail_response.content)}

# Define the STAC collection asset type - thumbnail in this case
asset = {
    "data": '{"key": "thumbnail", "href":"", "type": "image/png", '
    '"roles":  ["test_asset"], "title": "test_asset"}'
}

# Post the thumbnail to the GeoCatalog collections asset endpoint
response = requests.post(
    collection_assets_endpoint,
    data=asset,
    files=thumbnail,
    headers=getBearerToken(),
    params={"api-version": api_version}
)

if response.status_code==201:
    print("STAC Collection thumbnail updated for:",stac_collection['title'])
else:
    raise_for_status(response)

Nieuwe verzameling lezen vanuit uw Planetaire Computer Pro GeoCatalog

Vernieuw uw browser en u zou de miniatuur moeten kunnen zien. U kunt de verzameling JSON ook programmatisch ophalen door de volgende aanroep uit te voeren naar het eindpunt van de verzameling:

# Request the collection JSON from your GeoCatalog
collection_endpoint = f"{geocatalog_url}/stac/collections/{stac_collection['id']}"

response = requests.get(
    collection_endpoint,
    json={'collection_id':stac_collection['id']},
    headers=getBearerToken(),
    params={"api-version": api_version}
)

if response.status_code==200:
    print("STAC Collection successfully read:",stac_collection['title'])
else:
    raise_for_status(response)

response.json()
print(f"""
You successfully created a new STAC Collection in GeoCatalog named {collection_id}.
You can view your collection by visiting the GeoCatalog Explorer: {geocatalog_url}/collections
""")

STAC-items en -assets opnemen

Nadat u deze verzameling hebt gemaakt, kunt u nieuwe STAC-items opnemen in uw STAC-verzameling met behulp van de Items-API van uw GeoCatalog. Dit proces uitvoeren door:

  1. Een SAS-token verkrijgen van de Planetaire Computer van Microsoft
  2. Dat token registreren als een opnamebron in GeoCatalog
  3. Plaats STAC-items uit die verzameling in de Item-API van GeoCatalog.
  4. Controleren of de items succesvol zijn ingevoerd
ingestion_sources_endpoint = f"{geocatalog_url}/inma/ingestion-sources"
ingestion_source_endpoint = lambda id: f"{geocatalog_url}/inma/ingestion-sources/{id}"


def find_ingestion_source(container_url: str) -> Optional[Dict[str, Any]]:

    response = requests.get(
        ingestion_sources_endpoint,
        headers=getBearerToken(),
        params={"api-version": api_version},
    )

    for source in response.json()["value"]:
        ingestion_source_id = source["id"]

        response = requests.get(
            ingestion_source_endpoint(ingestion_source_id),
            headers=getBearerToken(),
            params={"api-version": api_version},
        )
        raise_for_status(response)

        response = response.json()

        if response["connectionInfo"]["containerUrl"] == container_url:
            return response


def create_ingestion_source(container_url: str, sas_token: str):
    response = requests.post(
        ingestion_sources_endpoint,
        json={
            "kind": "SasToken",
            "connectionInfo": {
                "containerUrl": container_url,
                "sasToken": sas_token,
            },
        },
        headers=getBearerToken(),
        params={"api-version": api_version},
    )
    raise_for_status(response)


def remove_ingestion_source(ingestion_source_id: str):
    response = requests.delete(
        ingestion_source_endpoint(ingestion_source_id),
        headers=getBearerToken(),
        params={"api-version": api_version},
    )
    raise_for_status(response)

Query's uitvoeren op de planetaire computer

Eerst moet u een query uitvoeren op de Planetaire Computer om te zoeken naar Sentinel-2-afbeeldingen die voldoen aan onze specifieke vereisten. In dit geval zoekt u naar Sentinel-2 beelden in de Planetaire Computer die voldoet aan de volgende criteria:

  • Verzameling - Afbeeldingen uit de Sentinel-2-l2a collectie
  • Tijdsbereik - Verzameld tussen 4 februari en 11 februari 2024
  • Interesse-gebied - Afbeeldingen verzameld over zuid-IJsland (gedefinieerd als grenskaart)

Door deze zoekopdracht uit te voeren, kunt u de overeenkomende STAC-items in de Planetaire Computer vinden.

# Search criteria
print("Using the below parameters to search the Planetary Computer:\n")
print("Collection:", pc_collection)
print("Bounding box for area of interest:",bbox_aoi)
print("Date range:",param_date_range)
print("Max number of items:",param_max_items)
# Query the Planetary Computer

# Connect to the Planetary Computer
catalog = Client.open("https://planetarycomputer.microsoft.com/api/stac/v1")

search = catalog.search(collections=[pc_collection], bbox=bbox_aoi, datetime=param_date_range)
total_items = search.item_collection()

items = total_items[:param_max_items]
print("Total number of matching items:",len(total_items))
print("Total number of items for ingest base on user selected parameter:",len(items))

if total_items==0:
    print("No items matched your user specified parameters used at the top of this demo. Update these parameters")
# Print an example STAC item returned by the Planetary Computer
items[0]

Een invoerbron registreren

Voordat u deze STAC-items en de bijbehorende assets (afbeeldingen) kunt opnemen in een GeoCatalog-verzameling, moet u bepalen of u een nieuwe opnamebron moet registreren. Opnamebronnen worden door GeoCatalog gebruikt om bij te houden tot welke opslaglocaties (Azure Blob Storage-containers) deze toegang heeft.

Het registreren van een opnamebron wordt bereikt door GeoCatalog de locatie van de opslagcontainer en een SAS-token met leesmachtigingen voor toegang tot de container op te geven. Als de STAC-items en de bijbehorende assets zich in een opslagcontainer bevinden waar uw GeoCatalog geen toegang tot heeft gekregen, zal de invoer mislukken.

Om dit proces te starten, vraagt u eerst een SAS-token aan bij de Planetaire Computer die ons leestoegang geeft tot de container waarin de Sentinel-2-installatiekopieën zich bevinden.

# Request API token from the Planetary Computer

pc_token = requests.get("https://planetarycomputer.microsoft.com/api/sas/v1/token/{}".format(pc_collection)).json()
print(f"Planetary Computer API Token will expire {pc_token['msft:expiry']}")

Vervolgens probeert u deze Azure Blob Storage-container en het bijbehorende SAS-token te registreren als een opnamebron met GeoCatalog. Er bestaat mogelijk al een opnamebron voor deze opslagcontainer. Als dat zo is, zoekt u de ID van de bestaande opnamebron.

Waarschuwing

Als er een dubbele opnamebron wordt gevonden met een token dat in de komende 15 minuten verloopt, wordt deze verwijderd en vervangen. Als u een invoerbron verwijdert die momenteel wordt gebruikt door lopende invoeringen, kunnen die invoeringen worden verbroken.

existing_ingestion_source: Optional[Dict[str, Any]] = find_ingestion_source(pc_collection_asset_container)

if existing_ingestion_source:
    connection_info = existing_ingestion_source["connectionInfo"]
    expiration = datetime.fromisoformat(connection_info["expiration"].split('.')[0]) # works in all Python 3.X versions
    expiration = expiration.replace(tzinfo=timezone.utc) # set timezone to UTC
    if expiration < datetime.now(tz=timezone.utc) + timedelta(minutes=15):
        print(f"Recreating existing ingestion source for {pc_collection_asset_container}")
        remove_ingestion_source(existing_ingestion_source["id"])
        create_ingestion_source(pc_collection_asset_container, pc_token["token"])
    else:
        print(f"Using existing ingestion source for {pc_collection_asset_container} with expiration {expiration}")
else:
    print(f"Creating ingestion source for {pc_collection_asset_container}")
    create_ingestion_source(pc_collection_asset_container, pc_token["token"])

STAC-items opnemen met behulp van de Items-API van GeoCatalog

Nu u een opnamebron hebt geregistreerd of hebt gevalideerd dat er een bron bestaat, neemt u de STAC-items op die u in de Planetaire computer hebt gevonden met behulp van de Items-API van GeoCatalog. U doet dit door elk item te posten in de Items-API, waarmee een nieuwe opnamebewerking wordt gemaakt in GeoCatalog.

# Ingest items

items_endpoint = f"{geocatalog_url}/stac/collections/{collection_id}/items"

operation_ids = []

for item in items:

    item_json = item.to_dict()
    item_json['collection'] = collection_id

    # Remove non-static assets
    del(item_json['assets']['rendered_preview'])
    del(item_json['assets']['preview'])
    del(item_json['assets']['tilejson'])

    response = requests.post(
        items_endpoint,
        json=item_json,
        headers=getBearerToken(),
        params={"api-version": api_version}
    )

    operation_ids.append(response.json()['id'])
    print(f"Ingesting item {item_json['id']} with operation id {response.json()['id']}")

Aangezien het opnemen van sentinel-2-items enige tijd kan duren, kunt u deze code uitvoeren om de status van uw opnamebewerkingen te controleren met behulp van de Operations-API van GeoCatalog.

# Check the status of the operations
operations_endpoint = f"{geocatalog_url}/inma/operations"
# Loop through all the operations ids until the status of each operation ids is "Finished"
pending=True

start = time.time()

while pending:
    # Count the number of operation ids that are finished vs unfinished
    num_running = 0
    num_finished = 0
    num_failed = 0
    clear_output(wait=True)
    for operation_id in operation_ids:
        response = requests.get(
            f"{operations_endpoint}/{operation_id}",
            headers=getBearerToken(),
            params={"api-version": api_version},
        )
        raise_for_status(response)
        status = response.json()["status"]
        print(f"Operation id {operation_id} status: {status}")
        if status == "Running":
            num_running+=1
        elif status == "Failed":
            num_failed+=1
        elif status == "Succeeded":
            num_finished+=1
    
    num_running
    stop=time.time()
    # Print the sumary of num finished, num running and num failed
    
    print("Ingesting Imagery:")
    print(f"\tFinished: {num_finished}\n\tRunning: {num_running}\n\tFailed: {num_failed}")
    print("Time Elapsed (seconds):",str(stop-start))
    
    if num_running == 0:
        pending=False
        print(f"Ingestion Complete!\n\t{num_finished} items ingested.\n\t{num_failed} items failed.")

    else:
        print(f"Waiting for {num_running} operations to finish")
        time.sleep(5)

U moet uw webbrowser kunnen vernieuwen en op het tabblad Items klikken om deze zojuist geüploade items weer te geven.

Verzamelingsbeheer

Nu u deze STAC-items en de bijbehorende assets (afbeeldingen) hebt opgenomen in de STAC-verzameling, moet u uw GeoCatalog met enkele andere configuratiebestanden opgeven voordat u deze items in de geocatalog-webinterface kunt visualiseren.

Instellingen voor weergave van collecties

Download eerst een renderconfiguratiebestand voor deze verzameling van de Planetaire Computer. Dit configuratiebestand kan worden gelezen door GeoCatalog om afbeeldingen op verschillende manieren weer te geven in de Explorer. Dit komt doordat STAC-items veel verschillende assets (afbeeldingen) kunnen bevatten die kunnen worden gecombineerd om volledig nieuwe afbeeldingen te maken van een bepaald gebied waarin zichtbare of niet-zichtbare functies worden gemarkeerd. Zo hebben Sentinel-2 STAC-items meer dan 12 verschillende beelden van verschillende delen van het elektromagnetische spectrum. Met deze weergaveconfiguratie wordt GeoCatalog geïnstrueerd over het combineren van deze afbeeldingen, zodat afbeeldingen kunnen worden weergegeven in Natuurlijke kleur of Onwaarkleur (Kleur infrarood).

# Read render JSON from Planetary Computer

render_json = requests.get("https://planetarycomputer.microsoft.com/api/data/v1/mosaic/info?collection={}".format(pc_collection)).json()
render_json['renderOptions']

Na het lezen van deze renderoptiesconfiguratie uit de Planetary Computer, kunt u deze renderopties voor de verzameling inschakelen door deze configuratie te versturen naar het eindpunt voor renderopties.

# Post render options config to GeoCatalog render-options API

render_config_endpoint = f"{geocatalog_url}/stac/collections/{collection_id}/configurations/render-options"

for render_option in render_json['renderOptions']:

    # Rename render configs such that they can be stored by GeoCatalog
    render_option['id'] = render_option['name'].translate(str.maketrans('', '', string.punctuation)).lower().replace(" ","-")[:30]

    # Post render definition
    response = requests.post(
        render_config_endpoint,
        json=render_option,
        headers=getBearerToken(),
        params={"api-version": api_version}
    )

Mozaïekdefinities

Net als bij de renderconfiguratie die hierboven is besproken, kunnen we met GeoCatalog's Explorer een of meer mozaïekdefinities voor de verzameling opgeven. Met deze mozaïekdefinities kunnen we de Verkenner van GeoCatalog instrueren over het filteren van de items die worden weergegeven in de Verkenner. Met een eenvoudige weergaveconfiguratie (weergegeven in de volgende cel) wordt geocatalog bijvoorbeeld geïnstrueerd om de meest recente afbeelding voor een bepaald gebied weer te geven. Met geavanceerdere renderconfiguraties kunnen we verschillende weergaven weergeven, zoals de minst bewolkte afbeelding voor een bepaalde locatie die in oktober 2023 is vastgelegd.

# Post mosaic definition

mosiacs_config_endpoint = f"{geocatalog_url}/stac/collections/{collection_id}/configurations/mosaics"

response = requests.post(
    mosiacs_config_endpoint,
    json={"id": "mos1",
          "name": "Most recent available",
          "description": "Most recent available imagery in this collection",
          "cql": []
    },
    headers=getBearerToken(),
    params={"api-version": api_version}
)

GeoCatalog-webinterface openen

Congrats! U hebt een verzameling gemaakt, STAC-items en -assets toegevoegd en uw verzameling bijgewerkt om de vereiste configuratiebestanden op te nemen, zodat deze kan worden weergegeven via de Explorer in de webinterface van GeoCatalog.

Ga terug naar GeoCatalog Explorer in de webinterface om uw verzameling weer te geven.

Queryverzameling via STAC API

Nu u uw verzameling hebt bekeken in GeoCatalog Explorer, leert u hoe u de STAC-API's van GeoCatalog kunt gebruiken om STAC-items en -assets te zoeken en op te halen voor verdere analyse.

Dit proces begint met het plaatsen van een zoekopdracht naar de STAC API van uw GeoCatalog. Specifiek zoekt u naar afbeeldingen in uw verzameling die binnen het oorspronkelijke begrenzingsvak vallen dat u hebt gebruikt om afbeeldingen uit de Planetaire Computer te extraheren.

Deze query retourneert waarschijnlijk alle STAC-items die u eerder in uw verzameling hebt geplaatst.

stac_search_endpoint = f"{geocatalog_url}/stac/search"

response = requests.post(
    stac_search_endpoint,
    json={"collections":[collection_id],
          "bbox":bbox_aoi
    },
    headers=getBearerToken(),
    params={"api-version": api_version, "sign": "true"}
)

matching_items = response.json()['features']
print(len(matching_items))

In uw vorige query hebt u ook een andere parameter opgegeven: sign:true. Hiermee wordt GeoCatalog geïnstrueerd om een ondertekend href (item href + SAS-token) te retourneren waarmee u de opgegeven assets uit Azure Blob Storage kunt lezen.

# Download one of the assets bands, band 09
asset_href = matching_items[0]['assets']['B09']['href']
print(asset_href)

response = requests.get(asset_href)
img = Image.open(BytesIO(response.content))
img

De hulpbronnen opschonen

Items verwijderen

Op dit moment hebt u een GeoCatalog-verzameling gemaakt, items en assets toegevoegd aan de verzameling en deze items en assets opgehaald met behulp van de STAC-API van GeoCatalog. Voor de laatste fase van deze zelfstudie gaat u deze items verwijderen en uw verzameling verwijderen.

# Delete all items

for item in matching_items:
    response = requests.delete(
        f"{items_endpoint}/{item['id']}",
        headers=getBearerToken(),
        params={"api-version": api_version}
    )

U kunt controleren of al uw items zijn verwijderd door de volgende opdracht uit te voeren. Houd er rekening mee dat het enkele minuten kan duren voordat items en de bijbehorende assets volledig zijn verwijderd.

# Confirm that all the items have been deleted
response = requests.post(
    stac_search_endpoint,
    json={"collections":[stac_collection['id']],
          "bbox": bbox_aoi
    },
    headers=getBearerToken(),
    params={"api-version": api_version, "sign": "true"}
)

matching_items = response.json()['features']
print(len(matching_items))

Verzameling verwijderen

Als laatste stap wilt u mogelijk uw verzameling volledig verwijderen uit uw GeoCatalog-exemplaar.

# Delete the collection
response = requests.delete(
    f"{collections_endpoint}/{collection_id}",
    headers=getBearerToken(),
    params={"api-version": api_version}
)

raise_for_status(response)
print(f"STAC Collection deleted: {collection_id}")

Volgende stappen

In deze van begin tot eind handleiding hebt u het proces doorlopen voor het maken van een nieuwe STAC-verzameling, het opnemen van Sentinel-2-afbeeldingen in de verzameling en het opvragen van deze afbeeldingen via de API's van GeoCatalog. Als u meer wilt weten over elk van deze onderwerpen, bekijkt u deze andere materialen: