Spatial Operations on Satellite Image dataset

DATASET DESCRIPTION

Shuvam Das
deepkapha notes
10 min readJan 28, 2023

--

The dataset consists of wind speeds of tropical storms at different points in time using satellite images captured throughout a storm’s life cycle[1].

Data were aggregated by NASA data containing images from 494 storms. We have anywhere from 4 to 648 images per unique storm. The information originates from a satellite wavelength that specializes in long-wave infrared, enhancing cloud visibility and enhancing our ability to assess the spatial arrangement of storms. Each image is paired with a wind speed measurement in knots that is contained in a different file. The objective is to predict the wind speed for each image in the evaluation set.

CODE STRUCTURE

from google.colab import drive
drive.mount('/content/gdrive')
%cd /content/gdrive/My\ Drive/
%cd nasa-data1
import pandas as pd
import numpy as np
from PIL import Image
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline


df = pd.read_csv("training_set_labels.csv")
df.head()

This code is using Google Colab to mount a drive and navigate to a specific directory within that drive. It then uses the pathlib library to specify the path to a directory called “nasa-data1” and assigns variables to the “train” and “test” subdirectories within it. It then uses the os library to print the number of files in each of those subdirectories.

Then it imports some libraries such as pandas, numpy, PIL, seaborn and matplotlib for reading a CSV file and for visualization, and it uses pandas to read the file “training_set_labels.csv” and shows the first 5 rows of it.

It also imports the cv2 and numpy library for image processing and manipulation.

It’s important to note that this is just the beginning of the code and other parts of the script will use these libraries to perform different operations on the images and data.

DISPLAYING THE CURRENT IMAGES

i1 = cv2.imread("train/abs_001.jpg")
i2 = cv2.imread("train/abs_002.jpg")
i3 = cv2.imread("train/abs_003.jpg")
plt.figure(figsize=(10,10))
plt.subplot(121)
plt.imshow(cv2.cvtColor(i1, cv2.COLOR_BGR2RGB))
plt.title("image 1")

This code is using OpenCV library to read three images (“abs_001.jpg”, “abs_002.jpg”, “abs_003.jpg”) from a directory called “train” and display them using matplotlib library. It starts by reading the images using the cv2.imread() function, which takes in the file path of the image and returns the image data in the format of a numpy array. The images are assigned to variables i1, i2 and i3 respectively.

Then it creates a new figure with the size of (10, 10) using plt.figure(figsize=(10,10)) and set up a subplot with one row and two columns using plt.subplot(121). Then it uses plt.imshow() function to display the image, but before that it uses cv2.cvtColor(i1, cv2.COLOR_BGR2RGB) to convert the image format from BGR to RGB as OpenCV reads image in BGR format and matplotlib in RGB.

Finally, it uses plt.title(“image 1”) to add a title to the image.

It’s important to note that this is just the first image, the following lines of code will display the other two images in the same way.

from upper left — fig 1, fig 2, fig 3, fig 4

From the above images, we can clearly infer that the wind pattern was really changing along with time. In figure 1 we can see the cloud wind pattern is more concentrated toward the middle of the onsite field shown. This shows that variations in the wind's rotating motion change the structure and pattern of its formation. In the second figure, we see the cumulonimbus shifts away from the onsite and hence the speed of its rotation actually is different and over 5.5 percent more than that of the first figure. In the final figure, all that remains is the eye or the center itself churning around at its own centripetal force. Thus, this shows how the wind speed variates the wind structure.

CROPPING THE IMAGES TO SHOW THE INTERNAL PATTERNS OF THE IMAGE

# for second image from the training set thats a bit different
upper = 70
lower = 300
left = 120
right = 380
crop_top = i2[upper: lower,:,:]
plt.figure(figsize=(10,10))
plt.imshow(cv2.cvtColor(crop_top, cv2.COLOR_BGR2RGB))
plt.show()

This code is using OpenCV library to read two images (“abs_000.jpg”, “abs_006.jpg”) from a directory called “train” and perform cropping on these images using the specified upper, lower, left, and right values. It also uses matplotlib library to display the cropped images. First, it reads the images using the cv2.imread() function, which takes in the file path of the image and returns the image data in the format of a numpy array. The images are assigned to variables i1, i2 respectively.

