Solved

Download and crop an image using the API and gdalwrap in python

  • 27 July 2023
  • 1 reply
  • 183 views

Badge

Apologize for the question but i am a beginner in programming.
I am trying to write a script in Python and automatically download and crop a specific area using gdalwarp (I tried with the clip tool without success: https://developers.planet.com/apis/orders/tools/#using-tools).
Although being able to get a clipped image, this is simply a black thumbnail (840KB).
The final goal would be just to download the cropped part.
At the moment I am downloading the full image and it creates the thumbnail mentioned above.
The coordinates were extracted with the geojson.io tool

Could be the problem related with the coordinate system (although the clipped image is quite small and let me think the issue is something else).

 

Could you please advice what am I doing wrong?

 

Below the code section:

# Clip the image using gldalwarp
clip_output_image = os.path.join(save_folder, "clipped_" + filename)
input_coordinates = "33.282952632083095, 34.94060635659089, 33.282952632083095, 34.94060635659089"

# Define the target coordinate system (UTM 36N)
target_srs = "EPSG:32636"

# Check if the file already exists, if yes, skip the clipping step
if os.path.exists(clip_output_image):
print("Clipped image already exists. Skipping gdalwarp.")
else:
cmd = [
gdalwarp_path,
"-te", *input_coordinates.split(","),
"-ts", "1000", "1000",
"-t_srs", target_srs, # Specify the target UTM coordinate system
save_path,
clip_output_image
]

# Construct the gdalwarp command
cmd = f"gdalwarp -te {input_coordinates} -ts 1000 1000 -t_srs {target_srs} {save_path} {clip_output_image}"

try:
# Execute the gdalwarp command using subprocess
exit_code = subprocess.run(cmd, check=True)
if exit_code.returncode == 0:
# gdalwarp command executed successfully
print("Image clipped and saved to:", clip_output_image)
else:
# gdalwarp command failed
print("gdalwarp command execution failed.")
except subprocess.CalledProcessError as e:
# Handle the error if the command fails
print(f"Error occurred while executing gdalwarp command: {e}")
print("Image was not clipped.")

 

icon

Best answer by Miguel Castro Gomez 27 July 2023, 11:27

View original

1 reply

Badge +4

Hi @Dante Abate,

Have you tried ordering your image using Planet’s Order API. As you mentioned, it includes the possibility to pass tools, amongst them clipping the image to an AOI.

Find below a code example for that:

First load some python modules, set your Planet API Key and create a session

# Load modules
import os
import json
import pathlib
import requests

# Define your Planet API Key
if os.environ.get('PL_API_KEY', ''):
    PLANET_API_KEY = os.environ.get('PL_API_KEY', '')
else:
    PLANET_API_KEY = 'PASTE_YOUR_API_KEY_HERE'
     
# Create a session with your credentials
session = requests.Session()
session.auth = (PLANET_API_KEY, "")

Next, load your AOI (should be in EPSG:4326 - WGS 84)

geojson_files = "/path/to/your/aoi.geojson"

with open(geojson_files) as f:
geojson_data = json.loads(f.read())

Third, define your order payload, including the clipping tool

order_payload = {
    "name": "order_products",
    "products": [{
        "item_ids": [‘YOUR PRODUCT ID’], # if you have several, expand the list [‘id1’, ‘id2’, ‘id3’]
        "item_type": 'PSScene',
        "product_bundle": 'analytic_sr_udm2' # set the bundle you want
    }],
    "tools": [
        {
            "clip": {
                "aoi": geojson_data["features"][0]["geometry"]
            }
        }
    ]
}

Finally, send the request for your image(s)

# Define url for orders api
order_url = "https://api.planet.com/compute/ops/orders/v2"

# Send request
order_response = session.post(order_url, json=order_payload)
print('Order status code:', order_response.status_code)
print('Order ID:', order_response.json()['id'], '\n')

Once the order is ready to be downloaded, you can easily do so as follows:
Get the results:

order_id_url = order_url + order_response.json()['id']

r = session.get(order_id_url)
response = r.json()
results = response['_links']['results']
[r['name'] for r in results]

Define a function to handle the download:

def download_results(results, overwrite=False):
results_urls = [r['location'] for r in results]
results_names = [r['name'] for r in results]
print('{} items to download'.format(len(results_urls)))

for url, name in zip(results_urls, results_names):
path = pathlib.Path(os.path.join('data', name))

if overwrite or not path.exists():
print('downloading {} to {}'.format(name, path))
r = requests.get(url, allow_redirects=True)
path.parent.mkdir(parents=True, exist_ok=True)
open(path, 'wb').write(r.content)
else:
print('{} already exists, skipping {}'.format(path, name))

Download the results: 

download_results(results)

Hope it helps,

Miguel

Reply