Color detection plays a crucial role in computer vision, from sorting items by color to assisting visually impaired users. By combining the power of Flask, OpenCV, and machine learning, you can build an advanced web app that accurately detects and classifies colors from uploaded images or user interactions.

In this tutorial, we will deploy a color detection web app on an Ubuntu 24.04 GPU server. The app utilizes a pre-trained machine learning model for enhanced accuracy and offers an intuitive interface for uploading images and selecting pixels to identify their colors. You also learn how to structure the Flask backend, handle file uploads, and serve color predictions in real-time.

Prerequisites

  • An Ubuntu 24.04 server with an NVIDIA GPU.
  • A non-root user with sudo privileges.
  • NVIDIA drivers installed.

Step 1: Set Up Python Environment

First, we’ll install the necessary Python packages and create a virtual environment.

1. Install Python and pip.

apt install -y python3-pip python3-dev python3-venv

2. Create a virtual environment.

python3 -m venv venv

3. Activate the virtual environment.

source venv/bin/activate

Step 2: Install Required Python Packages

Now we’ll install all the Python dependencies for our project.

pip install tqdm flask opencv-python pandas numpy scikit-learn pillow

These packages include:

  • tqdm for progress bars
  • flask for the web framework
  • opencv-python for image processing
  • pandas, numpy for data handling
  • scikit-learn for machine learning
  • pillow for image handling

Step 3: Set Up Project Structure

1. Create the necessary directories for our web application.

mkdir templates static

2. Download the color database from Kaggle for color recognition.

3. Copy the downloaded dataset file from your local computer to the server.

scp archive.zip root@server-ip:/root/

4. Unzip the downloaded dataset.

unzip archive.zip

Step 4: Create the Machine Learning Model

Now we’ll create a script to train our color classification model.

1. Create a new file called model_trainer.py:

nano model_trainer.py

Add the following code.

import os
import cv2
import numpy as np
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import joblib
from tqdm import tqdm

class ColorModelTrainer:
    def __init__(self, dataset_path="training_dataset"):
        self.dataset_path = dataset_path
        self.classes = sorted(os.listdir(dataset_path))
        self.model = SVC(kernel='linear', probability=True)
    
    def load_dataset(self):
        X = []
        y = []
        
        print("Loading dataset...")
        for class_idx, class_name in enumerate(tqdm(self.classes)):
            class_path = os.path.join(self.dataset_path, class_name)
            for img_file in os.listdir(class_path):
                img_path = os.path.join(class_path, img_file)
                img = cv2.imread(img_path)
                if img is not None:
                    img = cv2.resize(img, (50, 50))  # Standardize size
                    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
                    X.append(img.flatten())
                    y.append(class_idx)
        
        return np.array(X), np.array(y)
    
    def train(self):
        X, y = self.load_dataset()
        X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
        
        print("Training model...")
        self.model.fit(X_train, y_train)
        
        # Evaluate
        y_pred = self.model.predict(X_test)
        accuracy = accuracy_score(y_test, y_pred)
        print(f"Model accuracy: {accuracy:.2f}")
        
        # Save model
        os.makedirs("static/models", exist_ok=True)
        joblib.dump(self.model, "static/models/color_classifier.joblib")
        joblib.dump(self.classes, "static/models/classes.joblib")
        print("Model saved successfully")

if __name__ == "__main__":
    trainer = ColorModelTrainer()
    trainer.train()

2. Run the training script.

python3 model_trainer.py

This script will:

  • Load and preprocess the training images
  • Train an SVM classifier
  • Evaluate the model accuracy
  • Save the trained model for later use

Step 5: Create the Color Detector Class

Now we’ll create the core functionality that detects colors using both traditional and ML methods.

1. Create a new file called color_detector.py:

nano color_detector.py

Add the following code.

import cv2
import pandas as pd
import numpy as np
import joblib
import os

class AdvancedColorDetector:
    def __init__(self):
        # Traditional method
        self.csv_path = os.path.join('static', 'colors.csv')
        self.index = ["color", "color_name", "hex", "R", "G", "B"]
        self.df = pd.read_csv(self.csv_path, names=self.index, header=None)
        
        # ML method
        self.ml_model = joblib.load("static/models/color_classifier.joblib")
        self.classes = joblib.load("static/models/classes.joblib")
    
    def get_color_name_traditional(self, R, G, B):
        minimum = float('inf')
        color_name = "Unknown"
        for i in range(len(self.df)):
            d = abs(R - int(self.df.loc[i, "R"])) + abs(G - int(self.df.loc[i, "G"])) + abs(B - int(self.df.loc[i, "B"]))
            if d < minimum:
                minimum = d
                color_name = self.df.loc[i, "color_name"]
        return color_name
    
    def get_color_name_ml(self, img, x, y):
        # Extract 50x50 patch around the clicked point
        patch_size = 25
        patch = img[max(0,y-patch_size):min(img.shape[0],y+patch_size),
                   max(0,x-patch_size):min(img.shape[1],x+patch_size)]
        
        if patch.size == 0:
            return "Unknown"
        
        # Resize and predict
        patch = cv2.resize(patch, (50, 50))
        patch = cv2.cvtColor(patch, cv2.COLOR_BGR2RGB).flatten()
        proba = self.ml_model.predict_proba([patch])[0]
        confidence = max(proba)
        if confidence < 0.6:  # Confidence threshold
            return "Unknown (Low Confidence)"
        
        return self.classes[np.argmax(proba)]
    
    def process_image(self, image_path, x, y):
        img = cv2.imread(image_path)
        if img is None:
            return None, "Could not read image"
        
        b, g, r = img[y, x]
        
        # Get results from both methods
        traditional_name = self.get_color_name_traditional(r, g, b)
        ml_name = self.get_color_name_ml(img, x, y)
        
        return {
            'rgb': (r, g, b),
            'traditional': traditional_name,
            'ml': ml_name
        }