Then it uses variables upper, lower, left, right to extract the region of interest from the image using the numpy array slicing. for the first image it is extracting the image from 150th row to 300th row and from 100th column to 280th column. This is done by using the i1[upper: lower, left:right,:] notation.

Then it creates a new figure with the size of (10, 10) using plt.figure(figsize=(10,10)) and it uses plt.imshow() function to display the cropped image, but before that it uses cv2.cvtColor(crop_top, cv2.COLOR_BGR2RGB) to convert the image format from BGR to RGB as OpenCV reads image in BGR format and matplotlib in RGB. Then it uses plt.show() to display the image on the output.

It repeats the same process for second image but with different values of upper, lower, left, right to crop the image. This code can be used to crop the desired region of interest from the image with the help of the specified coordinates.

INSPECTING THE INNER PATTERNS OF THE IMAGES USING RECTANGLE SPOTTING

upper = 150
lower = 300
left = 100
right = 280
start_point, end_point = (left, upper),(right, lower)
image_draw = np.copy(i1)
cv2.rectangle(image_draw, pt1=start_point, pt2=end_point, color=(0, 255, 0), thickness=3)
plt.figure(figsize=(5,5))
plt.imshow(cv2.cvtColor(image_draw, cv2.COLOR_BGR2RGB))
plt.show()

This code is using OpenCV library to draw a rectangle on an image read from a directory called “train” using the specified upper, lower, left, and right values. It also uses matplotlib library to display the image with the rectangle. First, it reads the image using the cv2.imread() function, which takes in the file path of the image and returns the image data in the format of a numpy array. The image is assigned to variable i1.

The rectangle mainly spots the centre of the image, inspecting the main changing pattern for the whole different structures. By comparing other images we can inspect through the rectangles how the pattern changes for different images.

Then it uses variables upper, lower, left, right to create the start point and end point of the rectangle using the numpy array slicing. It creates a tuple of the start point and end point of the rectangle using the format (left, upper) and (right, lower) respectively. It creates a copy of the image using np.copy(i1) and then it uses the cv2.rectangle function to draw a rectangle on the image. This function takes the image, starting point, end point, color and thickness of the rectangle as input. Then it creates a new figure with the size of (5, 5) using plt.figure(figsize=(5,5)) and it uses plt.imshow() function to display the image with rectangle, but before that it uses cv2.cvtColor(image_draw, cv2.COLOR_BGR2RGB) to convert the image from BGR color space to RGB color space. The plt.show() function is used to display the image on the screen.

STRUCTURING HISTOGRAMS FOR THE INTENSITIES OF THE IMAGES

hist = cv2.calcHist([i1],[0], None, [80], [0,80])
intensity_values = np.array([x for x in range(hist.shape[0])])
plt.bar(intensity_values, hist[:,0], width = 5)
plt.title("Bar histogram for image 1")
plt.show()

This code calculates the histogram of the image i1 and plots it using the matplotlib library. First, it uses the cv2.calcHist() function from the OpenCV library to calculate the histogram of the image i1. The function takes in the image, channels, mask, histSize, and range as arguments. In this case, the image is i1, the channel is 0 (since it’s grayscale image), no mask is used, histSize is 80 and the range is 0 to 80. This function returns a histogram of the image. Then it creates an array called intensity_values that contains the values from 0 to 79, corresponding to the bins in the histogram.

Then it uses the plt.bar() function from the matplotlib library to create a bar plot of the histogram. It takes in the intensity_values as the x-axis, and the histogram values as the y-axis, and the width of the bars is set to 5.

Then it uses the plt.title() function to set the title of the plot as “Bar histogram for image 1”. Finally, it uses the plt.show() function to display the histogram on the screen.

CREATING NEGATIVES OF THE IMAGE FOR MORE DETAILED VALIDATION

neg_i1 = -1 * i1 + 255
plt.figure(figsize=(10,10))
plt.subplot(1, 2, 1)
plt.imshow(i1,cmap="gray")
plt.subplot(1, 2, 2)
plt.imshow(neg_i1,cmap="gray")
plt.show()

