Spaces:
Sleeping
Sleeping
File size: 5,566 Bytes
a8624ef |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
from PIL import Image
import numpy as np
import math
import gradio as gr
import io
from collections import Counter
from sklearn.cluster import KMeans
import colorsys
def rgb_to_hsv(rgb):
"""Convertit RGB vers HSV"""
r, g, b = rgb / 255.0
return np.array(colorsys.rgb_to_hsv(r, g, b))
def extract_dominant_colors(image, max_colors=100):
"""Extrait les couleurs dominantes en regroupant par teintes"""
if image.mode != 'RGB':
image = image.convert('RGB')
# Convertit en tableau numpy
np_image = np.array(image)
pixels = np_image.reshape(-1, 3)
if len(pixels) == 0:
return np.array([])
# Si on a moins de couleurs que la limite, on retourne toutes les couleurs uniques
unique_pixels = np.unique(pixels, axis=0)
if len(unique_pixels) <= max_colors:
return unique_pixels
# Sinon, on utilise K-means pour regrouper les couleurs similaires
kmeans = KMeans(n_clusters=max_colors, random_state=42, n_init=10)
kmeans.fit(pixels)
# Retourne les centres des clusters (couleurs dominantes)
return kmeans.cluster_centers_.astype(int)
def sort_colors_by_hue(colors):
"""Trie les couleurs par teinte (HSL)"""
def get_hue(rgb):
r, g, b = rgb / 255.0
h, s, v = colorsys.rgb_to_hsv(r, g, b)
return h
def get_brightness(rgb):
return np.mean(rgb)
# Trie d'abord par teinte, puis par luminosité
sorted_colors = sorted(colors, key=lambda rgb: (get_hue(rgb), get_brightness(rgb)))
return np.array(sorted_colors)
def create_color_palette(colors, square_size=50):
if len(colors) == 0:
return None
num_colors = len(colors)
# Calcul du nombre de colonnes et lignes pour faire un carré
grid_size = math.ceil(math.sqrt(num_colors))
palette_size = grid_size * square_size
# Crée une image vide
palette = Image.new("RGB", (palette_size, palette_size), (255, 255, 255))
for i, color in enumerate(colors):
r, g, b = color
# Crée un carré de la couleur
color_square = Image.new("RGB", (square_size, square_size), (int(r), int(g), int(b)))
x = (i % grid_size) * square_size
y = (i // grid_size) * square_size
palette.paste(color_square, (x, y))
return palette
def process_image(input_image, max_colors, sort_by_hue):
if input_image is None:
return None, "Veuillez uploader une image"
try:
# Extraction des couleurs dominantes
colors = extract_dominant_colors(input_image, max_colors)
# Tri par teinte si demandé
if sort_by_hue and len(colors) > 0:
colors = sort_colors_by_hue(colors)
# Création de la palette
palette = create_color_palette(colors)
if palette is not None:
message = f"Palette créée avec {len(colors)} couleurs dominantes"
return palette, message
else:
return None, "Aucune couleur trouvée dans l'image"
except Exception as e:
return None, f"Erreur lors du traitement : {str(e)}"
def download_palette(input_image, max_colors, sort_by_hue):
if input_image is None:
return None
try:
colors = extract_dominant_colors(input_image, max_colors)
if sort_by_hue and len(colors) > 0:
colors = sort_colors_by_hue(colors)
palette = create_color_palette(colors)
if palette:
# Sauvegarde dans un buffer
buffer = io.BytesIO()
palette.save(buffer, format="PNG")
buffer.seek(0)
return buffer
except:
return None
# Création de l'interface Gradio
with gr.Blocks(title="Extracteur de Palette de Couleurs") as demo:
gr.Markdown("# 🎨 Extracteur de Palette de Couleurs")
gr.Markdown("Upload une image pour extraire les couleurs dominantes et créer une palette visuelle")
with gr.Row():
with gr.Column():
input_image = gr.Image(type="pil", label="Image d'entrée")
max_colors = gr.Slider(minimum=5, maximum=200, value=50, step=5, label="Nombre maximum de couleurs")
sort_by_hue = gr.Checkbox(value=True, label="Trier par teintes")
with gr.Row():
submit_btn = gr.Button("🎨 Extraire les couleurs", variant="primary")
download_btn = gr.DownloadButton("💾 Télécharger la palette", variant="secondary")
with gr.Column():
output_image = gr.Image(label="Palette de couleurs", interactive=False)
status_text = gr.Textbox(label="Statut", interactive=False)
# Traitement principal
submit_btn.click(
fn=process_image,
inputs=[input_image, max_colors, sort_by_hue],
outputs=[output_image, status_text]
)
# Téléchargement
download_btn.click(
fn=download_palette,
inputs=[input_image, max_colors, sort_by_hue],
outputs=[download_btn]
)
# Exemples
gr.Examples(
examples=[
["https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/React-icon.svg/1200px-React-icon.svg.png", 50, True],
["https://upload.wikimedia.org/wikipedia/commons/thumb/6/61/HTML5_logo_and_wordmark.svg/1200px-HTML5_logo_and_wordmark.svg.png", 30, True]
],
inputs=[input_image, max_colors, sort_by_hue],
outputs=[output_image, status_text],
fn=process_image
)
if __name__ == "__main__":
demo.launch() |