om440's picture
Upload 12 files
a966d70 verified
Raw
History Blame Contribute Delete
4.13 kB
import gradio as gr
import cv2
import numpy as np
from PIL import Image
IMG_SIZE = 256
REFERENCE_PATH = "reference_bottle.npy"
THRESHOLD_SCORE = 400
reference = np.load(REFERENCE_PATH)
def detect_classical(input_image):
if input_image is None:
return "<h2>Veuillez importer une image.</h2>", None, None, None
img_rgb = np.array(input_image.convert("RGB"))
img_rgb = cv2.resize(img_rgb, (IMG_SIZE, IMG_SIZE))
gray = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2GRAY)
diff = cv2.absdiff(gray, reference)
diff_blur = cv2.GaussianBlur(diff, (5, 5), 0)
_, mask = cv2.threshold(diff_blur, 35, 255, cv2.THRESH_BINARY)
kernel = np.ones((5, 5), np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
anomaly_score = int(np.sum(mask > 0))
if anomaly_score > THRESHOLD_SCORE:
prediction = "DÉFECTUEUSE"
color = "#c0392b"
emoji = "❌"
else:
prediction = "BONNE"
color = "#27ae60"
emoji = "✅"
result_html = f"""
<div style="
text-align:center;
padding:25px;
border-radius:18px;
background-color:#f8f9fa;
border:3px solid {color};
">
<h1 style="color:{color}; font-size:44px;">
{emoji} Prédiction : {prediction}
</h1>
<p style="font-size:24px;">
Score d'anomalie : <b>{anomaly_score}</b>
</p>
<p style="font-size:20px;">
Seuil utilisé : <b>{THRESHOLD_SCORE}</b>
</p>
</div>
"""
return result_html, img_rgb, diff, mask
custom_css = """
.gradio-container {
max-width: 1250px !important;
margin: auto !important;
}
h1 {
font-size: 26px !important;
margin-bottom: 5px !important;
}
.compact-text {
font-size: 14px !important;
margin-bottom: 5px !important;
}
footer {
display: none !important;
}
"""
example_paths = [
"examples/good_141.png",
"examples/good_093.png",
"examples/good_146.png",
"examples/defect_017bd.png",
"examples/defect_004sd.png",
"examples/defect_010c.png",
"examples/defect_016sd.png",
]
def load_gallery_example(evt: gr.SelectData):
image_path = example_paths[evt.index]
image = Image.open(image_path).convert("RGB")
result_html, original, diff, mask = detect_classical(image)
return image, result_html, original, diff, mask
with gr.Blocks(
title="Détection de défauts - Méthode classique",
css=custom_css
) as demo:
gr.Markdown(
"""
# Détection de défauts sur bouteilles - Méthode classique
<p class="compact-text">
Comparaison avec une image de référence + score d'anomalie. Importer une image ou cliquer sur un exemple.
</p>
"""
)
with gr.Row():
with gr.Column(scale=1):
input_image = gr.Image(
type="pil",
label="Image à analyser",
height=260
)
button = gr.Button("Analyser l'image", variant="primary")
with gr.Column(scale=1):
result_output = gr.HTML(label="Résultat")
with gr.Row():
original_output = gr.Image(label="Image analysée", height=160)
diff_output = gr.Image(label="Différence", height=160)
mask_output = gr.Image(label="Masque", height=160)
gr.Markdown("### Exemples de test")
gallery = gr.Gallery(
value=example_paths,
label="Cliquer sur une image pour la tester",
columns=7,
height=140,
object_fit="contain",
allow_preview=False
)
button.click(
fn=detect_classical,
inputs=input_image,
outputs=[
result_output,
original_output,
diff_output,
mask_output
]
)
gallery.select(
fn=load_gallery_example,
inputs=None,
outputs=[
input_image,
result_output,
original_output,
diff_output,
mask_output
]
)
demo.launch()