Colors From Image
Colors From Image finds the dominant color palette from an image. Often times when I see beautiful flowers I wonder what color palette they have. On a recent walk with my dog I saw a pink and orange plumeria in full bloom. I got the idea to make a Python program that would analyze the colors from an image and return the palette and hex codes.
The Process:
First, I had to figure out how to process an image and get the dominant colors from it. I knew I wanted to use Python and both of these articles used something called K-Means Clustering, an unsupervised machine learning algorithm, to find the dominant colors from an image.
- OpenCV and Python K-Means Color Clustering
- Color palette extraction with K-means clustering | Machine Learning from Scratch (Part IV)
Venelin Valkov in the second article explains how the algorithm works:
Let’s say you have some vector X that contains n data points. Running our algorithm consists of the following steps:
- Take random k points (called centroids) from X
- Assign every point to the closest centroid. The newly formed bunch of points is called cluster.
- For each cluster, find new centroid by calculating a new center from the points
- Repeat steps 2-3 until centroids stop changing
This image from Stack Overflow illustrates the process.
I decided to use Scikit-learn’s KMeans function to analyze the image and group the colors into clusters. I wanted to show the dominant colors from left to right, which required some sorting of arrays and lists after the KMeans function ran. I output an equal percentage version and a weighted version and saved them as .png files.
The weighted version shows that the image is about 45% dark purple and only 5% lavender. While this was neat, I didn’t include the weighted output in the final web version.
Once I was able to get the colors from an image locally, I created a new Django project to easily handle all the nuances of the web. The user uploads a valid image and chooses the number of colors between 3 and 7 using a select
. I used the default SQLite database because I wasn’t going to do anything fancy with the database. I only needed it so I could save the image a user uploaded and then run the KMeans function on it. I used opencv-python to analyze the uploaded image, which needed the file saved on the server before it could run on the image. To help with performance I did a few things:
- Prevented images over 2MB. This was mostly because I didn’t want to store big files on the server.
- Downsized the image that KMeans ran on if the image was over a certain KB size. There are a few different breakpoints that get larger images down to about 250 x 250 pixels when they are run through the algorithm. A 1MB image without the downsize took 50 seconds to process the 3000 x 2500 pixels, but only 2 or 3 seconds to process after being downsized.
Once the algorithm finishes, it writes over the existing file in /media/outputs/color-palette.png
and displays that file to the user along with the original image and hex codes. If this was a larger scale project I would have a new png be saved after each output, and then perhaps run a cron job to delete all the outputs every night to save storage space. But because this is a smaller project, using a single file that is displayed immediately back to the user works well.
The focus of this project was functionality. I used default Bootstrap styling and made sure the outputs collapsed nicely on mobile.
I deployed the project on Digital Ocean with the help of this guide.