Lab 2 - RGB to Grayscale Conversions

Methods summary

  1. Simple Averaging
    • Gray = (R + G + B) / 3
  2. Weighted Average
    • Gray = 0.3 * R + 0.59 * G + 0.11 * B
    • Gray = 0.2126 * R + 0.7152 * G + 0.0722 * B
    • Gray = 0.299 * R + 0.587 * G + 0.114 * B
  3. Desaturation
    • Gray = (min(R,G,B) + max(R,G,B)) / 2
  4. Decomposition
    • Maximum: Gray = max(R,G,B)
    • Minimum: Gray = min(R,G,B)
  5. Single colour channel
    • Gray = R or
    • Gray = G or
    • Gray = B
  6. Custom number of grey shades $$[a_0 = 0, a_1), [a_1, a_2), ... , [a_{p-1}, a_p = 255], a_i - a_{i-1} = 255 / p$$
  7. Custom number of grey shades with error-diffusion dithering

Imports


In [1]:
import numpy as np

import matplotlib.pyplot as plt
%matplotlib inline
import matplotlib.image as mpimg

In [2]:
img = mpimg.imread('ara01.png')
imgplot = plt.imshow(img)


Methods

Simple Averaging


In [3]:
def simple_avg(pixel):
    R = pixel[0]
    G = pixel[1]
    B = pixel[2]
    
    return (R + G + B) / 3

In [4]:
%%time

temp_img = np.copy(img)

for i in range(temp_img.shape[0]):
    for j in range(temp_img.shape[1]):
        temp_img[i, j] = np.array([simple_avg(temp_img[i, j])] * 3)


CPU times: user 9.04 s, sys: 10.3 ms, total: 9.05 s
Wall time: 9.02 s

In [5]:
plt.figure(figsize=(30,30))

plt.subplot(1, 2, 1),
plt.imshow(img)

plt.subplot(1, 2, 2),
plt.imshow(temp_img)

plt.show()


Weighted Average


In [6]:
def weighted_avg_1(pixel):
    R = pixel[0]
    G = pixel[1]
    B = pixel[2]
    
    return 0.3    * R + 0.59   * G + 0.11   * B

def weighted_avg_2(pixel):
    R = pixel[0]
    G = pixel[1]
    B = pixel[2]
    
    return 0.2126 * R + 0.7152 * G + 0.0722 * B

def weighted_avg_3(pixel):
    R = pixel[0]
    G = pixel[1]
    B = pixel[2]
    
    return 0.299  * R + 0.587  * G + 0.114  * B

In [7]:
%%time

temp_img1 = np.copy(img)
temp_img2 = np.copy(img)
temp_img3 = np.copy(img)

for i in range(temp_img1.shape[0]):
    for j in range(temp_img1.shape[1]):
        temp_img1[i, j] = np.array([weighted_avg_1(temp_img1[i, j])] * 3)
        temp_img2[i, j] = np.array([weighted_avg_2(temp_img2[i, j])] * 3)
        temp_img3[i, j] = np.array([weighted_avg_3(temp_img3[i, j])] * 3)


CPU times: user 42.7 s, sys: 3.48 ms, total: 42.7 s
Wall time: 42.7 s

In [8]:
plt.figure(figsize=(70,40))

plt.subplot(1, 4, 1),
plt.imshow(img)

plt.subplot(1, 4, 2),
plt.imshow(temp_img1)

plt.subplot(1, 4, 3),
plt.imshow(temp_img2)

plt.subplot(1, 4, 4),
plt.imshow(temp_img3)

plt.show()


Desaturation


In [9]:
def desaturation(pixel):
    R = pixel[0]
    G = pixel[1]
    B = pixel[2]
    
    return (min(R,G,B) + max(R,G,B)) / 2

In [10]:
%%time

temp_img = np.copy(img)

for i in range(temp_img.shape[0]):
    for j in range(temp_img.shape[1]):
        temp_img[i, j] = np.array([desaturation(temp_img[i, j])] * 3)


CPU times: user 10.2 s, sys: 11.6 ms, total: 10.3 s
Wall time: 10.2 s

