File size: 23,021 Bytes
13795d4
 
 
 
 
 
 
 
 
 
 
22dc2e3
 
cad0ba5
155ba3c
cad0ba5
f2d70d3
cad0ba5
 
 
 
0698d2a
4fe58f8
 
13795d4
4fe58f8
13795d4
4fe58f8
 
13795d4
 
 
 
4fe58f8
 
13795d4
4fe58f8
13795d4
4fe58f8
13795d4
 
4fe58f8
 
13795d4
4fe58f8
 
 
13795d4
 
 
 
4fe58f8
 
13795d4
4fe58f8
 
 
 
 
 
13795d4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4fe58f8
332c659
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8540618
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
df7b1e1
8540618
df7b1e1
8540618
 
 
7b7d862
df7b1e1
 
8540618
 
 
 
 
 
 
 
 
 
 
b8bcd53
8540618
 
 
 
 
4fe58f8
 
 
 
 
 
 
 
13795d4
 
 
 
332c659
 
 
8540618
 
 
 
4fe58f8
 
 
615f25c
4fe58f8
f2d70d3
4fe58f8
 
 
 
 
22dc2e3
 
 
0698d2a
 
22dc2e3
 
 
 
 
0698d2a
22dc2e3
48b107e
22dc2e3
 
 
72bb4e8
 
22dc2e3
72bb4e8
 
13795d4
4fe58f8
13795d4
 
 
 
332c659
 
 
 
8540618
e408fa1
8540618
 
4fe58f8
 
 
 
 
 
13795d4
4fe58f8
deb649d
e05124c
13795d4
4fe58f8
 
13795d4
4fe58f8
 
 
 
13795d4
 
332c659
 
 
8540618
df7b1e1
 
 
 
 
8540618
 
13795d4
4fe58f8
 
 
 
 
332c659
 
 
 
 
8540618
 
332c659
 
 
 
8540618
e64920c
df7b1e1
 
 
 
 
8540618
 
332c659
 
4fe58f8
df7b1e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13795d4
332c659
df7b1e1
 
 
 
 
 
 
 
 
 
4fe58f8
8540618
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
# author : OzlemAkgunoglu
# github : https://github.com/OzlemAkgunoglu
# Dynamic Photo Filter App 
# This is a Dynamic Photo Filter App that allows you to apply various filters to your images. 
# Adjust brightness, contrast, sharpening, and select a filter for real-time changes.
# And this app is created using OpenCV and Gradio. Thank you for using it.

# Let's load the necessary libraries
import cv2 as cv  # OpenCV for image processing
import numpy as np  # Numpy for arrays
import gradio as gr  # Gradio for UI
import re

def rgba_to_rgb(rgba_string):
    match = re.match(r'rgba\(([\d.]+),\s*([\d.]+),\s*([\d.]+),\s*([\d.]+)\)', rgba_string)
    if not match:
        raise ValueError("Invalid RGBA")
    
    r, g, b, a = map(float, match.groups())
    
    return (int(r), int(g), int(b))
    
# Let's define the filter functions
def apply_grayscale(image):
    return cv.cvtColor(image, cv.COLOR_BGR2GRAY)  # Convert the image to grayscale

# Sepia filter function
def apply_sepia(image):
    sepia_filter = np.array([[0.272, 0.534, 0.131], 
                             [0.349, 0.686, 0.168],
                             [0.393, 0.769, 0.189]])
    sepia_image = cv.transform(image, sepia_filter)  # Apply the filter
    return np.clip(sepia_image, 0, 255).astype(np.uint8)  # clip to hold values between 0 and 255 prevent excessive brightness or darkening. 

def apply_negative(image):
    return cv.bitwise_not(image)  # Invert the image 

# Sketch filter
def apply_sketch(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)  # Convert the image to grayscale
    inv = cv.bitwise_not(gray)  # Invert the grayscale image
    blurred = cv.GaussianBlur(inv, (21, 21), sigmaX=0, sigmaY=0) 
    sketch_image = cv.divide(gray, 255 - blurred, scale=256)
    return sketch_image

def apply_sharpen(image, sharpening):
    sharpening_filter = np.array([[0, -1, 0],
                                  [-1, 5 + sharpening, -1],
                                  [0, -1, 0]])
    return cv.filter2D(image, -1, sharpening_filter)  # Apply the filter each pixel is multiplied by the value in the kernel

