Basics of Satellite Imagery Analysis, Part2

Prathyash Joy Binu
4 min readJul 5, 2023

--

In the article, we will be focusing on the hands-on experience in processing satellite imagery using Python for Computer vision tasks

Satellite Imagery can be assosicated with various applications like, crop monitoring, mineral exploration, urban planning, etc. Processing these types of images for computer vision tasks is not easy as you think when compared to normal RGB images. Before the action, I recommend you guys read the article regarding the theory and concepts of satellite imagery and its working.

Note: The image that we are going to deal with here consist of more than 3 channel. So Image processing and analysis are entirely different from the way that we commonly do it in computer vision applications.

Here let’s split the whole process into different modules.

  1. Package Installation

2. Download the Image

3. Image Processing

4. Image Analysis

Installations

Please install the Python packages either in the local machine or use it in google colab, if you are going with online editors rather than local machines

pip install rasterio
pip install sentinelsat
pip install geopandas
pip install matplotlib

#(Install GDAL with conda forge command )
pip install GDAL

Where is our Image?

Our first step is to download the image. In the previous article, it is mentioned that we commonly use images from Landsat and Sentinal Satellites. For downloading the image there are some open source APIs are available, with some limitations at free quota.

API Sources: https://scihub.copernicus.eu/twiki/do/view/SciHubWebPortal/APIHubDescription

https://www.sentinel-hub.com/develop/api/

We will be using the Copernicus open-access hub to download the Sentinal Images. The Sentinel-2 acquires 13 spectral bands ranging from Visible and Near-Infrared to Shortwave Infrared wavelengths along a 290 km orbital swath. While its spatial resolution varies from 10m to 60m, the four bands wiz. red, blue, green, and NIR have a resolution of 10m per pixel.

Please import the Python packages below installed


import folium
import geopandas as gpd
from sentinelsat.sentinel import SentinelAPI, read_geojson, geojson_to_wkt
import rasterio
import matplotlib.pyplot as plt
from rasterio import plot
from rasterio.plot import show
from rasterio.mask import mask
from osgeo import gdal
import numpy as np

Before calling the API we need an AOI (The polygon of the location we need to capture). For that, we need the GeoJSON file (a format for encoding geographic data structures). There are several ways to create a Shapefile or a GeoJSON file and geojson.io is one such place. Save the GeoJSON to a file named aoi.geojson .

Now Let’s call the API

Create an account in the open access hub https://scihub.copernicus.eu/dhus/#/home

#create instance of sentinal
api = SentinelAPI('username', 'password')

#Specify the path of geojson file
footprint = geojson_to_wkt(read_geojson('/content/aoi.geojson'))

#Specify the data , satellite name on the query
products = api.query(footprint,
date = ('NOW-100DAYS', 'NOW' ),
platformname = 'Sentinel-2',
processinglevel = 'Level-2A',
cloudcoverpercentage = (0, 20))

The code above will download the products related to that location and return some data that is stored in the products variable. We need to analyze the API further

Processing the Data

Convert the products to a geo data frame to analyze the result. For that, we will be using the below code

gdf = api.to_geodataframe(products)
print(gdf.columns)

The result of the above code consists of the following features. Based on these features we can analyze which type of image is needed to be downloaded.

['title', 'link', 'link_alternative', 'link_icon', 'summary', 'ondemand',
'generationdate', 'beginposition', 'endposition', 'ingestiondate',
'orbitnumber', 'relativeorbitnumber', 'illuminationazimuthangle',
'illuminationzenithangle', 'vegetationpercentage',
'notvegetatedpercentage', 'waterpercentage', 'unclassifiedpercentage',
'mediumprobacloudspercentage', 'highprobacloudspercentage',
'snowicepercentage', 'cloudcoverpercentage', 'level1cpdiidentifier',
'format', 'processingbaseline', 'platformname', 'filename',
'instrumentname', 'instrumentshortname', 'size', 's2datatakeid',
'producttype', 'platformidentifier', 'orbitdirection',
'platformserialidentifier', 'processinglevel', 'datastripidentifier',
'granuleidentifier', 'identifier', 'uuid', 'geometry']

Here we can see various useful information like vegetation data, cloud cover, water content, etc of the AOI. I will be sorting the data based on the percentage of cloud coverage. As we know that we need images with less cloud coverage.

gdf_sorted = gdf.sort_values(['cloudcoverpercentage'], ascending=[True])

After this execution data frame will be displayed with less cloud coverage. The next part is downloading the exact image based on our preference. The download of any particular image needs a URL.So in the above result, we can see a feature called uuid. Copy the uuid and run the below code by replacing the uuid.

Note: The size of the image will be more than 500 MB as it contains all the metadata and various resolution

#replace uuid
api.download("f197d3d4-c5db-451f-bfcf-04642599ee0f")

This code will download a zip file consisting of the satellite image data and metadata in various resolutions. Let's explore the folder structure. Before that, please unzip the file

The dataset with all 13 bands of information. We will write the data of these three bands in an empty tiff file and mask AOI on it. Locate the folder named ‘R10’ and change the names of files in the code below accordingly.

bands = r'...\GRANULE\L2A_T18TWL_A025934_20200609T155403\IMG_DATA\R10m'
blue = rasterio.open(bands+'\T18TWL_20200609T154911_B02_10m.jp2')
green = rasterio.open(bands+'\T18TWL_20200609T154911_B03_10m.jp2')
red = rasterio.open(bands+'\T18TWL_20200609T154911_B04_10m.jp2')
with rasterio.open('image_name.tiff','w',driver='Gtiff', width=blue.width, height=blue.height, count=3, crs=blue.crs,transform=blue.transform, dtype=blue.dtypes[0]) as rgb:
rgb.write(blue.read(1),3)
rgb.write(green.read(1),2)
rgb.write(red.read(1),1)
rgb.close()

The next step is to combine these 3 bands to make a single TIF file and visualize the image.

sdata = rasterio.open("image_name.tiff")

from rasterio.plot import show
show(sdata)

--

--

Prathyash Joy Binu

AI/ ML Engineer @ Reflections Infos Systems , R&D Enthusiast, Product Development,