Color Name Prediction: A Simple, Perfect Guide to Live Machine Learning with KNN

LakshmanLakshman
6 min read

Introduction

Introducing Color Name Prediction, a user-friendly web application that identifies color names with just a click! Powered by a sophisticated K-Nearest Neighbors (KNN) algorithm, it analyzes the RGB values of images to accurately predict color names from a dataset of over 865 diverse shades. Say goodbye to color confusion and hello to precise color identification with Color Name Prediction!

GitHub Link: https://github.com/LakshmanKishore/colorNamePrediction

Live Application Link: https://lakshmankishore.github.io/colorNamePrediction/

Live Application Demo

Witness the Color Name Prediction application in action! Below is a captivating demonstration of the final application, showcasing its intuitive interface and precise color naming capabilities.

Explaining K-Nearest Neighbors (KNN):

KNN Primer: KNN is a versatile machine learning algorithm commonly used for classification tasks. It operates on the principle that similar data points tend to belong to the same class. In our case, each color name in our dataset represents a distinct class, and KNN helps us classify new colors by finding the nearest known color based on their RGB values.

Mapping RGB Values to Color Names:

Color Prediction in Action: In our project, we've curated a dataset of approximately 864 unique color names, covering a wide spectrum of hues and shades. Despite the seemingly limited number of color names, the RGB color space allows for millions of possible combinations. Our application bridges this gap by leveraging the KNN algorithm to predict color names for RGB values that may not exist in our dataset. By calculating the Euclidean distance between the input color and every color in our dataset, we identify the closest match and predict its corresponding color name.

Understanding the Color Name Prediction Project Structure

Let's explore the contents of the Color Name Prediction project and understand what each file contains:

  1. build-using-flask

    • This directory contains an older version of the application built using Flask, a Python web framework. This version was originally deployed on Heroku. However, due to the limitations of the Heroku free tier, the application was migrated to a simple static site with custom implementation of KNN.
  2. app.css

    • This file contains the CSS styles used to define the visual appearance and layout of the web application.
  3. app.js

    • Here lies the JavaScript code responsible for implementing the core functionality of the Color Name Prediction application. This includes the logic for sampling colors from images, computing RGB values, and performing color name predictions using the K-Nearest Neighbors algorithm.
  4. colorName.csv

    • This CSV file contains a dataset of color names along with their corresponding RGB values. It serves as the reference data for the KNN algorithm to match sampled colors and predict their names.
  5. colorName.gif

    • This GIF file is a visual demonstration or animation showcasing the Color Name Prediction application in action. It illustrates the process of clicking on images and seeing the predicted color names.
  6. favicon.ico

    • The favicon.ico file is an icon displayed in the browser tab or bookmark bar to represent the Color Name Prediction website. It helps users identify and distinguish the site when multiple tabs are open.
  7. index.html

    • The index.html file is the main HTML file of the Color Name Prediction web application. It defines the structure of the webpage and includes elements such as images, buttons, and text inputs. JavaScript and CSS files are typically linked within this HTML file.
  8. readme.md

    • This Markdown file serves as documentation for the Color Name Prediction project.

