Note: This notebook is adapted from MIT 18.S191 Introduction to Computational Thinking course (Fall 2020). The course uses Julia Programming language, and I thought it would be fun to follow along while using Python :).

Note: Check out the lecture video on YouTube

What is an image, though?

  • A grid of colored squares called pixels
  • A color of each pair (i, j) of indices
  • A discretization

How can we store an image in the computer?

  • A 1D array --> vector
  • A 2D array --> matrix
  • A 3D array --> tensor

Load image using scikit-image (skimage) package

import skimage.io
import numpy as np
import warnings

warnings.filterwarnings("ignore")
url = "https://i.imgur.com/VGPeJ6s.jpg"
philip = skimage.io.imread(url)
skimage.io.imshow(philip)
<matplotlib.image.AxesImage at 0x1602b3d90>
type(philip)
numpy.ndarray
philip.dtype
dtype('uint8')
philip.shape
(3675, 2988, 3)

Slicing and Indexing

# Show the 100th and 400th pixels
skimage.io.imshow(philip[100:101, 400:401, :])
<matplotlib.image.AxesImage at 0x1622859d0>
skimage.io.imshow(philip[100, 400].reshape(1, 1, 3))
<matplotlib.image.AxesImage at 0x15d9ba190>
h, w, _ = philip.shape
# Extract bottom half of the image
# and a tenth of the width until nine tenth of the width into the image
head = philip[(h // 2) : h, (w // 10) : ((9 * w) // 10)]
skimage.io.imshow(head)
<matplotlib.image.AxesImage at 0x15db11040>
head.shape
(1838, 2391, 3)
philip.shape
(3675, 2988, 3)

Manipulating matrices

An image is just a matrix, so we can manipulate matrices to manipulate the image:

stacked_philip = np.hstack([head, head])
stacked_philip.shape
(1838, 4782, 3)
skimage.io.imshow(stacked_philip)
<matplotlib.image.AxesImage at 0x15e80cb20>
a = np.hstack([head, np.flip(head, axis=1)])
b = np.hstack([np.flip(head, axis=0), np.flip(np.flip(head, axis=1), axis=0)])
c = np.vstack([a, b])
a.shape, b.shape, c.shape
((1838, 4782, 3), (1838, 4782, 3), (3676, 4782, 3))
skimage.io.imshow(c)
<matplotlib.image.AxesImage at 0x15fd0c3a0>

Manipulating an image

  • How can we get inside the image and change it?
  • There are two possibilities:
    • Modify or mutate numbers inside the array. This is useful when we want to change a small piece
    • Create a new copy of the array. This is useful when we want to alter everything together

Painting a piece of an image

  • Let's paint a corner red
  • We'll copy the image first so we don't destroy the original
new_phil = head.copy()
skimage.io.imshow(new_phil)
<matplotlib.image.AxesImage at 0x15e46c2b0>

Using for loops

%%timeit
for i in range(1, 100):
    for j in range(1, 300):
        new_phil[i, j] = [255, 0, 0] # Paint this corner red
42 ms ± 301 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
skimage.io.imshow(new_phil)
<matplotlib.image.AxesImage at 0x15dfc01c0>