Image Processing - Basics


Intro

Notebook that explores the basics of image processing in Python, like image loading, representation and transformations.


In [1]:
import seaborn as sns
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

import os
import sys
sys.path.append(os.path.join(os.pardir))

from utils import image_processing
%load_ext autoreload
%autoreload 2

%matplotlib inline

sns.set_style("dark")

Load and Plot Image


In [ ]:
img_path = os.path.join(os.path.pardir, 'resources', 'mona_lisa.jpg')

In [ ]:
# Load with open-cv
import cv2
# open-cv represents RGB images as BGR (reverse order)
img = cv2.cvtColor(cv2.imread(img_path), cv2.COLOR_BGR2RGB))
sns.plt.imshow(img)
sns.plt.show()

In [ ]:
# Load with scikit
from skimage import io
img = io.imread(img_path)
sns.plt.imshow(img)
sns.plt.show()

In [ ]:
# Load with PIL
from PIL import Image
with Image.open(img_path) as img:
    sns.plt.imshow(img.convert(mode='RGB'))
    sns.plt.show()

Plot Color Channels


In [ ]:
# red color channel
sns.plt.imshow(img[:,:,0])
sns.plt.show()

In [ ]:
# red color channel in grey color map 
sns.plt.imshow(img[:,:,0], cmap='gray')
sns.plt.show()

Image from array


In [ ]:
# dummy list of strings representing our image
a = ["0000000000",
     "0111111100",
     "0000111100",
     "0000111100",
     "0001111100",
     "0000111100",
     "0001100000",
     "0000000000",
     "0000000000"]

In [ ]:
# build numpy array of 0s and 1s from previous list
a = np.array([list(map(int, s)) for s in a], dtype=np.float32)
a.shape

In [ ]:
# plot image
plt.imshow(a, cmap='gray', interpolation='none', vmin=0, vmax=1)
plt.show()

Morphological Operations


In [ ]:
from skimage import morphology
b = np.array([[1,1,1],
            [1,1,1],
            [1,1,1]])
res = morphology.binary_dilation(a, b).astype(np.uint8)
#res = morphology.binary_erosion(res, b).astype(np.uint8)

In [ ]:
plt.imshow(res, cmap='gray', interpolation='none', vmin=0, vmax=1)
plt.show()

In [ ]:
b = np.array([[0,0,0,0],
            [0,1,1,0],
            [0,0,0,0]])
s = np.array([[1,0],
              [1,1]])

In [ ]:
res = morphology.binary_dilation(b, s).astype(np.uint8)
res

In [ ]:
plt.imshow(res, cmap='gray', interpolation='none', vmin=0, vmax=1)
plt.show()

Convolution Filters


In [ ]:
from scipy import ndimage
from skimage import data

In [ ]:
# load initial ref image
image = data.coins()
plt.imshow(image, cmap='gray', interpolation='none')
plt.show()

In [ ]:
# convolve image with custom kernel
k = np.array([[1/16,1/8,1/16],
            [1/18,1,1/8],
            [1/16,1/8,1/16]])
n_image = ndimage.convolve(image, k, mode='constant', cval=0.0)

In [ ]:
# plot convolved image
plt.imshow(n_image, cmap='gray', interpolation='none')
plt.show()

Gaussian Convolution

Try convolving an image using a Gaussian kernel.


In [ ]:
# gaussian distribution formula
def gaussian(x, mu, sig):
    return np.exp(-np.power(x - mu, 2.) / (2 * np.power(sig, 2.)))

In [ ]:
# plot 1D gaussian curve
x = np.linspace(-3.0, 3.0, 6)
z = gaussian(x, 0, 1)
plt.plot(z)

In [ ]:
# compute 2D gaussian
z_2d = np.matmul(z.reshape(-1, 1), z.reshape(1, -1))
plt.imshow(z_2d)

In [ ]:
# load initial ref image
image = data.camera()
plt.imshow(image, cmap='gray')
plt.show()

In [ ]:
# convolve
n_image = ndimage.convolve(image, z_2d)
plt.imshow(n_image, cmap='gray', interpolation='none')
plt.show()

Images Normalization


In [ ]:
# load all imgs filepaths for the celeba database
dir_path = os.path.join(os.pardir, 'resources', 'img_align_celeba')
imgs_filepath = [os.path.join(dir_path, img_name) for img_name in os.listdir(dir_path)]
print(len(imgs_filepath))

In [ ]:
# load subset of images
imgs = image_processing.load_data(imgs_filepath[:100])
imgs.shape

Mean/Deviation of Images


In [ ]:
# compute mean images (across list of images, so axis=0)
mean_img = np.mean(imgs, axis=0)
# plot image (convert to int values)
plt.imshow(mean_img.astype(np.uint8))
plt.show()

In [ ]:
# compute std images (across list of images, so axis=0)
std_img = np.std(imgs, axis=0)
# plot image (convert to int values)
plt.imshow(std_img.astype(np.uint8))
plt.show()

In [ ]:
plt.imshow(np.mean(std_img, axis=2).astype(np.uint8))
plt.show()

Normalization


In [ ]:
# flatten imgs to single vector
flattened_imgs = imgs.ravel()
print(flattened_imgs.shape)

In [ ]:
# plot flattened images
(_, _, _) = plt.hist(flattened_imgs, bins=255)

In [ ]:
# plot flattened mean image
(_, _, _) = plt.hist(mean_img.ravel(), bins=255)

In [ ]:
bins = 20
fig, axs = plt.subplots(1, 3, figsize=(12, 6), sharey=True, sharex=True)
axs[0].hist((imgs[0]).ravel(), bins)
axs[0].set_title('img distribution')
axs[1].hist((mean_img).ravel(), bins)
axs[1].set_title('mean distribution')
axs[2].hist((imgs[0] - mean_img).ravel(), bins)
axs[2].set_title('(img - mean) distribution')

In [ ]:
# normalized image (remove mean and divide by std)
(_, _, _) = plt.hist(((imgs[0] - mean_img)/std_img).ravel(), bins=20)

In [ ]: