Image Processing Dense Array, JPEG, PNG
In this post, we will cover the basics of working with images in Matplotlib, OpenCV and Keras.
Images are dense matrixes, and have a certain numbers of rows and columns. They can have 1 (grey) or 3 (RGB) or 4 (RGB + alpha-transparency) channels.
The dimension of the image matrix is ( height, width, channels).
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from PIL import Image
import cv2
from sys import getsizeof
import tensorflow as tf
#image = Image.open("images/freedom.png")
#plt.show(image)
Load image using Matplotlib
The Matplotlib image tutorial recommends using matplotlib.image.imread to read image formats from disk. This function will automatically change image array values to floats between zero and one, and it doesn't give any other options about how to read the image.
- imshow works on 0-1 floats & 0-255 uint8 values
- It doesn't work on int!
image = mpimg.imread("images/freedom.png")
plt.imshow(image)
plt.colorbar()
print(image.dtype)
freedom_array_uint8 = (image*255).astype(np.uint8) #convert to 0-255 values
image = cv2.imread("images/freedom.png")
#OpenCV uses BGR as its default colour order for images, matplotlib uses RGB
RGB_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)# cv2.cvtColor() method is used to convert an image from one color space to another
plt.imshow(RGB_image)
plt.colorbar()
For this image, the matrix will have 600 x 400 x 3 = 720,000 values. Each value is an unsigned 8-bit integer, in total 720,000 bytes.
Using unsigned 8-bit integers (256 possible values) for each value in the image array is enough for displaying images to humans. But when working with image data, it isn't uncommon to switch to 32-bit floats, for example. This increases tremendously the size of the data.
By loading the image files we can save them as arrays. Typical array operations can be performed on them.
print (RGB_image.shape, RGB_image.dtype)
image_keras = tf.keras.preprocessing.image.load_img("images/freedom.png") # loads and decodes image
print(type(image_keras))
print(image_keras.format)
print(image_keras.mode)
print(image_keras.size)
#image_keras.show()
np.save("images/freedom.npy", RGB_image)
freedomnpy = np.load('images/freedom.npy')
print("Size of array:", freedomnpy.nbytes)
print("Size of disk:", getsizeof(freedomnpy))
Storing one pixels takes several bytes.There are two main options for saving images: whether to lose some information while saving, or not.
JPG format
-
JPEG is lossy by deflaut
-
When saving an image as $*$.JPEG and read from it again, it is not necessary to get back the same values
-
The "image04_jpg.jpg" has 6.3 kB, less than the 7\% of $*$.npy file that generated it
-
cv2.IMWRITE_JPEG_QUALITY is between (0, 100), and allows to save losseless
cv2.imwrite("images/freedom_jpg.jpg", freedomnpy, [cv2.IMWRITE_JPEG_QUALITY, 0])
freedom_jpg = cv2.imread("images/freedom_jpg.jpg")
plt.imshow(freedom_jpg)
cv2.imwrite("images/freedom_png.png", freedomnpy, [cv2.IMWRITE_PNG_COMPRESSION, 0])
freedom_png = cv2.imread("images/freedom_png.png")
plt.imshow(freedom_png)