This code applies a negative transformation on the image i1 and then plots the original image and the negative image side by side using the matplotlib library. First, it creates a new image called neg_i1 by applying a negative transformation on the image i1 using the following mathematical operation: -1 * i1 + 255. This operation inverts the intensity values of the image and returns the negative of the image. Then it uses the plt.figure() function from the matplotlib library to set the figure size to (10,10) and creates a subplot of 1 row and 2 columns. Then it uses the plt.subplot() function to specify the first subplot and the plt.imshow() function to display the original image i1 with a grayscale color map. It uses the plt.subplot() function to specify the second subplot and the plt.imshow() function to display the negative image neg_i1 with a grayscale color map.

Finally, it uses the plt.show() function to display the side of the original and negative image by side on the screen.

CONTROLLING THE BRIGHTNESS

alpha = 1 # Simple contrast control
beta = 100 # Simple brightness control
new_image = cv2.convertScaleAbs(i1, alpha=alpha, beta=beta)
plot_image(i1, new_image, title_1 = "Orignal", title_2 = "brightness control")

This code uses the OpenCV library’s convertScaleAbs function to adjust the brightness and contrast of an image. The alpha variable is being used as a contrast control and is set to 1. The beta variable is being used as a brightness control and is set to 100. The function takes the original image as an input and applies the changes to the brightness and contrast based on the values of alpha and beta. The new image is stored in the variable new_image. Finally, the function plot_image is being used to display the original image and the new image, with the titles “Original” and “brightness control” respectively.

IMAGE THRESHOLDING

import cv2
from google.colab.patches import cv2_imshow
import numpy as np


cv2_imshow(i1)
ret, thresh1=cv2.threshold(i1,130,255,cv2.THRESH_BINARY)
print(thresh1.shape)
cv2_imshow(thresh1)

This code uses the OpenCV library to perform a simple image thresholding operation on an image. The image is first displayed using the cv2_imshow function, which is a utility function provided by Google Colab to display the image. Then the cv2.threshold() function is used to threshold the input image. This function takes in the following arguments:

The image on which thresholding is to be applied. The threshold value (130) which pixels with intensity greater than this value will be set to 255. The maximum value of intensity (255) which is used to threshold the image. The thresholding method (THRESH_BINARY) which specifies whether to threshold the image in binary or in inverse binary. The function returns two outputs, the first one is the threshold value (ret) and the second one is the thresholded image (thresh1). The shape of the thresholded image is printed using the shape attribute. Finally, the thresholded image is displayed using the cv2_imshow() function again.

SHARPENING THE IMAGE PATTERNS TO SEE THE EDGES

# Common Kernel for image sharpening
kernel = np.array([[-1,-1,-1],
[-1, 9,-1],
[-1,-1,-1]])
# Applys the sharpening filter using kernel on the original image without noise
sharpened = cv2.filter2D(i1, -1, kernel)
# Plots the sharpened image and the original image without noise
plot_image(sharpened , i1, title_1="Sharpened image",title_2="Image")

This code is using the OpenCV library’s filter2D function to sharpen an image. The function takes in the following arguments:

  • The image on which the sharpening operation is to be applied (i1).
  • The depth of the image (-1).
  • The kernel (a 3x3 matrix) is used to sharpen the image.

The kernel is a 3x3 matrix defined as:

kernel = np.array([[-1,-1,-1],

[-1, 9,-1],

[-1,-1,-1]])

This is a common kernel used for image sharpening. It is a simple Sobel operator that is used to sharpen the image by detecting the edges in the image. When this kernel is convolved with the input image, it detects the edges and increases the intensity of the edges which results in a sharper image. The filter2D function applies the kernel on the input image and returns the sharpened image which is stored in the variable sharpened. Finally, the function plot_image() is used to display the original image and the sharpened image side by side. The title of the left image is “Sharpened image” and the title of the right image is “Image”

For the entire code visit the GitHub repository given in the references column[2].

REFERENCES

  1. https://drivendata.co/blog/predict-wind-speeds-benchmark/
  2. https://github.com/deepkapha/wind-speed-satellite-images

--

--