Step 6: Create the Flask Web Application

Now we’ll create the main Flask application that serves our web interface.

1. Create a new file called app.py:

nano app.py

Add the following code.

from flask import Flask, render_template, request, jsonify
import os
from color_detector import AdvancedColorDetector

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = os.path.join('static', 'uploads')
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)

detector = AdvancedColorDetector()

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        if 'file' not in request.files:
            return render_template('index.html', error="No file selected")
        
        file = request.files['file']
        if file.filename == '':
            return render_template('index.html', error="No file selected")
        
        if file:
            filename = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
            file.save(filename)
            return render_template('index.html', 
                                image_url=filename,
                                filename=file.filename)
    
    return render_template('index.html')

@app.route('/detect', methods=['POST'])
def detect():
    data = request.json
    filename = os.path.join(app.config['UPLOAD_FOLDER'], data['filename'])
    x, y = int(data['x']), int(data['y'])
    
    result = detector.process_image(filename, x, y)
    
    return jsonify({
        'rgb': f"RGB({result['rgb'][0]}, {result['rgb'][1]}, {result['rgb'][2]})",
        'traditional': result['traditional'],
        'ml': result['ml']
    })

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

2. Create the web interface template in the templates directory.

nano templates/index.html

Add the following code.

<!DOCTYPE html>
<html>
<head>
    <title>Advanced Color Detection</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .container { max-width: 800px; margin: 0 auto; }
        .upload-box { border: 2px dashed #ccc; padding: 20px; text-align: center; margin-bottom: 20px; }
        #image-container { position: relative; margin-top: 20px; }
        #uploaded-image { max-width: 100%; cursor: crosshair; }
        #color-info { margin-top: 10px; padding: 15px; background: #f5f5f5; border-radius: 5px; }
        .result-box { margin: 10px 0; padding: 10px; background: white; border-left: 4px solid #4CAF50; }
        .error { color: red; }
        .method-label { font-weight: bold; color: #333; }
    </style>
</head>
<body>
    <div class="container">
        <h1>Advanced Color Detection</h1>
        <p>Upload an image and click anywhere to detect colors using both traditional and ML methods</p>
        
        <form method="post" enctype="multipart/form-data" class="upload-box">
            <input type="file" name="file" accept="image/*" required>
            <button type="submit">Upload Image</button>
            {% if error %}<p class="error">{{ error }}</p>{% endif %}
        </form>

        {% if image_url %}
        <div id="image-container">
            <img id="uploaded-image" src="{{ image_url }}" alt="Uploaded Image">
            <div id="color-info">
                <div class="result-box">
                    <span class="method-label">Traditional Method:</span> <span id="traditional-result">Click on the image</span>
                </div>
                <div class="result-box">
                    <span class="method-label">ML Method:</span> <span id="ml-result">Click on the image</span>
                </div>
                <div class="result-box">
                    <span class="method-label">RGB Values:</span> <span id="rgb-result">-</span>
                </div>
            </div>
        </div>
        {% endif %}
    </div>

    {% if image_url %}
    <script>
        document.getElementById('uploaded-image').addEventListener('click', function(e) {
            const rect = this.getBoundingClientRect();
            const x = e.clientX - rect.left;
            const y = e.clientY - rect.top;
            
            fetch('/detect', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    filename: '{{ filename }}',
                    x: x,
                    y: y
                })
            })
            .then(response => response.json())
            .then(data => {
                document.getElementById('traditional-result').textContent = data.traditional;
                document.getElementById('ml-result').textContent = data.ml;
                document.getElementById('rgb-result').textContent = data.rgb;
            });
        });
    </script>
    {% endif %}
</body>
</html>

Step 7: Run the Application

Start the Flask development server.

python3 app.py

You will see the following output.

 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://server-ip:5000

Step 8: Access the Application

1. Open a web browser and navigate to http://server-ip:5000.
2. Click the “Browse” button to upload an image from your local computer.


3. After uploading, click on any color in the image.


4. The app will display:

  • The RGB values of the selected color
  • The color name detected by the traditional method
  • The color name detected by the machine learning method

Conclusion

In this tutorial, you have built a robust and interactive web app capable of detecting colors using machine learning on an Ubuntu 24.04 GPU server. You configured the environment, deployed a Flask application, and integrated a color classification model to enhance accuracy. This setup provides a strong foundation for more complex vision tasks such as object recognition or augmented reality.