Stuff I find slightly meaningful and close to achievable

From image to scatter: python tutorial

This post is about using python's pillow library together with the python OpenCV binder cv2 to perform basic image processing tasks. To be specific, the goal is to transform an object's image into a scatterplot representing its boundaries.

Loading an image

We'll first work with this kirby image, which we can obtain from the url using the python requests package as follows:

from PIL import Image
import requests

url = "https://upload.wikimedia.org/wikipedia/en/2/2d/SSU_Kirby_artwork.png"

url_data = requests.get(url, stream=True)


img = Image.open(url_data.raw)
img = np.asarray(img)

We can then visualize the image using matplotlib's imshow routine

import matplotlib.pyplot as plt

plt.imshow(img)
plt.axis('off')
plt.show()

The result is as expected:

image base

Edge detection

We'll extract the image's edges using the Canny algorithm. We'll skip the details and jump to the results. Using OpenCV's canny algorithm implementation with thresholds $90, 90$, we obtain the edges:

image edges

The image is a rectangular $363\times 275$ array, which we can pad to a $363\times 363$ square using the snippet

import cv2 as ocv

pad_edges = ocv.copyMakeBorder(edges,
                           (size - edges.shape[0])//2,
                           (size - edges.shape[0])//2,
                           (size - edges.shape[1])//2,
                           (size - edges.shape[1])//2,
                           ocv.BORDER_CONSTANT,
                           value=[0,0,0, 0])

This yields the image

edges square

Edges as a scatter

To turn our square image array $I$ of size $363\times 363$ into a set of points $P$ in the plane , we start from a square grid $G$ of the same size with values uniformly spaced on the square $[-5,+5]^2$. We then map the pixel $I_{ij}$ to the point $G_{ij}$ only if the pixel's intensity is nonzero. This is simply done through a for loop:

for i,x in enumerate(xgrid):
    for j,y in enumerate(ygrid):
        if pad_edges[i,j] > 0:
            points.append([x,y])

The result is the following scatter:

scatter