Part 1: HSI Transform

In Lab 2, we saw how various contrast stretches can be used to improve the contrast (i.e. image lightness) and thereby improve the colour-composite derived from three stretched images. In this part of Lab 3, you will be introduced to the HSI transform, which can be used, along with contrast stretching, to further refine the colour balance of colour images.

Readings: Mather and Koch (2011), Computer Processing of Remotely-Sensed Images, pp 171-172

The RGB-to-HSI transform takes three bands of imagery, or a red-green-blue (RGB) colour composite, as input and produces three transformed bands: hue, saturation, and intensity (HSI). Note, HSI is sometimes referred to as ISH or even HIS; Mather and Koch refer to this transform by the HSI convention, while WhiteboxTools uses ISH. Hue is related to the dominant wavelength of light and is perceived as the color associated with a pixel in a composite image. Saturation is the purity of a color. Colours become less pure as more white light is added, making them appear somewhat pastel. Intensity refers to the brightness, or lightness, of a color. There are several versions of the RGB-to-HSI transform, but one common convention results in HSI values within the following numerical ranges:

0 < H < 2PI

0 < S < 1

0 < I < 1

Hue is actually and angular quantity, and therefore its degree range takes 0 < H < 360.

Be sure to download the imagery data associated with this lab assignment into an appropriate directory. These data should contain a sub-region of a Landsat 8 scene, including seven bands (i.e. bands 1 through 7) of image data, for an area of Southern Ontario between Kitchener-Waterloo, Cambridge, and Guelph. The image was acquired June 21, 2016. To get a sense of the data, use WhiteboxTools' CreateColourComposite tool to create a 432 natural-colour RGB composite image. Using a Python script, this might look something like the following:

from WBT.whitebox_tools import WhiteboxTools


wbt = WhiteboxTools()
wbt.work_dir = "/path/to/data/" # Update this

print("Creating a colour composite...")
wbt.verbose = False  # We don't need progress updates
wbt.create_colour_composite(
    red="band4_clipped.tif",
    green="band3_clipped.tif",
    blue="band2_clipped.tif",
    output="natural_colour.tif",
    enhance=False
)

print("All done!")

It is important that you do not enhance the composite (enhance=False), which is not the default setting. Displaying the resulting image using your data visualization software of choice, you should find that it looks as follows:

natural_colour.png image

Notice how dark, faded, and washed-out the colours in the image appear. The idea behind an HSI transform is simple. We can convert the three bands of data used to create this natural-colour composite image into the HSI colour space. We then perform a linear contrast stretch on the intensity (to brighten the image) and saturation (to make the image more colourful) bands and then perform the inverse transform (HSI-to-RGB) back into RGB colour space. When we perform contrast stretching directly on the RGB components, as we did in Lab 2, there is a good chance that the image colouring will be significantly altered, producing an unnatural appearance. By stretching only the intensity and saturation bands without altering the hue data, we will not be adjusting the colour values, only their colourfulness and lightness. In this way, we can ensure that the resulting enhanced image still looks natural after the adjustment.

So, let's do the adjustments and see if we can improve the colour-composite. Using VS Code, create a new Python script called hsi.py and copy the following script into the file:

from WBT.whitebox_tools import WhiteboxTools


wbt = WhiteboxTools()
wbt.work_dir = "/path/to/data/" # Update this

wbt.verbose = False  # We don't need progress updates

# Transform the data into intensity-hue-satuation
print("Transform the data into intensity-hue-satuation...")
wbt.rgb_to_ihs(
    red="band4_clipped.tif",
    green="band3_clipped.tif",
    blue="band2_clipped.tif",
    intensity="intensity.tif",
    hue="hue.tif",
    saturation="saturation.tif"
)

# Perform a contrast stretch on the intensity band
print("Stretching the intensity band...")
wbt.percentage_contrast_stretch(
    i="intensity.tif",
    output="intensity_cs.tif",
    clip=8.0,
    tail="upper",
    num_tones=1024
)

# The contrast stretched image has a value range from 0-1024 but we need it from 0-1
wbt.divide(
    input1="intensity_cs.tif",
    input2=1024.0,
    output="intensity_rescaled.tif"
)

# Now, perform a contrast stretch on the saturation band
print("Stretching the saturation band...")
wbt.percentage_contrast_stretch(
    i="saturation.tif",
    output="saturation_cs.tif",
    clip=0.75,
    tail="upper",
    num_tones=1024
)

# The contrast stretched image has a value range from 0-1024 but we need it from 0-1
wbt.divide(
    input1="saturation_cs.tif",
    input2=1024.0,
    output="saturation_rescaled.tif"
)

# Transform the IHS data back into RGB, using the stretched intensity and saturation bands,
# and create a colour composite
print("Transform the IHS data back into RGB...")
wbt.verbose = False
wbt.ihs_to_rgb(
    intensity="intensity_rescaled.tif",
    hue="hue.tif",
    saturation="saturation_rescaled.tif",
    output="natural_colour_hsi.tif"
)

print("All done!")

Once the script has sucessfully run, open the resulting natural_colour_hsi.tif image using your data visualization software of choice.

1.1. Describe the impact that stretching the intensity and saturation bands had on the natural-colour composite image. Include a screenshot of the enhanced image with your final report. (3 marks)

1.2. How much did we clip the tails of the intensity and saturation bands by? (2 marks)

Now experiment with adjusting each of the intensity and saturation stretch parameters (i.e. clip and tail values in the percentage_contrast_stretch function) to see if you can further refine the image quality.

Include the colour composite resulting from your best (most refined) transformation and also include the final stretch parameter values used to create the image. (3 marks)

The enhance optional parameter used in the CreateColourComposite tool performs an automated adjustment similar to the HSI-transform based stretch of the composite image. However, when we need more control over this adjustment, manually manipulating the HSI values as we have above is our best option.