Image Processing Application #1: Color Quantization

First, let's load in an image of Theo Ignatius Litovsky-Tralie (TILT)

Every pixel has 3 coordinates: red, green, and blue. We'll treat every pixel as a data point in 3D and reshape into a data matrix so that, as usual, each individual data point is a row in this matrix, and red, green, and blue are columns.

Let's actually plot these as a point cloud. We'll plot all pairs of 2 coordinates against each other

We can see that different shades of green from the grass are there, as well as Theo's orange, and the pink on my shirt, among other things. It's pretty clear from these plots, though, that these colors are all in one blob in 3D. Still, we can use KMeans here to find clusters. Regardless of the distribution of points, KMeans will tend to find clusters that are spread out and compact, since it minimizes the sum of the squared distances to each cluster center.

Let's first use KMeans to find 16 cluster centers. We'll cheat using the KMeans method from scikit-learn, though you'll have to implement your own version in the assignment.

Let's plot these cluster centers as we did the original point cloud

As promised, they are spread out pretty evenly throughout the dataset. If we substitute the color of each pixel with the color of the center to which its assigned (the closest center above), we get the following image

What we've managed to achieve above is something referred to as "nonuniform quantization," and it's a form of compression. In the original image, we had 3 channels, red green and blue, each with 8 bits, for a total of 24-bit color. Here, we've reduced to 16 possible colors total, which is only 4 bits. So we've compressed by a factor of 6, while still retaining a lot of the original color.

Let's say we only used 4 colors instead, so we go down to 2 bits. Then we get the following results

Actually, at this point, we have the opportunity to do something artistic which you might recognize. We can change the colors that we assign each cluster and then do the mapping again. We'll use white, blue, red, and black to make it a big like the Obama campaign posters

Image Processing Application #2: Superpixels

We can address a slightly different problem if we also include spatial information in the vectorization of each pixel.

First, let's just create a data matrix where each row is a pixel but this time there are two columns: one for the x coordinate and one for the y coordinate of that pixel. We're going to be using a lot more clusters, so we'll downscale and crop the image first to get a faster running time

Let's do k-means clustering on these points, taking 900 clusters

If we color each point by what cluster it was assigned to, we see that many of the clusters look like hexagons

The reason for this is quite deep, but intuitively, KMeans is trying to find a minimum of the sum of the squared distances from the points in the dataset to the centers. Points that concentrate inside of a ball (or a disc in 2D) minimize such distances. In other words, a perfectly round ball is a "perfect cluster." However, if our points are equally spaced on the plane, we can't just fit a bunch of balls together and "tile" it. The polygon with the most sides that can tile the plane is a regular hexagon, so that ends up being the best option

Now let's combine what we've already done with the colors and go up to a 5D vector for each state, where the first 3 dimensions are red, green, and blue, and the last two dimensions are the X and Y coordinates

Now let's color each point by the RGB coordinates of each cluster center (ignoring the spatial coordinates). This will give us a nice little "tile mosaic" picture

To read more about superpixels and their applications, check out the paper that introduced them back in 2003