Introduction to Image Processing — Color Overcast Adjustment using Python

Kris Tabong
3 min readJan 9, 2021

In this article, we will focus on how to handle images with color overcast. These kinds of images usually happen when you have either an underexposure or overexposure. Let’s get started by uploading the needed libraries.

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from skimage.io import imshow, imread
from skimage.util import img_as_ubyte
Image Taken by Author

The image has mostly bluish in color and overcast. Let's investigate the RGB spectrum of the image.

image_overcast = imread(“siemreap.jpg”)
rgb_list = [‘Reds’,’Greens’,’Blues’]
fig, ax = plt.subplots(1, 3, figsize=(15,5), sharey = True)
for i in range(3):
ax[i].imshow(image_overcast[:,:,i], cmap = rgb_list[i])
ax[i].set_title(rgb_list[i], fontsize = 15)
RGB Channels

We can say that the image has a predominately blue color based on visual inspection. To have a better understanding of the distribution of colors, let's check the statistics per channel.

def channel_statistics(image):
df_color = []
for i in range(0, 3):
max_color =np.max(image[:,:,i])
mean_color = np.mean(image[:,:,i])
median_color = np.median(image[:,:,i])
perc_90 = np.percentile(image[:,:,i], 90, axis=(0,1))
perc_95 = np.percentile(image[:,:,i], 95, axis=(0,1))
perc_99 = np.percentile(image[:,:,i], 99, axis=(0,1))

row = (max_color, mean_color, median_color,
perc_90, perc_95, perc_99)
df_color.append(row)

return pd.DataFrame(df_color,
index = ['Red', ' Green', 'Blue'],
columns = ['Max', 'Mean', 'Median',
'P_90',' P_95', 'P_99'])
channel_statistics(image_overcast)
Image RGB stats

We can see that the highest value of the channel is blue. To reduce the blue channel, we will scale it down based on the maximum color value of the blue channel. Here is the code below on how I did it.

def percentile_adjustment(image):
fig, ax = plt.subplots(2, 3, figsize=(15,10), sharey = True)
f_size = 15
blue = 99.75
parameter_matrix = [[99] + [99] + [blue] + [99] ,
[95] + [95] + [blue] + [95] ,
[90] + [90] + [blue] + [90] ,
[85] + [85] + [blue] + [85] ,
[80] + [80] + [blue] + [80]]

ax[0][0].imshow(image)
ax[0][0].set_title(‘Original’, fontsize = f_size);
ax[0][1].imshow(img_as_ubyte((image /
[np.percentile(image[:,:,i],
parameter_matrix[0][i], axis=(0, 1)) \
for i in range(0, 3)]).clip(0,1)))

ax[0][1].set_title(‘Blue : {}, Others : {}’.format(blue,
parameter_matrix[0][1],
fontsize = f_size));
ax[0][2].imshow(img_as_ubyte((image /
[np.percentile(image[:,:,i],
parameter_matrix[1][i], axis=(0, 1)) \
for i in range(0, 3)]).clip(0,1)))

ax[0][2].set_title(‘Blue : {}, Others : {}’.format(blue,
parameter_matrix[1][1],
fontsize = f_size));
ax[1][0].imshow(img_as_ubyte((image /
[np.percentile(image[:,:,i],
parameter_matrix[2][i], axis=(0, 1)) \
for i in range(0, 3)]).clip(0,1)))
ax[1][0].set_title(‘Blue : {}, Others : {}’.format(blue,
parameter_matrix[2][1],
fontsize = f_size));
ax[1][1].imshow(img_as_ubyte((image /
[np.percentile(image[:,:,i],
parameter_matrix[3][i], axis=(0, 1)) \
for i in range(0, 3)]).clip(0,1)))
ax[1][1].set_title(‘Blue : {}, Others : {}’.format(blue,
parameter_matrix[3][1],
fontsize = f_size));
ax[1][2].imshow(img_as_ubyte((image/
[np.percentile(image[:,:,i],
parameter_matrix[4][i], axis=(0, 1)) \
for i in range(0, 3)]).clip(0,1)))

ax[1][2].set_title(‘Blue : {}, Others : {}’.format(blue,
parameter_matrix[4][1],
fontsize = f_size));
plt.tight_layout()
percentile_adjustment(image_overcast)

The code seems complex, but the important variable there is the parameter matrix, wherein the third variable is “blue”. Should you opt to change the color of interest, say green, just change the second item to a variable, and everything else as constant. After running the image, it should look like this.

Adjusting the Blue Channel

As you can see, we see the color from other channels better. Hooray. :) I like the 90% adjustment for blue since the green grass is more prominent.

I would like to thank my learning teammate “Tonichi” for the codes and for helping me creating this blog. You may visit him for a more detailed and fun application of python to image processing. https://tonichi-edeza.medium.com/

--

--

Kris Tabong

Learning more about Image Processing using Python