huggingkhalil's picture
Create app.py
1a192ff verified
import cv2
import numpy as np
import gradio as gr
from PIL import Image
def detect_shapes(image):
"""
Detect shapes in an image and return the annotated result
"""
# Convert PIL Image to OpenCV format
img = np.array(image)
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
# Create a copy for drawing contours
img_contour = img.copy()
# Convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Apply Gaussian blur
blur = cv2.GaussianBlur(gray, (5, 5), 1)
# Edge detection
edges = cv2.Canny(blur, 50, 150)
# Find contours
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
shapes_detected = []
# Process each contour
for cnt in contours:
area = cv2.contourArea(cnt)
if area > 500: # Filter small contours
# Approximate contour to polygon
epsilon = 0.02 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
# Get bounding rectangle
x, y, w, h = cv2.boundingRect(approx)
# Determine shape based on number of vertices
nb_sommets = len(approx)
shape = "Indéfini"
if nb_sommets == 3:
shape = "Triangle"
elif nb_sommets == 4:
ratio = w / float(h)
shape = "Carré" if 0.95 < ratio < 1.05 else "Rectangle"
elif nb_sommets > 6:
shape = "Cercle"
# Draw contour and label
cv2.drawContours(img_contour, [approx], 0, (0, 255, 0), 2)
cv2.putText(img_contour, shape, (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
shapes_detected.append({
'shape': shape,
'vertices': nb_sommets,
'area': int(area),
'position': f"({x}, {y})"
})
# Convert back to RGB for display
img_contour = cv2.cvtColor(img_contour, cv2.COLOR_BGR2RGB)
# Create summary text
summary = f"Détecté {len(shapes_detected)} forme(s):\n"
for i, shape_info in enumerate(shapes_detected, 1):
summary += f"{i}. {shape_info['shape']} - {shape_info['vertices']} sommets - Aire: {shape_info['area']} pixels\n"
return img_contour, summary
# Create Gradio interface
def create_interface():
with gr.Blocks(title="Détecteur de Formes Géométriques", theme=gr.themes.Soft()) as interface:
gr.Markdown("# 🔍 Détecteur de Formes Géométriques")
gr.Markdown("Téléchargez une image pour détecter et identifier les formes géométriques (triangles, carrés, rectangles, cercles)")
with gr.Row():
with gr.Column():
input_image = gr.Image(
type="pil",
label="📸 Image d'entrée",
height=400
)
detect_btn = gr.Button(
"🔍 Détecter les formes",
variant="primary",
size="lg"
)
gr.Markdown("### Instructions:")
gr.Markdown("""
- Téléchargez une image contenant des formes géométriques
- Les formes doivent être suffisamment grandes (aire > 500 pixels)
- Fonctionne mieux avec des formes aux contours nets
- Supporte: triangles, carrés, rectangles, cercles
""")
with gr.Column():
output_image = gr.Image(
label="🎯 Formes détectées",
height=400
)
output_text = gr.Textbox(
label="📊 Résumé de détection",
lines=8,
max_lines=15
)
# Examples section
gr.Markdown("### 📝 Exemples")
gr.Examples(
examples=[
# You can add example images here if you have them
# ["path/to/example1.jpg"],
# ["path/to/example2.jpg"],
],
inputs=input_image,
label="Cliquez sur un exemple pour le tester"
)
# Event handlers
detect_btn.click(
fn=detect_shapes,
inputs=input_image,
outputs=[output_image, output_text]
)
input_image.change(
fn=detect_shapes,
inputs=input_image,
outputs=[output_image, output_text]
)
return interface
# Launch the app
if __name__ == "__main__":
interface = create_interface()
interface.launch(
share=True,
server_name="0.0.0.0",
server_port=7860
)