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