Vincent GODARD - V4- 29/01/2024
Freely inspired by :
Sources:
Landsat Thematic Mapper (TM) data from September 10, 1987, West of Worcester, Massachusetts (from the https://clarklabs.org/download/)
scikit-image https://scikit-image.org/
matplotlib https://matplotlib.org/
numpy https://numpy.org/
Compressed file to download => here.
Some libraries are already preinstalled (e.g. Matplotlib). The Skimage library is not, and must be installed.
You then need to load them (Import function).
# To install Skimage, delete the # (before the "!").
# !pip install scikit-image
## Loading libraries
import skimage # Image processing library
import skimage.io as io # Utility for reading and writing images in various formats (shortened to io).
import skimage.metrics # Utility allowing measurements between images.
import matplotlib.pyplot as plt # Library for plotting and visualizing data in graphical form (shortened to plt).
import numpy as np # Library intended to manipulate multidimensional matrices or tables.
## To find out the version of skimage
skimage.__version__ # warning to "." after skiimage
You may find it useful to take a look at the https://scikit-learn.org/stable/ or https://scikit-image.org/ libraries, some of which have their own wikis in French^^! : https://fr.wikipedia.org/wiki/Scikit-learn or https://fr.wikipedia.org/wiki/Scikit-image or even https://fr.wikipedia.org/wiki/NumPy.
Reading an image file centered on the Howe Hill region, West of Worcester in Massachusetts (USA). This is the TM4 band (PIR, near infrared) and TM3 (red band) of the Landsat Thematic Mapper (TM) of September 10, 1987.
Unlike TD11, the file format is no longer .jpg (compressed JPEG format, https://fr.wikipedia.org/wiki/JPEG) but .tif (compressed or non-TIFF format, https://fr.wikipedia.org/wiki/Tagged_Image_File_Format).
## Reading with the imread() function before displaying
HOW87TM4 = io.imread('data/how87tm4.tif')
## Displaying the number of rows, columns and number of channels (if applicable)
## Using the .shape function of the .io module
print(HOW87TM4.shape)
## If you want to dress up the output (text between '', then "," before the .shape function on the HOW87TM4 variable)
print('(number of rows, number of columns):', HOW87TM4.shape)
We may also want to know the depth of our variable (its coding) by its type.
○ The type of a Python object determines what kind of object it is: https://docs.python.org/3/glossary.html#term-type
## Displaying information
print('type :', HOW87TM4.dtype )
The type is an integer (unsigned integer 8bits) encoded on one byte (256 levels of gray, for example).
## Displaying the image in gray level, using the imshow() function of the plt module:
plt.imshow(HOW87TM4, 'gray')
## To choose another color: https://matplotlib.org/stable/tutorials/colors/colormaps.html
## Write anything in place of 'gray', it generates an error message!
## At ValueError, in the list of colors, try others such as :
## viridis' (default color) or 'tab20c_r' to see the effect.
## Pay attention, it's case-sensitive (SHIFT/min)!
Compression in one of the most common formats, JPEG (https://fr.wikipedia.org/wiki/JPEG).
Compressing the HOW87TM4 image to jpeg with a compression level between 1 and 100
## Saving the compressed image in .jpg format
io.imsave('data/HOW87TM4.jpg', HOW87TM4, quality=50) # 50% compression
After compression, the two files need to be compared. The first step can be visual.
To the eye, they should still look very similar. Otherwise, the statistical indicators of similarity are likely to be very unfavorable!
## Reading the image in .jpg format
JPEG4 = io.imread('data/HOW87TM4.jpg') # Reading the image assigned to the JPEG variable
plt.imshow(JPEG4, 'gray')
To the eye, there's no obvious difference!
Visual and statistical comparisons.
Using the subplot() function of "matplotlib.pyplot" which allows you to organize different plots inside a display grid (https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot. subplot.html or in French https://courspython.com/tracer-plurieurs-courbes.html#display-de-plurieurs-traces-dans-la-meme-figure).
## Display of compressed image and difference image
plt.figure(figsize=(15, 5)) # display of images in two sub-figures (vary the size if necessary
plt.subplot(121) # display of multiple layouts in the same figure (121/122 layout on one line)
plt.title('JPEG4 (apparent luminances, 256 gray levels') # titling to identify the image
plt.imshow(JPEG4, 'gray') # display function in matplotlib.pyplot
## Add legend
plt.colorbar()
diff1 = np.absolute(HOW87TM4-JPEG4) # calculation (with numpy) the absolute value of the difference between the two images (origin - compressed)
plt.subplot(122) # display of multiple layouts in the same figure (121/122 layout on one line)
plt.imshow(diff1) # show the difference image between HOW87TM4 and JPEG4
## Add legend
plt.colorbar()
plt.title('TIFF - JPEG4 (deviation in val. absolute. of luminances app.)') # add a title to the sub-figure with the MSE value associated with the difference image
plt.show() # Not necessary here to display successive results stored in memory, but avoids unnecessary text above images (like: Text(0.5, 1.0, 'TIFF - JPEG4 Difference'))
The spatial distribution of the different gap values (from blue to yellow) seems fairly even.
Use of MSE (Mean-squared error) as a statistical indicator of compression loss.
What is MSE [mean-squared error or mean squared error (MSE) https://fr.wikipedia.org/wiki/Erreur_quadratique_moyenne]? Go see the settings and the explanations by following this link: https://scikit-image.org/docs/stable/api/skimage.metrics.html#skimage.metrics.mean_squared_error.
## Calculation of the mean square error (MSE) between the two images
mse = skimage.metrics.mean_squared_error(HOW87TM4, JPEG4) # calculation of the difference between the two images with skimage.metrics via MSE
MSE = f'{mse:.2f}' # MSE value with two decimal places
print(f" Value of the MSE (mean square error) between the two images: {mse:.2f}")
#print('Value of the MSE (mean square error) between the two images:', MSE)
As it is a raw value, it is difficult to know if this loss of information (deviation from the original image) is significant!
We will compare this MSE value with that obtained, in the next chapter, on another compression, PNG.
Save HOW87TM4 image with default compression level, when in PNG.
## Save compressed image in .png format
io.imsave('data/HOW87TM4.png', HOW87TM4) # no compression level is defined here
After compression, it's time to compare the two files. First, visually.
When read, they should look very similar!
## Read image in .png format
PNG4 = io.imread('data/HOW87TM4.png') # read image assigned to PNG variable
plt.imshow(PNG4, 'gray')
## Add legend
plt.colorbar()
To the eye, there's still no obvious difference!
Visual and statistical comparisons.
Using the subplot() function of "matplotlib.pyplot" which allows you to organize different plots inside a display grid (https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot. subplot.html or in French https://courspython.com/tracer-plurieurs-courbes.html#display-de-plurieurs-traces-dans-la-meme-figure).
## Display of compressed image and difference image
plt.figure(figsize=(15, 5)) # displays images in two sub-figures (vary size if necessary)
plt.subplot(121) # display of multiple layouts in the same figure (121/122 layout on one line)
plt.title('PNG4 (apparent luminances, 256 grey levels') # titling to identify the image
plt.imshow(PNG4, 'gray') # display function in matplotlib.pyplot
## Add legend
plt.colorbar()
diff2 = np.absolute(HOW87TM4-PNG4) # calcul (avec numpy) la valeur absolue de la différence entre les deux images (origine - compressée)
plt.subplot(122) # display of several layouts in the same figure (121/122 = layout on a line)
plt.imshow(diff2) # displays image of differences between HOW87TM4 and PNG4
## Add legend
plt.colorbar()
plt.title('TIFF - PNG4 (difference in absolute luminance values).)') # add a title to the sub-figure with the MSE value associated with the difference image
plt.show() # Not necessary here to display successive results stored in memory, but avoids unnecessary text above images (like: Text(0.5, 1.0, 'Difference TIFF - PNG4').)
The spatial distribution of the different gap values (from blue to yellow) seems fairly even.
Using MSE (mean-squared error) as a statistical indicator of compression loss.
What is MSE [mean-squared error (MSE) https://fr.wikipedia.org/wiki/Erreur_quadratique_moyenne]? See the settings and explanations by following this link: https://scikit-image.org/docs/stable/api/skimage.metrics.html#skimage.metrics.mean_squared_error.
## Calculation of the mean square error (MSE) between the two images
mse = skimage.metrics.mean_squared_error(HOW87TM4, PNG4) # calculation of the difference between the two images with skimage.metrics via MSE
MSE = f'{mse:.2f}' # MSE value to two decimal places
#print(f" MSE (mean square error) value between the two images: {mse:.2f}")
print('MSE (mean square error) value between the two images:', MSE)
So, no loss (MSE = 0) with PNG compression!
However, compare TIFF, JPEG and PNG file sizes in your data directory!
Don't be surprised if the HOW87TM3 image is very dark. Its dynamic range is low. We'll see how to analyze and improve it in TD 14.