Colour Paletter

As above.


Flask, NumPy, sklearn, SQL

I'd like to come back and make this application live, with an SQL databse and user login.

Palette Image
                    
from flask import Flask, flash, request, redirect, url_for, send_from_directory, render_template
from flask_bootstrap import Bootstrap4
from werkzeug.utils import secure_filename
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import os
from sklearn.cluster import KMeans


# Numpy bit to get colour info from image
def extract_colours(filename):
    img = Image.open(f"./static/images/temp/" + filename)
    img_array = np.array(img)
    num_colours = 7
    pixels = img_array.reshape(-1, 3)
    kmeans = KMeans(n_clusters=num_colours, random_state=0).fit(pixels)
    centers = kmeans.cluster_centers_.astype(int)
    labels = kmeans.labels_
    counts = np.bincount(labels)
    sorted_idx = np.argsort(-counts)
    dominant_colours = centers[sorted_idx]

    for i, (col, count) in enumerate(zip(dominant_colours, counts[sorted_idx])):
        print(f"{i+1}. RGB: {col.tolist()}, pixels: {count}")

    palette = np.zeros((50, 50 * num_colours, 3), dtype=np.uint8)
    for i, col in enumerate(dominant_colours):
        palette[:, i*50:(i+1)*50] = col

    plt.figure(figsize=(8, 2))
    plt.imshow(palette)
    plt.axis("off")
    plt.savefig(f'./static/images/outputs/'+filename, dpi=250)
    # plt.show()

# Define a function for opening images or allow image links for now
UPLOAD_FOLDER = './static/images/temp'
OUTPUT_FOLDER = './static/images/outputs'
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}

app = Flask(__name__)
bootstrap = Bootstrap4(app)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['OUTPUT_FOLDER'] = OUTPUT_FOLDER

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        # check if the post request has the file part
        if 'file' not in request.files:
            flash('No file part')
            return redirect(request.url)
        file = request.files['file']
        # If the user does not select a file, the browser submits an
        # empty file without a filename.
        if file.filename == '':
            flash('No selected file')
            return redirect(request.url)
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            extract_colours(filename)
            # return redirect(url_for('download_file', name=filename))
    return render_template('index.html', images = os.listdir(app.config['UPLOAD_FOLDER']))

if __name__ == '__main__':
    app.run(debug=True)
                    
                
                    
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Colour Paletter</title>
    {{ bootstrap.load_css() }}
    <style>
    </style>
</head>
<body>
<h1 style="text-align: center" class="my-4">Colour Paletter</h1>
<form style="text-align: center" method="post" enctype="multipart/form-data" class="p-3">
    <input type="file" name="file">
    <input type="submit" value="Upload">
</form>
<div class="row row-cols-xl-4 row-cols-lg-3 row-cols-md-2 row-cols-1 g-4 p-5" style="vertical-align: center">
    {% for image in images %}
    <div class="col d-flex flex-column align-content-center">
        <img src="static/images/temp/{{ image }}" class="image mb-3" style="width: 100%" alt="image"/>
        <img src="static/images/outputs/{{ image }}" class="image" style="width: 100%" alt="image"/>
    </div>
    {% endfor %}
</div>

</body>
</html>