def apply_edge_detection(image):
    return cv.Canny(image, 100, 200)

def apply_fall_filter(frame):
    fall_filter = np.array([[0.393, 0.769, 0.189],
                            [0.349, 0.686, 0.168],
                            [0.272, 0.534, 0.131]])
    return cv.transform(frame, fall_filter)

# Emboss filter
def apply_emboss(image):
    emboss_filter = np.array([[0, -1, 0],
                              [-1, 5, -1],
                              [0, -1, 0]])
    return cv.filter2D(image, -1, emboss_filter)

# Blur filter
def apply_blur(image, kernel_size):
    return cv.blur(image, (kernel_size, kernel_size))

# Vintage filter
def apply_vintage(image):
    vintage_filter = np.array([[0.627, 0.554, 0.369], 
                               [0.766, 0.714, 0.406],
                               [0.882, 0.869, 0.524]])
    vintage_image = cv.transform(image, vintage_filter)  # Apply the filter
    return np.clip(vintage_image, 0, 255).astype(np.uint8)  # clip to hold values between 0 and 255 prevent excessive brightness or darkening. 

# Combined filter
def apply_combined(image, sharpening):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    sepia = apply_sepia(image)
    sharpened = apply_sharpen(sepia, sharpening)
    edges = apply_edge_detection(gray)
    edges = cv.cvtColor(edges, cv.COLOR_GRAY2BGR)
    combined = cv.addWeighted(sharpened, 0.7, edges, 0.3, 0)
    return combined

# Cartoon filter
def apply_cartoon(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    gray = cv.medianBlur(gray, 7)
    edges = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY_INV, 9, 9)
    color = cv.bilateralFilter(image, 9, 300, 300)
    cartoon = cv.bitwise_and(color, color, mask=edges)
    return cartoon

# Watercolor filter
def apply_watercolor(image, size, sigma):
    blurred = cv.GaussianBlur(image, (size, size), sigma)
    watercolor = cv.addWeighted(image, 0.5, blurred, 0.5, 0)
    return watercolor

# Hue Shift filter
def apply_hue_shift(image, hue_shift):
    hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
    h, s, v = cv.split(hsv)
    h = cv.add(h, hue_shift)
    shifted_hsv = cv.merge([h, s, v])
    shifted_image = cv.cvtColor(shifted_hsv, cv.COLOR_HSV2BGR)
    return shifted_image

