bhavya-shah commited on
Commit
0f73b6f
·
1 Parent(s): cb1954d

Added app.py and requirements.txt

Browse files
Files changed (2) hide show
  1. app.py +205 -0
  2. requirements.txt +7 -0
app.py ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import cv2 as cv
4
+ import numpy as np
5
+ import transformers as t
6
+ from PIL import Image
7
+ import warnings
8
+ warnings.filterwarnings('ignore')
9
+
10
+ # Load models globally to avoid reloading
11
+ print("Loading models...")
12
+ # MaskFormer for person segmentation
13
+ feature_extractor = t.MaskFormerFeatureExtractor.from_pretrained("facebook/maskformer-swin-base-coco")
14
+ maskformer_model = t.MaskFormerForInstanceSegmentation.from_pretrained("facebook/maskformer-swin-base-coco")
15
+
16
+ # DPT for depth estimation
17
+ image_processor = t.DPTImageProcessor.from_pretrained("Intel/dpt-hybrid-midas")
18
+ depth_model = t.DPTForDepthEstimation.from_pretrained("Intel/dpt-hybrid-midas", low_cpu_mem_usage=True)
19
+ print("Models loaded successfully!")
20
+
21
+ def apply_gaussian_blur(image, kernel_size=15, sigma=10):
22
+ """Apply simple Gaussian blur to entire image"""
23
+ image_np = np.array(image)
24
+ d1_kernel = cv.getGaussianKernel(ksize=kernel_size, sigma=sigma, ktype=cv.CV_32F)
25
+ d2_kernel = d1_kernel @ d1_kernel.T
26
+ blurred = cv.filter2D(image_np, kernel=d2_kernel, ddepth=-1)
27
+ return Image.fromarray(blurred)
28
+
29
+ def apply_portrait_blur(image, kernel_size=15, sigma=10):
30
+ """Apply blur to background only, keeping person in focus"""
31
+ # Convert to RGB if needed
32
+ if image.mode != 'RGB':
33
+ image = image.convert('RGB')
34
+
35
+ # Get person segmentation mask
36
+ inputs = feature_extractor(images=image, return_tensors="pt")
37
+ with torch.no_grad():
38
+ outputs = maskformer_model(**inputs)
39
+
40
+ segment_result = feature_extractor.post_process_panoptic_segmentation(
41
+ outputs, target_sizes=[image.size[::-1]]
42
+ )[0]
43
+
44
+ predicted_panoptic_map = segment_result["segmentation"]
45
+ # Class 5 is 'person' in COCO dataset
46
+ person_mask = predicted_panoptic_map == 5
47
+ person_mask = person_mask.cpu().numpy()
48
+ # Invert: 0 for person, 255 for background
49
+ person_mask = np.where(person_mask, 0, 1) * 255
50
+ person_mask = np.array(person_mask, dtype='uint8')
51
+
52
+ # Apply Gaussian blur
53
+ image_np = np.array(image, dtype='uint8')
54
+ d1_kernel = cv.getGaussianKernel(ksize=kernel_size, sigma=sigma, ktype=cv.CV_32F)
55
+ d2_kernel = d1_kernel @ d1_kernel.T
56
+ full_image_blur = cv.filter2D(image_np, kernel=d2_kernel, ddepth=-1)
57
+
58
+ # Extract background from blurred image
59
+ segment_background = cv.bitwise_and(full_image_blur, full_image_blur, mask=person_mask)
60
+
61
+ # Extract person from original image
62
+ inverted_person_mask = cv.bitwise_not(person_mask)
63
+ segment_person = cv.bitwise_and(image_np, image_np, mask=inverted_person_mask)
64
+
65
+ # Combine
66
+ result = cv.add(segment_background, segment_person)
67
+ return Image.fromarray(result)
68
+
69
+ def apply_lens_blur(image, blur_threshold=10):
70
+ """Apply depth-based lens blur effect"""
71
+ # Convert to RGB if needed
72
+ if image.mode != 'RGB':
73
+ image = image.convert('RGB')
74
+
75
+ # Get depth map
76
+ inputs = image_processor(images=image, return_tensors="pt")
77
+ with torch.no_grad():
78
+ outputs = depth_model(**inputs)
79
+ predicted_depth = outputs.predicted_depth
80
+
81
+ # Interpolate to original size
82
+ prediction = torch.nn.functional.interpolate(
83
+ predicted_depth.unsqueeze(1),
84
+ size=image.size[::-1],
85
+ mode="bicubic",
86
+ align_corners=False
87
+ )
88
+
89
+ # Convert to depth map
90
+ output = prediction.squeeze().cpu().numpy()
91
+ formatted = (output * 255 / np.max(output)).astype("uint8")
92
+ depth_map = np.array(formatted, dtype='uint8')
93
+
94
+ # Normalize depth map to 0-15 range
95
+ normalized_depth_map = np.array(depth_map / 255 * 15, dtype='uint8')
96
+
97
+ # Apply variable blur based on depth
98
+ image_np = np.array(image, dtype='uint8')
99
+ result = np.zeros_like(image_np, dtype='uint8')
100
+
101
+ for i in range(15, -1, -1):
102
+ if i < blur_threshold:
103
+ radius = 15 - i
104
+ if radius > 0:
105
+ d1_kernel = cv.getGaussianKernel(ksize=radius, sigma=10, ktype=cv.CV_32F)
106
+ d2_kernel = d1_kernel @ d1_kernel.T
107
+ full_image_blur = cv.filter2D(image_np, ddepth=-1, kernel=d2_kernel)
108
+ else:
109
+ full_image_blur = image_np
110
+ else:
111
+ full_image_blur = image_np
112
+
113
+ mask = np.where(normalized_depth_map == i, 255, 0)
114
+ mask = np.array(mask, dtype='uint8')
115
+ segment_background = cv.bitwise_and(full_image_blur, full_image_blur, mask=mask)
116
+ result = cv.bitwise_or(result, segment_background)
117
+
118
+ return Image.fromarray(result)
119
+
120
+ def process_image(image, effect_type, kernel_size, sigma, blur_threshold):
121
+ """Main processing function"""
122
+ if image is None:
123
+ return None
124
+
125
+ if effect_type == "Gaussian Blur":
126
+ return apply_gaussian_blur(image, kernel_size, sigma)
127
+ elif effect_type == "Portrait Blur (Background Only)":
128
+ return apply_portrait_blur(image, kernel_size, sigma)
129
+ elif effect_type == "Lens Blur (Depth-based)":
130
+ return apply_lens_blur(image, blur_threshold)
131
+
132
+ return image
133
+
134
+ # Create Gradio interface
135
+ with gr.Blocks(title="Image Blur Effects") as demo:
136
+ gr.Markdown(
137
+ """
138
+ # 📸 Image Blur Effects
139
+ Upload an image and apply different blur effects:
140
+ - **Gaussian Blur**: Simple blur applied to entire image
141
+ - **Portrait Blur**: Smart background blur keeping people in focus
142
+ - **Lens Blur**: Depth-based blur simulating camera lens effects
143
+ """
144
+ )
145
+
146
+ with gr.Row():
147
+ with gr.Column():
148
+ input_image = gr.Image(type="pil", label="Upload Image")
149
+ effect_type = gr.Radio(
150
+ choices=[
151
+ "Gaussian Blur",
152
+ "Portrait Blur (Background Only)",
153
+ "Lens Blur (Depth-based)"
154
+ ],
155
+ value="Gaussian Blur",
156
+ label="Select Effect"
157
+ )
158
+
159
+ with gr.Accordion("Advanced Settings", open=False):
160
+ kernel_size = gr.Slider(
161
+ minimum=3, maximum=31, step=2, value=15,
162
+ label="Kernel Size (for Gaussian/Portrait Blur)"
163
+ )
164
+ sigma = gr.Slider(
165
+ minimum=1, maximum=20, value=10,
166
+ label="Sigma (for Gaussian/Portrait Blur)"
167
+ )
168
+ blur_threshold = gr.Slider(
169
+ minimum=0, maximum=15, value=10,
170
+ label="Blur Threshold (for Lens Blur - higher = more in focus)"
171
+ )
172
+
173
+ process_btn = gr.Button("Apply Effect", variant="primary")
174
+
175
+ with gr.Column():
176
+ output_image = gr.Image(type="pil", label="Result")
177
+
178
+ gr.Markdown(
179
+ """
180
+ ### Tips:
181
+ - **Gaussian Blur**: Adjust kernel size and sigma for blur intensity
182
+ - **Portrait Blur**: Works best with clear person in image
183
+ - **Lens Blur**: Mimics DSLR depth-of-field effect
184
+ """
185
+ )
186
+
187
+ process_btn.click(
188
+ fn=process_image,
189
+ inputs=[input_image, effect_type, kernel_size, sigma, blur_threshold],
190
+ outputs=output_image
191
+ )
192
+
193
+ # Example images
194
+ gr.Examples(
195
+ examples=[
196
+ ["example.jpg", "Gaussian Blur", 15, 10, 10],
197
+ ],
198
+ inputs=[input_image, effect_type, kernel_size, sigma, blur_threshold],
199
+ outputs=output_image,
200
+ fn=process_image,
201
+ cache_examples=False,
202
+ )
203
+
204
+ if __name__ == "__main__":
205
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ gradio==4.44.0
2
+ torch==2.1.0
3
+ transformers==4.35.0
4
+ opencv-python-headless==4.8.1.78
5
+ numpy==1.24.3
6
+ Pillow==10.1.0
7
+ timm==0.9.12