Spaces:
Sleeping
Sleeping
File size: 4,961 Bytes
1a192ff | 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 | 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
) |