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"
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)]

<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>