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
    )