In [11]:
plt.figure(figsize=(70,40))

plt.subplot(1, 2, 1),
plt.imshow(img)

plt.subplot(1, 2, 2),
plt.imshow(temp_img)

plt.show()


Decomposition


In [12]:
def max_gray(pixel):
    R = pixel[0]
    G = pixel[1]
    B = pixel[2]
    
    return max(R,G,B)

def min_gray(pixel):
    R = pixel[0]
    G = pixel[1]
    B = pixel[2]
    
    return min(R,G,B)

In [13]:
%%time

temp_img1 = np.copy(img)
temp_img2 = np.copy(img)

for i in range(temp_img1.shape[0]):
    for j in range(temp_img1.shape[1]):
        temp_img1[i, j] = np.array([max_gray(temp_img1[i, j])] * 3)
        temp_img2[i, j] = np.array([min_gray(temp_img2[i, j])] * 3)


CPU times: user 9.6 s, sys: 3.41 ms, total: 9.6 s
Wall time: 9.63 s

In [14]:
plt.figure(figsize=(70,40))

plt.subplot(1, 3, 1),
plt.imshow(img)

plt.subplot(1, 3, 2),
plt.imshow(temp_img1)

plt.subplot(1, 3, 3),
plt.imshow(temp_img2)

plt.show()


Single color channel


In [15]:
def single_R(pixel):
    R = pixel[0]
    G = pixel[1]
    B = pixel[2]
    
    return R

def single_G(pixel):
    R = pixel[0]
    G = pixel[1]
    B = pixel[2]
    
    return G

def single_B(pixel):
    R = pixel[0]
    G = pixel[1]
    B = pixel[2]
    
    return B

In [16]:
%%time

temp_img1 = np.copy(img)
temp_img2 = np.copy(img)
temp_img3 = np.copy(img)

for i in range(temp_img1.shape[0]):
    for j in range(temp_img1.shape[1]):
        temp_img1[i, j] = np.array([single_R(temp_img1[i, j])] * 3)
        temp_img2[i, j] = np.array([single_G(temp_img2[i, j])] * 3)
        temp_img3[i, j] = np.array([single_B(temp_img3[i, j])] * 3)


CPU times: user 12.1 s, sys: 7.7 ms, total: 12.1 s
Wall time: 12.1 s

In [17]:
plt.figure(figsize=(70,40))

plt.subplot(1, 4, 1),
plt.imshow(img)

plt.subplot(1, 4, 2),
plt.imshow(temp_img1)

plt.subplot(1, 4, 3),
plt.imshow(temp_img2)

plt.subplot(1, 4, 4),
plt.imshow(temp_img3)

plt.show()


Custom number of grey shades

$$[a_0 = 0, a_1), [a_1, a_2), ... , [a_{p-1}, a_p = 255], a_i - a_{i-1} = 255 / p$$

In [18]:
def set_middle_pixel_for_p_shades(pixel, p):
    R = pixel[0]
    
    if p < 1 or p >= 256:
        print('p value not valid')
    
    lst = [0]
    diff = 255 / p
    running_total = 0 + diff
    
    for i in range(1, p):
        lst.append(running_total)
        
        if lst[i-1] <= R < lst[i]:
            # print(lst)
            # print(diff)
            return (lst[i-1] + lst[i]) / 2
        
        running_total += diff

In [19]:
%%time

temp_img = np.copy(img)

for i in range(temp_img.shape[0]):
    for j in range(temp_img.shape[1]):
        temp_img[i, j] = np.array([set_middle_pixel_for_p_shades(temp_img[i, j], 5)] * 3)


CPU times: user 12.8 s, sys: 11.7 ms, total: 12.8 s
Wall time: 12.8 s

In [22]:
plt.figure(figsize=(70,40))

plt.subplot(1, 2, 1),
plt.imshow(img)

plt.subplot(1, 2, 2),
plt.imshow(temp_img, cmap='viridis')

plt.show()



In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]:

Custom number of grey shades with error-diffusion dithering


In [ ]:


In [ ]:


In [ ]: