jakubswi / Image-Colour-Palette-Generator

Image Color Analyzer is a Python Flask application that allows users to upload images and analyze the dominant colors present in the image using the KMeans clustering algorithm. The application provides a simple web interface for users to interact with, displaying the dominant colors and their occurrences as a JSON response.
MIT License
0 stars 1 forks source link

How to delete a file from flask server after a request #1

Closed jakubswi closed 8 months ago

jakubswi commented 8 months ago

Hi, i don't know how to delete a file from folder uploads after it gets passed to index.html so i can display it on a page. This is my code for a website that takes a picutere and returns a list of 10 most popular colors in it.: `import os import numpy as np from PIL import Image from flask import Flask, render_template, send_from_directory, after_this_request from flask_bootstrap import Bootstrap5 from flask_uploads import UploadSet, IMAGES, configure_uploads from flask_wtf import FlaskForm from flask_wtf.file import FileField, FileRequired, FileAllowed from sklearn.cluster import KMeans from wtforms import SubmitField

app = Flask(name) Bootstrap5(app) app.config['SECRET_KEY'] = "dskdkskamdsakmdak" app.config['UPLOADED_PHOTOS_DEST'] = 'uploads' photos = UploadSet('photos', IMAGES) configure_uploads(app, photos)

class UploadForm(FlaskForm): photo = FileField( validators=[FileAllowed(photos, 'Only images are allowed'), FileRequired('File field should not be empty')]) submit = SubmitField("Upload")

def get_dominant_colors(image_path): with Image.open(image_path) as image: width, height = image.size image_size = (width * height) / 100 image = image.convert('RGB') img_array = np.array(image) pixels = img_array.reshape(-1, 3) kmeans = KMeans(n_clusters=10, random_state=0) labels = kmeans.fit_predict(pixels) centers = kmeans.clustercenters color_counts = {} for label in np.unique(labels): color = tuple(centers[label].astype(int)) color_counts[color] = np.count_nonzero(labels == label) sorted_colors = sorted(color_counts.items(), key=lambda x: x[1], reverse=True) dominant_colors = [color for color, count in sorted_colors[:10]] color_occurrences = [count / image_size for color, count in sorted_colors[:10]] dominant_colors_hex = ['#%02x%02x%02x' % color for color in dominant_colors] return dominant_colors_hex, color_occurrences

@app.route('/uploads/') def get_file(filename): return send_from_directory(app.config['UPLOADED_PHOTOS_DEST'], filename)

@app.route('/', methods=["GET", "POST"]) def main_page(): form = UploadForm() if form.validate_on_submit(): file = photos.save(form.photo.data) photo_path = os.path.join(app.config['UPLOADED_PHOTOS_DEST'], file) dominant_colors_hex, color_occurrences = get_dominant_colors(photo_path) color_occurrences = [f"{color:.4f}" for color in color_occurrences] return render_template("index.html", dominant_colors=dominant_colors_hex, color_occurrences=color_occurrences, file=photo_path, form=form) return render_template("index.html", dominant_colors=None, color_occurrences=None, file=None, form=form)

if name == "main": app.run(debug=False)`

jftsang commented 8 months ago

Heya, when commenting fyi you can wrap your code in triple backticks to get it in a codeblock

def hello():
    ... # like this
    # then you keep your indents
jftsang commented 8 months ago

It'd be probably best not to store the uploaded file on the server at all. Use an AJAX call to send it to the server, do the k-means calculation on the server, send the results back as JSON and use client-side logic (i.e. JavaScript) to display the answers. You can still display the image on the client side (you will want to use URL.createObjectURL (doc) to create a URL for the image, and then do img.src = ... in your JS).

You'd avoid all the hassles of storing data server-side - storage space, but also worrying about privacy (at the moment, anyone can access anyone else's uploads).

If you really want to do something similar to what you have now, you can do something like this:

from werkzeug.security import safe_join

@app.route('/uploads/<filename>')
def get_file(filename):
    try:
        return send_from_directory(app.config['UPLOADED_PHOTOS_DEST'], filename)
    else:  # only do this if no exception
        os.unlink(safe_join(app.config['UPLOADED_PHOTOS_DEST'], filename))

(Don't use os.path.join!)

jakubswi commented 8 months ago

Thank you @jftsang, but how would it look like in code, how do I do the URL.createObjectURL? In the 'main_page' method or JS?

jftsang commented 8 months ago

In the JS. See my PR :-)

jakubswi commented 8 months ago

Thank you so much, you're amazing. It works, sorry about earlier, didn't realize it's js, i don't have much expierance with js.