ImageMaster / app.py
Ynvers's picture
Correction
14da26f
import gradio as gr
from PIL import Image
import numpy as np
import cv2
import matplotlib.pyplot as plt
# Fonctions de traitement d'image
def load_image(image):
return image
def apply_negative(image):
"""
Transforme l'image en son négatif en inversant les valeurs de chaque pixel.
En résumé chaque pixel est soustrait de 255.
"""
img = np.array(image)
negative = 255 - img
return Image.fromarray(negative)
def binarize_image(image, threshold):
"""
D'abord l'image est convertie en niveau de gris.
Puis on utilise un seuil moyen pour la binarison de l'image.
"""
img = np.array(image)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_binary = np.where( img_gray < threshold, 0, 255).astype(np.uint8)
return Image.fromarray(img_binary)
def resize_image(image, width, height):
"""
Demande à l'utilisateur de choisir la hauteur et la largeur finale de l'image.
Ensuite resize cette image à partir de ces informations
"""
return image.resize((width, height))
def rotate_image(image, angle):
"""
Faire tourner l'image sur des angles données
"""
return image.rotate(angle)
def histogramme(image):
"""
Afficher l'histogramme de l'image.
La fonction fait la différence entre les images à un canal et celles à trois
"""
img_array = np.array(image)
gray_image = cv2.cvtColor(img_array, cv2.COLOR_RGB2GRAY)
fig, axis = plt.subplots(figsize=(8, 4))
axis.set_title("Histogramme des niveaux de gris")
histo = cv2.calcHist([img_array], [0], None, [256], [0, 256])
axis.plot(histo, color='black')
fig.canvas.draw()
data = np.frombuffer(fig.canvas.buffer_rgba(), dtype=np.uint8)
data = data.reshape(fig.canvas.get_width_height()[::-1] + (4,))
plt.close(fig)
return Image.fromarray(data[:,:,:3])
def contours_Sobel(image):
"""
Détecter et afficher les contours des images
"""
img = np.array(image)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=5)
sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=5)
sobel = np.sqrt(sobel_x**2 + sobel_y**2)
sobel = np.uint8(sobel)
return Image.fromarray(sobel)
def filtre_Gaussien(image, kernel_size=5):
"""
Appliquer un Filtre Gaussien avec une matrice définissable par l'utilisateur à l'image
"""
img = np.array(image)
flou = cv2.GaussianBlur(img, (kernel_size, kernel_size), 0)
return Image.fromarray(flou)
def erosion(image):
croix = np.array([
[0,1,0],
[1,1,1],
[0,1,0]], dtype=np.uint8)
croix = croix*255
image_test = np.array(image)
img_erosion = cv2.erode(image_test, croix)
return Image.fromarray(img_erosion)
def dilatation(image):
croix = np.array([
[0,1,0],
[1,1,1],
[0,1,0]], dtype=np.uint8)
croix = croix*255
image_test = np.array(image)
img_dilate = cv2.dilate(image_test, croix)
return Image.fromarray(img_dilate)
def update_fields(operation):
if operation == "Redimensionner":
return (gr.update(visible=True),
gr.update(visible=True),
gr.update(visible=False),
gr.update(visible=False),
gr.update(visible=False))
elif operation == "Binarisation":
return (gr.update(visible=False),
gr.update(visible=False),
gr.update(visible=True),
gr.update(visible=False),
gr.update(visible=False))
elif operation == "Rotation":
return (gr.update(visible=False),
gr.update(visible=False),
gr.update(visible=False),
gr.update(visible=True),
gr.update(visible=False))
elif operation == "Filtre Gaussien":
return (gr.update(visible=False),
gr.update(visible=False),
gr.update(visible=False),
gr.update(visible=False),
gr.update(visible=True))
else:
return (gr.update(visible=False),
gr.update(visible=False),
gr.update(visible=False),
gr.update(visible=False),
gr.update(visible=False))
def image_processing(image, operation, threshold=128, width=100, height=100, angle=0, kernel_size=5):
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 == "Contours Sobel":
return contours_Sobel(image)
elif operation == "Filtre Gaussien":
return filtre_Gaussien(image, kernel_size)
elif operation == "Erosion":
return erosion(image)
elif operation == "Dilatation":
return dilatation(image)
return image
def load_image_and_histogram(image):
hist_image = histogramme(image)
return hist_image
# Interface Gradio
with gr.Blocks() as demo:
gr.Markdown("## Image Master")
with gr.Row():
image_input = gr.Image(
type="pil",
label="Charger Image"
)
operation = gr.Radio(
["Négatif",
"Binarisation",
"Redimensionner",
"Rotation",
"Contours Sobel",
"Filtre Gaussien",
"Erosion",
"Dilatation"
],
label="Opération")
threshold = gr.Slider(0, 255, 128, label="Seuil de binarisation", visible=False)
width = gr.Slider(minimum=50, maximum=1000, value=100, step=10, label="Largeur", visible=False)
height = gr.Slider(minimum=50, maximum=1000, value=100, step=10, label="Hauteur", visible=False)
angle = gr.Slider(minimum=-180, maximum=180, value=0, step=1, label="Angle de Rotation", visible=False)
kernel_size = gr.Slider(minimum=1, maximum=21, value=5, step=2, label="Taille du Noyau (Flou)", visible=False)
image_output = gr.Image(label="Image Modifiée")
submit_button = gr.Button("Appliquer")
histogram_output = gr.Image(label="Histogramme")
operation.change(update_fields, inputs=[operation], outputs=[width, height, threshold, angle, kernel_size])
image_input.change(load_image_and_histogram, inputs=image_input, outputs=histogram_output)
submit_button.click(image_processing, inputs=[image_input, operation, threshold, width, height, angle, kernel_size], outputs=image_output)
demo.launch()