import gradio as gr from PIL import Image import numpy as np import cv2 import matplotlib.pyplot as plt from skimage import exposure from scipy import signal from skimage.color import rgb2gray # Fonctions de traitement d'image def load_image(image): return image def apply_negative(image): img_np = np.array(image) negative = 255 - img_np return Image.fromarray(negative) def binarize_image(image, threshold): img_np = np.array(image.convert('L')) _, binary = cv2.threshold(img_np, threshold, 255, cv2.THRESH_BINARY) return Image.fromarray(binary) def resize_image(image, width, height): return image.resize((width, height)) def rotate_image(image, angle): return image.rotate(angle) def histogram(image): img_np = np.array(image) gray = rgb2gray(img_np) hist, _ = exposure.histogram(gray) plt.figure(figsize=(6, 4)) plt.title('Histogramme en nuances de gris') plt.xlabel('Intensité des pixels') plt.ylabel('Nombre de pixels') plt.bar(np.arange(len(hist)), hist, width=0.5, color='gray') plt.tight_layout() plt.show() def mean_filter(image): img_np = np.array(image) mean_filtered = cv2.blur(img_np, (5, 5)) # Filtre moyen 5x5 return Image.fromarray(mean_filtered) def gaussian_filter(image): img_np = np.array(image) gaussian_filtered = cv2.GaussianBlur(img_np, (5, 5), 0) # Filtre gaussien 5x5 return Image.fromarray(gaussian_filtered) def contour_extract(image): img_np = np.array(image.convert('L')) kernel = np.array([[0, 0, 0], [-1, 1, 0], [0, 0, 0]]) img_contour = signal.convolve2d(img_np, kernel, boundary='symm', mode='same') return Image.fromarray(np.uint8(np.absolute(img_contour))) def morph_erosion(image): img_np = np.array(image.convert('L')) # Conversion en niveaux de gris kernel = np.ones((5, 5), np.uint8) # Noyau 5x5 pour l'érosion erosion = cv2.erode(img_np, kernel, iterations=1) return Image.fromarray(erosion) def morph_dilation(image): img_np = np.array(image.convert('L')) # Conversion en niveaux de gris kernel = np.ones((5, 5), np.uint8) # Noyau 5x5 pour la dilatation dilation = cv2.dilate(img_np, kernel, iterations=1) return Image.fromarray(dilation) # Sauvegarder l'image sur l'ordinateur def save_image(image): img_np = np.array(image) save_path = "image_modifiee.png" cv2.imwrite(save_path, cv2.cvtColor(img_np, cv2.COLOR_RGB2BGR)) # Sauvegarder en format PNG return save_path # Interface Gradio def image_processing(image, operation, threshold=128, width=100, height=100, angle=0): if operation == "Négatif": return apply_negative(image) elif operation == "Binarisation": return binarize_image(image, threshold) elif operation == "Redimensionner": return resize_image(image, width, height) elif operation == "Rotation": return rotate_image(image, angle) elif operation == "Histogramme": histogram(image) # Affichage seulement return image elif operation == "Filtre moyen": return mean_filter(image) elif operation == "Filtre gaussien": return gaussian_filter(image) elif operation == "Contours": return contour_extract(image) elif operation == "Erosion": return morph_erosion(image) elif operation == "Dilatation": return morph_dilation(image) return image # Mise à jour dynamique de la visibilité des champs en fonction de l'opération def update_visibility(operation): return { "threshold": operation == "Binarisation", "width": operation == "Redimensionner", "height": operation == "Redimensionner", "angle": operation == "Rotation" } # Interface Gradio avec style custom_css = """ #main-header { color: #4CAF50; /* Vert clair */ font-family: 'Arial', sans-serif; text-align: center; } #upload-area { border: 2px solid #FF9800; /* Orange */ background-color: #FFF3E0; } #result-area { border: 2px solid #4CAF50; background-color: #E8F5E9; } #process-button { background-color: #FF9800; /* Orange */ color: white; font-size: 16px; } """ with gr.Blocks(css=custom_css) as demo: gr.Markdown("## 🌈 PixelCrafter: Transformez vos images avec style 🎨") with gr.Row(): image_input = gr.Image(type="pil", label="Charger Image") operation = gr.Radio( ["Négatif", "Binarisation", "Redimensionner", "Rotation", "Histogramme", "Filtre moyen", "Filtre gaussien", "Contours", "Erosion", "Dilatation"], label="Opération", value="Négatif" ) threshold = gr.Slider(0, 255, 128, label="Seuil de binarisation", visible=False) width = gr.Number(value=100, label="Largeur", visible=False) height = gr.Number(value=100, label="Hauteur", visible=False) angle = gr.Number(value=0, label="Angle de Rotation", visible=False) image_output = gr.Image(label="Image Modifiée") # Mise à jour de la visibilité des champs operation.change(update_visibility, inputs=operation, outputs=[threshold, width, height, angle]) # Bouton d'application submit_button = gr.Button("Appliquer") submit_button.click(image_processing, inputs=[image_input, operation, threshold, width, height, angle], outputs=image_output) # Sauvegarde de l'image save_button = gr.Button("Sauvegarder l'image") save_button.click(save_image, inputs=image_output, outputs=gr.File(label="Télécharger l'image")) # Lancer l'application Gradio demo.launch()