aboalaa147 commited on
Commit
4bb0dc0
·
verified ·
1 Parent(s): 45ec269

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +175 -0
app.py ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import matplotlib.pyplot as plt
4
+ from PIL import Image
5
+ import io
6
+ from stringart import StringArtGenerator
7
+
8
+ def generate_string_art(image, num_nails, iterations, weight, shape):
9
+ """Generate string art from uploaded image"""
10
+ if image is None:
11
+ return None
12
+
13
+ try:
14
+ # Initialize generator
15
+ generator = StringArtGenerator()
16
+
17
+ # Convert PIL image to numpy array and set it directly
18
+ np_img = np.array(image)
19
+ generator.image = image
20
+ generator.data = np.flipud(np_img).transpose()
21
+
22
+ # Preprocess
23
+ generator.preprocess()
24
+ generator.set_nails(int(num_nails))
25
+ generator.set_iterations(int(iterations))
26
+ generator.set_weight(int(weight))
27
+ generator.set_shape(shape)
28
+ generator.set_seed(42)
29
+
30
+ # Generate pattern
31
+ pattern = generator.generate()
32
+
33
+ if len(pattern) == 0:
34
+ return None
35
+
36
+ # Create visualization
37
+ lines_x = []
38
+ lines_y = []
39
+ for i in range(len(pattern)-1):
40
+ lines_x.extend([pattern[i][0], pattern[i+1][0], None])
41
+ lines_y.extend([pattern[i][1], pattern[i+1][1], None])
42
+
43
+ # Create plot
44
+ fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 8))
45
+
46
+ # Original image
47
+ ax1.imshow(generator.image, cmap='gray')
48
+ ax1.set_title('Original Image (Preprocessed)')
49
+ ax1.axis('off')
50
+
51
+ # String art
52
+ xmin, ymin = 0., 0.
53
+ xmax = generator.data.shape[0]
54
+ ymax = generator.data.shape[1]
55
+
56
+ ax2.set_xlim([xmin, xmax])
57
+ ax2.set_ylim([ymin, ymax])
58
+ ax2.set_aspect('equal')
59
+ ax2.axis('off')
60
+ ax2.set_title(f'String Art ({len(pattern)} connections)')
61
+ ax2.set_facecolor('white')
62
+
63
+ # Plot all lines at once for better performance
64
+ ax2.plot(lines_x, lines_y, linewidth=0.15, color='black', alpha=0.8)
65
+
66
+ plt.tight_layout()
67
+
68
+ # Save to buffer
69
+ buf = io.BytesIO()
70
+ plt.savefig(buf, format='png', bbox_inches='tight', dpi=150, facecolor='white')
71
+ buf.seek(0)
72
+ plt.close()
73
+
74
+ # Return image
75
+ result_image = Image.open(buf)
76
+ return result_image
77
+
78
+ except Exception as e:
79
+ print(f"Error: {str(e)}")
80
+ return None
81
+
82
+ # Create Gradio interface
83
+ with gr.Blocks(
84
+ title="String Art Generator",
85
+ theme=gr.themes.Soft(),
86
+ css="""
87
+ .gradio-container {
88
+ max-width: 1200px !important;
89
+ }
90
+ """
91
+ ) as demo:
92
+
93
+ gr.Markdown("""
94
+ # 🎨 String Art Generator
95
+
96
+ Transform your images into beautiful string art! Upload an image and watch as an algorithm recreates it using virtual string connections between nails.
97
+
98
+ **How it works:** The algorithm places nails around a circle/rectangle, then iteratively finds the darkest paths between nails to recreate your image.
99
+ """)
100
+
101
+ with gr.Row():
102
+ with gr.Column(scale=1):
103
+ gr.Markdown("### 📤 Input")
104
+ image_input = gr.Image(
105
+ type="pil",
106
+ label="Upload Your Image",
107
+ sources=["upload"],
108
+ height=300
109
+ )
110
+
111
+ gr.Markdown("### ⚙️ Settings")
112
+ with gr.Row():
113
+ num_nails = gr.Slider(
114
+ minimum=50,
115
+ maximum=200,
116
+ value=120,
117
+ step=10,
118
+ label="Number of Nails",
119
+ info="More nails = more detail, but slower processing"
120
+ )
121
+ iterations = gr.Slider(
122
+ minimum=500,
123
+ maximum=3000,
124
+ value=1500,
125
+ step=100,
126
+ label="Iterations",
127
+ info="More iterations = better quality, but slower"
128
+ )
129
+
130
+ with gr.Row():
131
+ weight = gr.Slider(
132
+ minimum=5,
133
+ maximum=40,
134
+ value=20,
135
+ step=5,
136
+ label="Line Weight",
137
+ info="Thickness of virtual string"
138
+ )
139
+ shape = gr.Dropdown(
140
+ choices=["circle", "rectangle"],
141
+ value="circle",
142
+ label="Nail Arrangement",
143
+ info="Shape for nail placement"
144
+ )
145
+
146
+ generate_btn = gr.Button(
147
+ "🎨 Generate String Art",
148
+ variant="primary",
149
+ size="lg"
150
+ )
151
+
152
+ gr.Markdown("""
153
+ ### 💡 Tips:
154
+ - High contrast images work best
155
+ - Simple compositions are ideal
156
+ - Processing may take 1-3 minutes
157
+ - Start with lower settings for faster results
158
+ """)
159
+
160
+ with gr.Column(scale=1):
161
+ gr.Markdown("### 🎯 Result")
162
+ output_image = gr.Image(
163
+ label="Generated String Art",
164
+ height=600
165
+ )
166
+
167
+ generate_btn.click(
168
+ fn=generate_string_art,
169
+ inputs=[image_input, num_nails, iterations, weight, shape],
170
+ outputs=output_image,
171
+ show_progress=True
172
+ )
173
+
174
+ if __name__ == "__main__":
175
+ demo.launch()