def apply_60s_tv(image):
    # Convert to sepia
    sepia = apply_sepia(image)
    
    # Reduce sharpness
    blurred = cv.GaussianBlur(sepia, (5, 5), sigmaX=0, sigmaY=0)
    
    # Add noise
    noise = np.zeros(sepia.shape, dtype=np.int16)
    cv.randn(noise, 0, 20)
    noisy_image = cv.add(blurred, noise, dtype=cv.CV_8UC3)
    noisy_image = np.clip(noisy_image, 0, 255).astype(np.uint8)
    
    # Reduce color depth
    noisy_image = (noisy_image // 32) * 32
    
    return noisy_image

# Vignette filter
def apply_vignette(image, strength, aspect_ratio, center_x, center_y, radius, smoothness):
    rows, cols = image.shape[:2]
    center = (int(cols * center_x), int(rows * center_y))
    mask = np.zeros((rows, cols), dtype=np.float32)
    for i in range(rows):
        for j in range(cols):
            distance_x = (j - center[0]) / (cols * aspect_ratio)
            distance_y = (i - center[1]) / rows
            distance = np.sqrt(distance_x**2 + distance_y**2)
            mask[i, j] = 1 - (distance / radius) ** strength
    mask = np.clip(mask, 0, 1)
    mask = np.stack((mask, mask, mask), axis=2)
    vignette_image = cv.multiply(image.astype(np.float32), mask)
    return vignette_image.astype(np.uint8)

# Tint filter
def apply_tint(image, tint_color, intensity):
    tint_color = np.array(tint_color, dtype=np.float32) / 255.0
    tint_color = cv.cvtColor(np.uint8([[tint_color]]), cv.COLOR_BGR2HSV).flatten()
    hsv_image = cv.cvtColor(image, cv.COLOR_BGR2HSV).astype(np.float32)
    hsv_image[:, :, 0] = (hsv_image[:, :, 0] + tint_color[0] * intensity) % 180
    hsv_image[:, :, 1] = np.clip(hsv_image[:, :, 1] + tint_color[1] * intensity, 0, 255)
    hsv_image[:, :, 2] = np.clip(hsv_image[:, :, 2] + tint_color[2] * intensity, 0, 255)
    tinted_image = cv.cvtColor(hsv_image.astype(np.uint8), cv.COLOR_HSV2BGR)
    return tinted_image

# Dictionary to map filter names to functions
filter_functions = {
    "Grayscale": apply_grayscale,
    "Sepia": apply_sepia,
    "Negative": apply_negative,
    "Sketch": apply_sketch,
    "Sharpen": apply_sharpen,
    "Edge Detection": apply_edge_detection,
    "Fall": apply_fall_filter,
    "Emboss": apply_emboss,
    "Blur": apply_blur,
    "Vintage": apply_vintage,
    "Combined": apply_combined,
    "Cartoon": apply_cartoon,
    "Watercolor": apply_watercolor,
    "Hue Shift": apply_hue_shift,
    "60s TV": apply_60s_tv,
    "Vignette": apply_vignette,
    "Tint": apply_tint
}

# Main function to apply selected filters
def apply_filters(image, filter_type, brightness, contrast, sharpening, kernel_size, hue_shift, size, sigma, vignette_strength, vignette_aspect_ratio, vignette_center_x, vignette_center_y, vignette_radius, vignette_smoothness, tint_color, tint_intensity):
    if image is None:
        gr.Error("Input image is empty!")  # for debugging
        return None  # Return None if the input image is empty
    
    # Adjust brightness and contrast
    image = cv.convertScaleAbs(image, alpha=contrast, beta=brightness)

    if isinstance(tint_color, str):
        if tint_color.startswith('#') and len(tint_color) == 7:
            try:
                tint_color = tint_color.lstrip('#')
                tint_color_rgb = tuple(int(tint_color[i:i+2], 16) for i in (0, 2, 4))
            except ValueError:
                print("Invalid hex color format. Using default color #FF0000.")
                tint_color_rgb = (255, 0, 0)  # Default color red
        elif tint_color.startswith('rgba('):
            try:
                tint_color_rgb = rgba_to_rgb(tint_color)
            except ValueError:
                print("Invalid rgba format. Using default color #FF0000.", )
                tint_color_rgb = (255, 0, 0)  # Default color red
        else:
            print("Invalid color format. Using default color #FF0000.")
            tint_color_rgb = (255, 0, 0)  # Default color red
    else:
        print("Invalid color format. Using default color #FF0000.")
        tint_color_rgb = (255, 0, 0)  # Default color red

    # Apply the selected filter from dictionary called filter_functions
    if filter_type in filter_functions:
        if filter_type == "Sharpen" or filter_type == "Combined":
            image = filter_functions[filter_type](image, sharpening)  # Calls the Sharpen or Combined filter with the sharpening parameter
        elif filter_type == "Blur":
            image = filter_functions[filter_type](image, kernel_size)  # Calls the Blur filter with the kernel_size parameter
        elif filter_type == "Hue Shift":
            image = filter_functions[filter_type](image, hue_shift)  # Calls the Hue Shift filter with hue_shift parameter
        elif filter_type == "Watercolor":
            image = filter_functions[filter_type](image, size, sigma)  # Calls the Watercolor filter with size and sigma parameters
        elif filter_type == "Vignette":
            image = filter_functions[filter_type](image, vignette_strength, vignette_aspect_ratio, vignette_center_x, vignette_center_y, vignette_radius, vignette_smoothness)  # Calls the Vignette filter with vignette_strength parameter
        elif filter_type == "Tint":
            image = filter_functions[filter_type](image, tint_color_rgb, tint_intensity) 
        else:
            image = filter_functions[filter_type](image)
        
    return image

# Define Interface
with gr.Blocks(theme="ParityError/Interstellar") as app:
    # Title and Description
    gr.Markdown("<h1 style='font-family: Arial, sans-serif; color: #333;'>📸 Photo Filter ⭐</h1>")
    gr.Markdown("<p style='color: #666;'>Apply professional photo filters with adjustable brightness, contrast, and sharpness. Perfect your images instantly!</p>")
    
    # Choices and Sliders at the Top
    with gr.Row():
        filter_choice = gr.Radio(list(filter_functions.keys()), label="Filter")
        
        with gr.Column():
            brightness_slider = gr.Slider(-100, 100, step=1, label="Brightness", value=0)
            contrast_slider = gr.Slider(0.5, 3.0, step=0.1, label="Contrast", value=1.0)
            sharpening_slider = gr.Slider(0, 5, step=0.1, label="Sharpening", value=0)
            blur_slider = gr.Slider(3, 21, step=2, label="Blur Kernel Size", value=15, visible=False)
            hue_shift_slider = gr.Slider(-180, 180, step=1, label="Hue Shift", value=0, visible=False)
            watercolor_size_slider = gr.Slider(3, 21, step=2, label="Watercolor Size", value=15, visible=False)
            watercolor_sigma_slider = gr.Slider(0.1, 10.0, step=0.1, label="Watercolor Sigma", value=2.0, visible=False)
            vignette_strength_slider = gr.Slider(1, 10, step=0.1, label="Vignette Strength", value=3.0, visible=False)
            vignette_aspect_ratio_slider = gr.Slider(0.5, 2.0, step=0.1, label="Vignette Aspect Ratio", value=1.0, visible=False)
            vignette_center_x_slider = gr.Slider(0.0, 1.0, step=0.01, label="Vignette Center X", value=0.5, visible=False)
            vignette_center_y_slider = gr.Slider(0.0, 1.0, step=0.01, label="Vignette Center Y", value=0.5, visible=False)
            vignette_radius_slider = gr.Slider(0.1, 1.0, step=0.01, label="Vignette Radius", value=0.75, visible=False)
            vignette_smoothness_slider = gr.Slider(1, 10, step=0.1, label="Vignette Smoothness", value=3.0, visible=False)
            tint_color_picker = gr.ColorPicker(label="Tint Color", value="#FF0000", visible=False)
            tint_intensity_slider = gr.Slider(0, 1, step=0.01, label="Tint Intensity", value=0.5, visible=False)
    
    # Horizontal display of the images 
    with gr.Row():
        image_input = gr.Image(label="Upload Image", type="numpy")
        image_output = gr.Image(label="Filtered Image")

    # Function to update visibility of sliders
    def update_slider_visibility(filter_type):
        blur_visible = filter_type == "Blur"
        hue_visible = filter_type == "Hue Shift"
        watercolor_visible = filter_type == "Watercolor"
        vignette_visible = filter_type == "Vignette"
        tint_visible = filter_type == "Tint"
        return (
            gr.update(visible=blur_visible),
            gr.update(visible=hue_visible),
            gr.update(visible=watercolor_visible),
            gr.update(visible=watercolor_visible),
            gr.update(visible=vignette_visible),
            gr.update(visible=vignette_visible),
            gr.update(visible=vignette_visible),
            gr.update(visible=vignette_visible),
            gr.update(visible=vignette_visible),
            gr.update(visible=vignette_visible),
            gr.update(visible=tint_visible),
            gr.update(visible=tint_visible)
        )

    # Link events for real-time updates
    image_input.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    filter_choice.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    brightness_slider.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    contrast_slider.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    sharpening_slider.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    blur_slider.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    hue_shift_slider.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    watercolor_size_slider.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    watercolor_sigma_slider.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    vignette_strength_slider.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    vignette_aspect_ratio_slider.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    vignette_center_x_slider.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    vignette_center_y_slider.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    vignette_radius_slider.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    vignette_smoothness_slider.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    tint_color_picker.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    tint_intensity_slider.change(
        apply_filters, 
        inputs=[
            image_input, filter_choice, brightness_slider, contrast_slider, sharpening_slider, 
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ], 
        outputs=image_output
    )
    
    # Update visibility of sliders when filter_choice changes
    filter_choice.change(
        update_slider_visibility, 
        inputs=[filter_choice], 
        outputs=[
            blur_slider, hue_shift_slider, watercolor_size_slider, watercolor_sigma_slider, 
            vignette_strength_slider, vignette_aspect_ratio_slider, vignette_center_x_slider, 
            vignette_center_y_slider, vignette_radius_slider, vignette_smoothness_slider, 
            tint_color_picker, tint_intensity_slider
        ]
    )

app.launch()