In this blog post, you will learn color spaces that are often used in image processing problems. More specifically, after reading the blog, you will be familiar with using
- skimage.color.rgb2lab
- skimage.color.lab2rgb
- keras.preprocessing.image.load_img
- keras.preprocessing.image.img_to_array
- matplotlib.pyplot.imshow
Let's first load two example images using keras.preprocessing.image.load_img. The list dir_data contains the path to two jpg images.
dir_data = ["../Flickr8k/Flicker8k_Dataset/1012212859_01547e3f17.jpg",
"../Flickr8k/Flicker8k_Dataset/2554531876_5d7f193992.jpg"]
Now let's read in the two images and save it into list. As you see from the printing, load_img returns an object of PIL.Image.Image with image mode RGB and size as a pre-specified target_size.
from keras.preprocessing.image import img_to_array, load_img
target_size = (256,256)
# Get images
Ximg = []
for filename in dir_data:
Ximg.append(load_img(filename,target_size=target_size))
print(Ximg[0])
Now using img_to_array we will convert each of the image into numpy array.
import numpy as np
Xsub_rgb = []
for img in Ximg:
Xsub_rgb.append(img_to_array(img))
print(Xsub_rgb[0].shape)
print(Xsub_rgb[0])
## convert the entire list to numpy array
Xsub_rgb = np.array(Xsub_rgb)
RGB color images consist of three layers: a red layer, a green layer, and a blue layer. Each layer in a color image has a value from 0 - 255. The value 0 means that it has no color in this layer. If the value is 0 for all color channels, then the image pixel is black.
As you see, all the R, G and B dimensions of the Xsub_rgb is in the range between 0 - 255.
## Extrat the first few example images
Nsample = Xsub_rgb.shape[0]
def plotMinMax(Xsub_rgb,labels=["R","G","B"]):
print("______________________________")
for i, lab in enumerate(labels):
mi = np.min(Xsub_rgb[:,:,:,i])
ma = np.max(Xsub_rgb[:,:,:,i])
print("{} : MIN={:8.4f}, MAX={:8.4f}".format(lab,mi,ma))
plotMinMax(Xsub_rgb,labels=["R","G","B"])
Let's look at each layer of the images¶
To visualize image in python, you can use matplotlib.pyplot.imshow. This function accept RGB image in standardized scale ranging between 0 and 1.
Notice that my code below devide the image rgb by 255.0. To plot each layer separately, we can assign values zero to all the layers except the one of interests.
from copy import copy
import matplotlib.pyplot as plt
count = 1
fig = plt.figure(figsize=(12,3*Nsample))
for rgb in Xsub_rgb:
## This section plot the original rgb
ax = fig.add_subplot(Nsample,4,count)
ax.imshow(rgb/255.0); ax.axis("off")
ax.set_title("original RGB")
count += 1
for i, lab in enumerate(["R","G","B"]):
crgb = np.zeros(rgb.shape)
crgb[:,:,i] = rgb[:,:,0]
ax = fig.add_subplot(Nsample,4,count)
ax.imshow(crgb/255.0); ax.axis("off")
ax.set_title(lab)
count += 1
plt.show()
The color representation for image is not limited to RGB. In image colorization problem, for example, LAB is more common color space for image colorization problem.
Colorizing B&W; Photos with Neural Networks says:
L stands for lightness, and a and b for the color spectrums green–red and blue–yellow. A Lab encoded image has one layer for grayscale and have packed three color layers into two.
Using skimage.color.rgb2lab, we can easily convert the RGB image into LAB format and with skimage.color.lab2rgb we can inverse LAB back to RGB. However, you need to pay a bit attentions to its scale.
The range of the dimensions for RGB and LAB in skimage.color.rgb2lab and lab2rgb are:
- rgb_lab:[0,1]x[0,1]x[0,1] -> [0,100] x [-128,128] x [-128,128]
- lab_rgb:[0,100] x [-128,128] x [-128,128] --> [0,1]x[0,1]x[0,1]
As rgb2lab assumes that the RGB is standardized to range between 0 and 1, we will first devide Xsublab by 255.0.
RGB -> LAB¶
Xsub_rgb01 = Xsub_rgb/255.0
Then now we are ready to convert rgb image to lab. Notice that L, A, and B dimensions have different range.
from skimage.color import rgb2lab, lab2rgb
Xsub_lab = rgb2lab(Xsub_rgb01)
plotMinMax(Xsub_lab,labels=["L","A","B"])
LAB -> RGB¶
We can also inverse the process by using lab2rgb.
# lab2rgb has to have a dimension (-,-,3)
Xsub_lab_rgb = np.zeros( Xsub_lab.shape)
for i in range(Xsub_lab.shape[0]):
Xsub_lab_rgb[i] = lab2rgb(Xsub_lab[i])
plotMinMax(Xsub_lab_rgb.reshape((1,) + Xsub_lab_rgb.shape),labels=["R","G","B"])
Check if the RGB -> LAB -> RGB worked by plotting¶
ax.imshow() takes standardized RGB images (ranging between 0 and 1). Using this function, I will plot the the original RGB image and inversed RGB image are generated are the same.
count = 1
fig = plt.figure(figsize=(6,3*Nsample))
for irgb, irgb2 in zip(Xsub_rgb01, Xsub_lab_rgb):
ax = fig.add_subplot(Nsample,2,count)
ax.imshow(irgb); ax.axis("off")
ax.set_title("original RGB")
count += 1
ax = fig.add_subplot(Nsample,2,count)
ax.imshow(irgb2); ax.axis("off")
ax.set_title("RGB -> LAB -> RGB")
count += 1
plt.show()
Check if the 0th dimension of the LAB image is showing the brightness.¶
Finally, we can visualize each dimension of LAB image as follows:
def extract_single_dim_from_LAB_convert_to_RGB(image,idim):
'''
image is a single lab image of shape (None,None,3)
'''
z = np.zeros(image.shape)
if idim != 0 :
z[:,:,0]=80 ## I need brightness to plot the image along 1st or 2nd axis
z[:,:,idim] = image[:,:,idim]
z = lab2rgb(z)
return(z)
count = 1
fig = plt.figure(figsize=(13,3*Nsample))
for lab in Xsub_lab:
ax = fig.add_subplot(Nsample,3,count)
lab_rgb_gray = extract_single_dim_from_LAB_convert_to_RGB(lab,0)
ax.imshow(lab_rgb_gray); ax.axis("off")
ax.set_title("L: lightness")
count += 1
ax = fig.add_subplot(Nsample,3,count)
lab_rgb_gray = extract_single_dim_from_LAB_convert_to_RGB(lab,1)
ax.imshow(lab_rgb_gray); ax.axis("off")
ax.set_title("A: color spectrums green to red")
count += 1
ax = fig.add_subplot(Nsample,3,count)
lab_rgb_gray = extract_single_dim_from_LAB_convert_to_RGB(lab,2)
ax.imshow(lab_rgb_gray); ax.axis("off")
ax.set_title("B: color spectrums blue to yellow")
count += 1
plt.show()