More info on specific files

  1. colorName.csv: The below is the screenshot of how the dataset looks like.

  2. app.js:

    1. Initialization of Variables:

       let imageInput = document.querySelector('.imageInput');
       let introduction = document.querySelector('.introduction');
       let image = document.querySelector('.image');
       let canvas = document.querySelector('canvas');
       let answer = document.querySelector('.answer');
       let c = canvas.getContext('2d');
      
      • Declares variables to reference elements in the HTML document such as image input, introduction text, canvas, and answer display area.
    2. Fetching CSV Data:

       var colorData = [];
      
       fetch('./colorName.csv')
         .then(response => response.text())
         .then(data => {
           // Process the CSV data
           processData(data);
         })
         .catch(error => {
           console.error('Error loading CSV file:', error);
         });
      
      • Fetches the colorName.csv file using the Fetch API.

      • Upon successful retrieval, the data is processed using the processData function.

    3. Processing CSV Data:

       function processData(data) {
         const rows = data.split('\n');
      
         for (let i = 1; i < rows.length; i++) {
           const columns = rows[i].split(',');
           const color = {
             name: columns[1],
             r: columns[3],
             g: columns[4],
             b: columns[5]
           };
           colorData.push(color);
         }
         console.log(colorData)
       }
      
      • Splits the CSV data into rows and extracts relevant information (color name, RGB values).

      • Constructs an array of color objects containing name, red, green, and blue values.

    4. Loading Image:

       function loadImage(src) {
           introduction.hidden = true;
           image.hidden = false;
           image.src = src;
       }
      
      • Hides the introduction text and displays the selected image in the image area upon user file input.
    5. Loading File:

       function loadFile(e) {
           if (e.target.files) {
               let imageFile = e.target.files[0];
               let reader = new FileReader();
               reader.readAsDataURL(imageFile);
               reader.onloadend = function (e) {
                   loadImage(e.target.result);
               }
           }
       }
      
      • Listens for changes in the image input and triggers the loadFile function to read and display the selected image.
    6. Color Sampling:

       function getColor(x, y) {
           let pixel = c.getImageData(x, y, 1, 1);
           let rgb = pixel.data;
      
           return rgb;
       }
      
      • Retrieves the RGB values of a pixel from the canvas at the specified coordinates (x, y).
    7. Displaying Color Name:

       function displayAnswer(text, rgb) {
           answer.innerText = text;
           answer.innerHTML += "  :  <div class='colorBox'></div>";
           let colorBox = document.querySelector('.colorBox');
           colorBox.style.backgroundColor = "rgb(" + rgb + ")";
       }
      
      • Displays the predicted color name along with a color box representing the sampled color.
    8. Canvas Usage:

       function useCanvas(el, image, callback) {
           el.width = image.width;
           el.height = image.height;
           el.getContext('2d')
               .drawImage(image, 0, 0, image.width, image.height);
           return callback();
       }
      
      • Renders the selected image on the canvas and invokes a callback function upon completion.
    9. K-Nearest Neighbors Algorithm:

       function findNearestColor(r, g, b, k) {
           // Calculate the Euclidean distance between the input RGB values and colors in the data
           const distances = colorData.map(color => {
             const d = Math.sqrt(
               Math.pow(r - color.r, 2) +
               Math.pow(g - color.g, 2) +
               Math.pow(b - color.b, 2)
             );
             return { color: color.name, distance: d };
           });
      
           // Sort the distances in ascending order
           distances.sort((a, b) => a.distance - b.distance);
      
           // Get the k nearest neighbors
           const nearestNeighbors = distances.slice(0, k);
      
           // Extract the color names of the nearest neighbors
           const nearestColorNames = nearestNeighbors.map(neighbor => neighbor.color);
      
           // Return the nearest color name(s)
           return nearestColorNames;
       }
      
      • Implements the KNN algorithm to find the nearest color name(s) based on the input RGB values.

      • Calculates the Euclidean distance between the input RGB values and colors in the dataset.

      • Sorts the distances in ascending order and selects the k nearest neighbors.

      • Returns the nearest color name(s) as predictions.

    10. Prediction Event Handling:

      function predict(e) {
        if (e.offsetX) {
            x = e.offsetX;
            y = e.offsetY;
        }
        else if (e.layerX) {
            x = e.layerX;
            y = e.layerY;
        }
        image.crossOrigin = "Anonymous";
        useCanvas(canvas, image, function () {
            let rgb = getColor(x, y);
            let rgb_string = rgb[0] + "," + rgb[1] + "," + rgb[2];
      
            const nearestColor = findNearestColor(rgb[0], rgb[1], rgb[2], 1);
            // console.log("Nearest Color", nearestColor)
            displayAnswer(nearestColor[0], rgb_string);
        });
      };
      
      imageInput.addEventListener('change', loadFile);
      image.addEventListener('click', predict);
      
      • Listens for click events on the image and triggers the predict function to sample the color and display the predicted name.

Conclusion

In this blog post, we've explored the Color Name Prediction application, unveiling its inner workings and showcasing the power of JavaScript and the K-Nearest Neighbors algorithm in predicting color names from RGB values.

Thank you for reading this article!

Happy coding and happy blogging!

1
Subscribe to my newsletter

Read articles from Lakshman directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Lakshman
Lakshman

I am a software engineer with a passion for learning, innovation, and open source.