Gertie01 commited on
Commit
ddd1937
·
verified ·
1 Parent(s): 4b644df

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. app.py +512 -0
  2. requirements.txt +1 -0
app.py ADDED
@@ -0,0 +1,512 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ from PIL import Image, ImageDraw, ImageFilter, ImageEnhance
4
+ import cv2
5
+ import math
6
+ import random
7
+ from typing import Tuple, Optional
8
+
9
+ def create_spiral_illusion(width: int = 512, height: int = 512,
10
+ spiral_count: int = 5,
11
+ rotation_speed: float = 0.5,
12
+ color_scheme: str = "rainbow") -> Image.Image:
13
+ """Create a spiral optical illusion."""
14
+ img = Image.new('RGB', (width, height), color='white')
15
+ draw = ImageDraw.Draw(img)
16
+
17
+ center_x, center_y = width // 2, height // 2
18
+ max_radius = min(width, height) // 2
19
+
20
+ colors = {
21
+ "rainbow": ['#FF0000', '#FF7F00', '#FFFF00', '#00FF00', '#0000FF', '#4B0082', '#9400D3'],
22
+ "blue": ['#000080', '#0000FF', '#4169E1', '#1E90FF', '#00BFFF', '#87CEEB'],
23
+ "warm": ['#FF0000', '#FF4500', '#FF6347', '#FF7F50', '#FFA500', '#FFD700'],
24
+ "cool": ['#00CED1', '#48D1CC', '#40E0D0', '#00FFFF', '#00CED1', '#4682B4']
25
+ }
26
+
27
+ palette = colors.get(color_scheme, colors["rainbow"])
28
+
29
+ for i in range(max_radius):
30
+ angle = (i * rotation_speed) % (2 * math.pi)
31
+ spiral_offset = math.sin(i * 0.1) * 10
32
+
33
+ for j in range(spiral_count):
34
+ spiral_angle = angle + (j * 2 * math.pi / spiral_count)
35
+ x = center_x + (i + spiral_offset) * math.cos(spiral_angle)
36
+ y = center_y + (i + spiral_offset) * math.sin(spiral_angle)
37
+
38
+ color_idx = (i + j * 20) % len(palette)
39
+ draw.ellipse([x-3, y-3, x+3, y+3], fill=palette[color_idx])
40
+
41
+ return img
42
+
43
+ def create_wave_distortion(input_image: Image.Image,
44
+ wave_amplitude: float = 20,
45
+ wave_frequency: float = 0.05,
46
+ direction: str = "horizontal") -> Image.Image:
47
+ """Apply wave distortion to create illusion effect."""
48
+ img_array = np.array(input_image)
49
+ h, w = img_array.shape[:2]
50
+
51
+ output = np.zeros_like(img_array)
52
+
53
+ for y in range(h):
54
+ for x in range(w):
55
+ if direction == "horizontal":
56
+ offset = int(wave_amplitude * math.sin(x * wave_frequency))
57
+ new_x = (x + offset) % w
58
+ output[y, x] = img_array[y, new_x]
59
+ else:
60
+ offset = int(wave_amplitude * math.sin(y * wave_frequency))
61
+ new_y = (y + offset) % h
62
+ output[y, x] = img_array[new_y, x]
63
+
64
+ return Image.fromarray(output)
65
+
66
+ def create_tunnel_illusion(width: int = 512, height: int = 512,
67
+ rings: int = 20,
68
+ perspective: float = 0.8) -> Image.Image:
69
+ """Create a tunnel/depth illusion."""
70
+ img = Image.new('RGB', (width, height), color='black')
71
+ draw = ImageDraw.Draw(img)
72
+
73
+ center_x, center_y = width // 2, height // 2
74
+
75
+ for i in range(rings, 0, -1):
76
+ radius = int((width // 2) * (i / rings) ** perspective)
77
+
78
+ # Alternating colors for depth effect
79
+ if i % 2 == 0:
80
+ color = (255, 255, 255)
81
+ else:
82
+ gray_value = int(255 * (1 - i / rings))
83
+ color = (gray_value, gray_value, gray_value)
84
+
85
+ draw.ellipse([center_x - radius, center_y - radius,
86
+ center_x + radius, center_y + radius],
87
+ outline=color, width=max(1, int(rings / 10)))
88
+
89
+ return img
90
+
91
+ def create_moire_pattern(width: int = 512, height: int = 512,
92
+ line_spacing: int = 10,
93
+ angle_offset: float = 5) -> Image.Image:
94
+ """Create a moiré pattern illusion."""
95
+ img = Image.new('RGB', (width, height), color='white')
96
+ draw = ImageDraw.Draw(img)
97
+
98
+ # First set of lines
99
+ for x in range(0, width, line_spacing):
100
+ draw.line([(x, 0), (x, height)], fill='black', width=2)
101
+
102
+ # Second set of lines at slight angle
103
+ angle_rad = math.radians(angle_offset)
104
+ for i in range(-width, width * 2, line_spacing):
105
+ x1 = i
106
+ y1 = 0
107
+ x2 = i + height * math.tan(angle_rad)
108
+ y2 = height
109
+
110
+ # Clip to image bounds
111
+ points = []
112
+ for x, y in [(x1, y1), (x2, y2)]:
113
+ x = max(0, min(width - 1, int(x)))
114
+ y = max(0, min(height - 1, int(y)))
115
+ points.append((x, y))
116
+
117
+ if len(points) == 2:
118
+ draw.line(points, fill='black', width=2)
119
+
120
+ return img
121
+
122
+ def create_rotating_grid illusion(width: int = 512, height: int = 512,
123
+ grid_size: int = 20,
124
+ rotation: float = 15) -> Image.Image:
125
+ """Create a rotating grid illusion."""
126
+ img = Image.new('RGB', (width, height), color='white')
127
+ draw = ImageDraw.Draw(img)
128
+
129
+ center_x, center_y = width // 2, height // 2
130
+ angle_rad = math.radians(rotation)
131
+
132
+ # Draw grid with rotation
133
+ for i in range(-width, width, grid_size):
134
+ for j in range(-height, height, grid_size):
135
+ # Rotate grid points around center
136
+ x1 = center_x + i * math.cos(angle_rad) - j * math.sin(angle_rad)
137
+ y1 = center_y + i * math.sin(angle_rad) + j * math.cos(angle_rad)
138
+ x2 = center_x + (i + grid_size) * math.cos(angle_rad) - j * math.sin(angle_rad)
139
+ y2 = center_y + (i + grid_size) * math.sin(angle_rad) + j * math.cos(angle_rad)
140
+
141
+ # Only draw if within bounds
142
+ if (0 <= x1 <= width and 0 <= y1 <= height) or (0 <= x2 <= width and 0 <= y2 <= height):
143
+ draw.line([(x1, y1), (x2, y2)], fill='black', width=1)
144
+
145
+ x3 = center_x + i * math.cos(angle_rad) - (j + grid_size) * math.sin(angle_rad)
146
+ y3 = center_y + i * math.sin(angle_rad) + (j + grid_size) * math.cos(angle_rad)
147
+
148
+ if (0 <= x1 <= width and 0 <= y1 <= height) or (0 <= x3 <= width and 0 <= y3 <= height):
149
+ draw.line([(x1, y1), (x3, y3)], fill='black', width=1)
150
+
151
+ return img
152
+
153
+ def apply_illusion(input_image: Optional[Image.Image],
154
+ illusion_type: str,
155
+ intensity: float = 1.0,
156
+ **params) -> Image.Image:
157
+ """Apply selected illusion effect to image or generate new illusion."""
158
+
159
+ if input_image is None and illusion_type not in ["spiral", "tunnel", "moire", "rotating_grid"]:
160
+ # Create a default pattern for image-based effects
161
+ input_image = create_gradient_pattern()
162
+
163
+ if illusion_type == "spiral":
164
+ return create_spiral_illusion(
165
+ spiral_count=int(params.get('spiral_count', 5)),
166
+ rotation_speed=params.get('rotation_speed', 0.5),
167
+ color_scheme=params.get('color_scheme', 'rainbow')
168
+ )
169
+
170
+ elif illusion_type == "wave":
171
+ return create_wave_distortion(
172
+ input_image,
173
+ wave_amplitude=int(params.get('wave_amplitude', 20)),
174
+ wave_frequency=params.get('wave_frequency', 0.05),
175
+ direction=params.get('direction', 'horizontal')
176
+ )
177
+
178
+ elif illusion_type == "tunnel":
179
+ return create_tunnel_illusion(
180
+ rings=int(params.get('rings', 20)),
181
+ perspective=params.get('perspective', 0.8)
182
+ )
183
+
184
+ elif illusion_type == "moire":
185
+ return create_moire_pattern(
186
+ line_spacing=int(params.get('line_spacing', 10)),
187
+ angle_offset=params.get('angle_offset', 5)
188
+ )
189
+
190
+ elif illusion_type == "rotating_grid":
191
+ return create_rotating_grid_illusion(
192
+ grid_size=int(params.get('grid_size', 20)),
193
+ rotation=params.get('rotation', 15)
194
+ )
195
+
196
+ elif illusion_type == "kaleidoscope":
197
+ return create_kaleidoscope(input_image, segments=int(params.get('segments', 6)))
198
+
199
+ elif illusion_type == "pinch":
200
+ return create_pinch_distortion(input_image, strength=params.get('strength', 0.5))
201
+
202
+ elif illusion_type == "twirl":
203
+ return create_twirl_effect(input_image, angle=params.get('twirl_angle', 180))
204
+
205
+ return input_image
206
+
207
+ def create_gradient_pattern(width: int = 512, height: int = 512) -> Image.Image:
208
+ """Create a gradient pattern as default input."""
209
+ img = Image.new('RGB', (width, height))
210
+ draw = ImageDraw.Draw(img)
211
+
212
+ for x in range(width):
213
+ for y in range(height):
214
+ r = int(255 * x / width)
215
+ g = int(255 * y / height)
216
+ b = int(255 * (x + y) / (width + height))
217
+ draw.point((x, y), fill=(r, g, b))
218
+
219
+ return img
220
+
221
+ def create_kaleidoscope(input_image: Image.Image, segments: int = 6) -> Image.Image:
222
+ """Create kaleidoscope effect."""
223
+ width, height = input_image.size
224
+ result = Image.new('RGB', (width, height))
225
+
226
+ center_x, center_y = width // 2, height // 2
227
+
228
+ for i in range(segments):
229
+ angle = (360 / segments) * i
230
+
231
+ # Rotate and copy segment
232
+ rotated = input_image.rotate(angle, expand=False)
233
+
234
+ # Create mask for this segment
235
+ mask = Image.new('L', (width, height), 0)
236
+ mask_draw = ImageDraw.Draw(mask)
237
+
238
+ start_angle = i * (360 / segments)
239
+ end_angle = (i + 1) * (360 / segments)
240
+
241
+ # Draw pie slice
242
+ mask_draw.pieslice([0, 0, width, height], start_angle, end_angle, fill=255)
243
+
244
+ # Apply to result
245
+ result.paste(rotated, mask=mask)
246
+
247
+ return result
248
+
249
+ def create_pinch_distortion(input_image: Image.Image, strength: float = 0.5) -> Image.Image:
250
+ """Create pinch/bulge distortion."""
251
+ img_array = np.array(input_image)
252
+ h, w = img_array.shape[:2]
253
+
254
+ output = np.zeros_like(img_array)
255
+ center_x, center_y = w // 2, h // 2
256
+ max_radius = min(w, h) // 2
257
+
258
+ for y in range(h):
259
+ for x in range(w):
260
+ dx = x - center_x
261
+ dy = y - center_y
262
+ distance = math.sqrt(dx**2 + dy**2)
263
+
264
+ if distance < max_radius:
265
+ factor = 1 - strength * (1 - distance / max_radius)
266
+ new_x = int(center_x + dx * factor)
267
+ new_y = int(center_y + dy * factor)
268
+
269
+ if 0 <= new_x < w and 0 <= new_y < h:
270
+ output[y, x] = img_array[new_y, new_x]
271
+ else:
272
+ output[y, x] = img_array[y, x]
273
+
274
+ return Image.fromarray(output)
275
+
276
+ def create_twirl_effect(input_image: Image.Image, angle: float = 180) -> Image.Image:
277
+ """Create twirl/swirl distortion."""
278
+ img_array = np.array(input_image)
279
+ h, w = img_array.shape[:2]
280
+
281
+ output = np.zeros_like(img_array)
282
+ center_x, center_y = w // 2, h // 2
283
+ max_radius = min(w, h) // 2
284
+
285
+ for y in range(h):
286
+ for x in range(w):
287
+ dx = x - center_x
288
+ dy = y - center_y
289
+ distance = math.sqrt(dx**2 + dy**2)
290
+
291
+ if distance < max_radius:
292
+ current_angle = math.atan2(dy, dx)
293
+ twist_angle = (angle * math.pi / 180) * (1 - distance / max_radius)
294
+ new_angle = current_angle + twist_angle
295
+
296
+ new_x = int(center_x + distance * math.cos(new_angle))
297
+ new_y = int(center_y + distance * math.sin(new_angle))
298
+
299
+ if 0 <= new_x < w and 0 <= new_y < h:
300
+ output[y, x] = img_array[new_y, new_x]
301
+ else:
302
+ output[y, x] = img_array[y, x]
303
+
304
+ return Image.fromarray(output)
305
+
306
+ # Create the Gradio interface
307
+ with gr.Blocks() as demo:
308
+ gr.Markdown("# 🌀 Illusion Diffusion Studio")
309
+ gr.Markdown("Create stunning optical illusions and mind-bending visual effects! Upload an image or generate patterns from scratch.")
310
+ gr.HTML('<div style="text-align: center; margin-bottom: 20px;"><a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color: #007bff; text-decoration: none; font-weight: bold;">Built with anycoder</a></div>')
311
+
312
+ with gr.Row():
313
+ with gr.Column(scale=1):
314
+ gr.Markdown("### 📤 Input Image (Optional)")
315
+ input_image = gr.Image(
316
+ label="Upload Image",
317
+ type="pil",
318
+ sources=["upload", "webcam", "clipboard"],
319
+ height=300
320
+ )
321
+
322
+ gr.Markdown("### 🎨 Illusion Type")
323
+ illusion_type = gr.Dropdown(
324
+ choices=[
325
+ ("Spiral Illusion", "spiral"),
326
+ ("Wave Distortion", "wave"),
327
+ ("Tunnel Effect", "tunnel"),
328
+ ("Moiré Pattern", "moire"),
329
+ ("Rotating Grid", "rotating_grid"),
330
+ ("Kaleidoscope", "kaleidoscope"),
331
+ ("Pinch Distortion", "pinch"),
332
+ ("Twirl Effect", "twirl")
333
+ ],
334
+ value="spiral",
335
+ label="Select Illusion Type"
336
+ )
337
+
338
+ gr.Markdown("### ⚙️ Parameters")
339
+
340
+ with gr.Group(visible=True) as spiral_params:
341
+ spiral_count = gr.Slider(3, 10, value=5, step=1, label="Spiral Count")
342
+ rotation_speed = gr.Slider(0.1, 2.0, value=0.5, step=0.1, label="Rotation Speed")
343
+ color_scheme = gr.Dropdown(
344
+ ["rainbow", "blue", "warm", "cool"],
345
+ value="rainbow",
346
+ label="Color Scheme"
347
+ )
348
+
349
+ with gr.Group(visible=False) as wave_params:
350
+ wave_amplitude = gr.Slider(5, 50, value=20, step=5, label="Wave Amplitude")
351
+ wave_frequency = gr.Slider(0.01, 0.2, value=0.05, step=0.01, label="Wave Frequency")
352
+ direction = gr.Radio(["horizontal", "vertical"], value="horizontal", label="Direction")
353
+
354
+ with gr.Group(visible=False) as tunnel_params:
355
+ rings = gr.Slider(10, 50, value=20, step=5, label="Number of Rings")
356
+ perspective = gr.Slider(0.5, 1.5, value=0.8, step=0.1, label="Perspective")
357
+
358
+ with gr.Group(visible=False) as moire_params:
359
+ line_spacing = gr.Slider(5, 30, value=10, step=5, label="Line Spacing")
360
+ angle_offset = gr.Slider(1, 20, value=5, step=1, label="Angle Offset")
361
+
362
+ with gr.Group(visible=False) as grid_params:
363
+ grid_size = gr.Slider(10, 50, value=20, step=5, label="Grid Size")
364
+ rotation = gr.Slider(5, 45, value=15, step=5, label="Rotation Angle")
365
+
366
+ with gr.Group(visible=False) as kaleidoscope_params:
367
+ segments = gr.Slider(3, 12, value=6, step=1, label="Segments")
368
+
369
+ with gr.Group(visible=False) as pinch_params:
370
+ strength = gr.Slider(0.1, 1.0, value=0.5, step=0.1, label="Pinch Strength")
371
+
372
+ with gr.Group(visible=False) as twirl_params:
373
+ twirl_angle = gr.Slider(90, 360, value=180, step=30, label="Twirl Angle")
374
+
375
+ generate_btn = gr.Button("🎭 Generate Illusion", variant="primary", size="lg")
376
+
377
+ gr.Markdown("### 🎯 Quick Examples")
378
+ gr.Examples(
379
+ examples=[
380
+ [None, "spiral", 5, 0.5, "rainbow"],
381
+ [None, "wave", 20, 0.05, "horizontal"],
382
+ [None, "tunnel", 20, 0.8, ""],
383
+ [None, "moire", 10, 5, ""],
384
+ [None, "rotating_grid", 20, 15, ""],
385
+ ],
386
+ inputs=[input_image, illusion_type, spiral_count, rotation_speed, color_scheme],
387
+ label="Try these presets!"
388
+ )
389
+
390
+ with gr.Column(scale=1):
391
+ gr.Markdown("### ✨ Output")
392
+ output_image = gr.Image(
393
+ label="Generated Illusion",
394
+ type="pil",
395
+ height=400,
396
+ interactive=True
397
+ )
398
+
399
+ with gr.Row():
400
+ download_btn = gr.DownloadButton(
401
+ "💾 Download",
402
+ variant="secondary"
403
+ )
404
+ clear_btn = gr.Button("🗑️ Clear", variant="secondary")
405
+
406
+ gr.Markdown("### 📊 Effect Info")
407
+ info_text = gr.Markdown(
408
+ "Select an illusion type and adjust parameters to create your optical illusion. "
409
+ "Some effects work best with uploaded images, while others generate patterns from scratch."
410
+ )
411
+
412
+ # Update parameter visibility based on illusion type
413
+ def update_params(illusion_type):
414
+ return {
415
+ spiral_params: gr.Group(visible=(illusion_type == "spiral")),
416
+ wave_params: gr.Group(visible=(illusion_type == "wave")),
417
+ tunnel_params: gr.Group(visible=(illusion_type == "tunnel")),
418
+ moire_params: gr.Group(visible=(illusion_type == "moire")),
419
+ grid_params: gr.Group(visible=(illusion_type == "rotating_grid")),
420
+ kaleidoscope_params: gr.Group(visible=(illusion_type == "kaleidoscope")),
421
+ pinch_params: gr.Group(visible=(illusion_type == "pinch")),
422
+ twirl_params: gr.Group(visible=(illusion_type == "twirl"))
423
+ }
424
+
425
+ def generate_illusion(img, ill_type, *params):
426
+ param_dict = {}
427
+
428
+ if ill_type == "spiral":
429
+ param_dict = {
430
+ 'spiral_count': params[0],
431
+ 'rotation_speed': params[1],
432
+ 'color_scheme': params[2]
433
+ }
434
+ elif ill_type == "wave":
435
+ param_dict = {
436
+ 'wave_amplitude': params[0],
437
+ 'wave_frequency': params[1],
438
+ 'direction': params[2]
439
+ }
440
+ elif ill_type == "tunnel":
441
+ param_dict = {
442
+ 'rings': params[0],
443
+ 'perspective': params[1]
444
+ }
445
+ elif ill_type == "moire":
446
+ param_dict = {
447
+ 'line_spacing': params[0],
448
+ 'angle_offset': params[1]
449
+ }
450
+ elif ill_type == "rotating_grid":
451
+ param_dict = {
452
+ 'grid_size': params[0],
453
+ 'rotation': params[1]
454
+ }
455
+ elif ill_type == "kaleidoscope":
456
+ param_dict = {
457
+ 'segments': params[0]
458
+ }
459
+ elif ill_type == "pinch":
460
+ param_dict = {
461
+ 'strength': params[0]
462
+ }
463
+ elif ill_type == "twirl":
464
+ param_dict = {
465
+ 'twirl_angle': params[0]
466
+ }
467
+
468
+ result = apply_illusion(img, ill_type, **param_dict)
469
+ return result
470
+
471
+ # Event handlers
472
+ illusion_type.change(
473
+ update_params,
474
+ illusion_type,
475
+ [spiral_params, wave_params, tunnel_params, moire_params,
476
+ grid_params, kaleidoscope_params, pinch_params, twirl_params]
477
+ )
478
+
479
+ generate_btn.click(
480
+ generate_illusion,
481
+ inputs=[input_image, illusion_type,
482
+ spiral_count, rotation_speed, color_scheme,
483
+ wave_amplitude, wave_frequency, direction,
484
+ rings, perspective,
485
+ line_spacing, angle_offset,
486
+ grid_size, rotation,
487
+ segments,
488
+ strength,
489
+ twirl_angle],
490
+ outputs=output_image,
491
+ api_visibility="public"
492
+ )
493
+
494
+ clear_btn.click(
495
+ lambda: [None, None],
496
+ outputs=[input_image, output_image]
497
+ )
498
+
499
+ # Launch the app with Gradio 6 syntax
500
+ demo.launch(
501
+ theme=gr.themes.Soft(
502
+ primary_hue="indigo",
503
+ secondary_hue="purple",
504
+ neutral_hue="slate",
505
+ text_size="lg",
506
+ spacing_size="lg",
507
+ radius_size="md"
508
+ ),
509
+ footer_links=[
510
+ {"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"}
511
+ ]
512
+ )
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ # No additional dependencies required