ngohel58 commited on
Commit
e33478b
·
verified ·
1 Parent(s): 7e51b97

Implement chromostereopsis effect using Depth Anything V2 Large model

Browse files
Files changed (1) hide show
  1. app.py +223 -16
app.py CHANGED
@@ -1,30 +1,237 @@
1
  import gradio as gr
2
  from transformers import pipeline
 
3
  from PIL import Image
4
 
5
- # Load the depth estimation pipeline using Depth Anything V2 Large model
6
  depth_pipeline = pipeline(task="depth-estimation", model="depth-anything/Depth-Anything-V2-Large-hf")
7
 
 
 
 
8
 
9
- def predict_depth(image):
10
- # image is a PIL Image
11
- result = depth_pipeline(image)
12
- depth_image = result["depth"]
13
- return depth_image
 
 
 
 
 
 
 
 
 
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
- title = "Depth Anything V2 Large - Depth Map Generator"
17
- description = "Upload an image to generate a depth map using the Depth Anything V2 Large model (Relative depth)."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
- iface = gr.Interface(
21
- fn=predict_depth,
22
- inputs=gr.Image(type="pil", label="Input Image"),
23
- outputs=gr.Image(type="pil", label="Predicted Depth Map"),
24
- title=title,
25
- description=description,
26
- )
 
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
  if __name__ == "__main__":
30
- iface.launch()
 
 
 
 
 
1
  import gradio as gr
2
  from transformers import pipeline
3
+ import numpy as np
4
  from PIL import Image
5
 
6
+ # Load the depth estimation pipeline using the Depth Anything V2 Large model
7
  depth_pipeline = pipeline(task="depth-estimation", model="depth-anything/Depth-Anything-V2-Large-hf")
8
 
9
+ # Global variables to store current state
10
+ current_original_image = None
11
+ current_depth_image = None
12
 
13
+ def process_depth_to_pil(depth_pil):
14
+ """
15
+ Normalize the depth PIL image to a grayscale 0-255 PIL image.
16
+ """
17
+ depth_array = np.array(depth_pil, dtype=np.float32)
18
+ # If the depth image has multiple channels, take the first channel
19
+ if depth_array.ndim == 3:
20
+ depth_array = depth_array[..., 0]
21
+ depth_min = depth_array.min()
22
+ depth_max = depth_array.max()
23
+ depth_norm = (depth_array - depth_min) / (depth_max - depth_min + 1e-6)
24
+ depth_255 = depth_norm * 255.0
25
+ depth_img = Image.fromarray(depth_255.astype(np.uint8), mode="L")
26
+ return depth_img
27
 
28
+ def apply_chromo_stereopsis(
29
+ original_img: Image.Image,
30
+ depth_img: Image.Image,
31
+ threshold: float,
32
+ feather: float,
33
+ black_level: float,
34
+ white_level: float
35
+ ) -> Image.Image:
36
+ """
37
+ Apply chromostereopsis red-blue effect to the original image using a depth map.
38
+ """
39
+ # Convert original image to grayscale
40
+ gray = np.array(original_img.convert("L"), dtype=np.float32)
41
+ # Levels adjustment
42
+ denom = (white_level - black_level) if (white_level > black_level) else 1e-6
43
+ adjusted_gray = (gray - black_level) / denom * 255.0
44
+ adjusted_gray = np.clip(adjusted_gray, 0, 255)
45
+ adjusted_gray_01 = adjusted_gray / 255.0
46
+ # Depth-based blend factor
47
+ depth_arr = np.array(depth_img, dtype=np.float32)
48
+ half_feather = feather / 2.0
49
+ blend = np.clip((depth_arr - (threshold - half_feather)) / (feather + 1e-6), 0, 1)
50
+ # Red / Blue channels
51
+ red = blend * adjusted_gray_01 * 255.0
52
+ blue = (1.0 - blend) * adjusted_gray_01 * 255.0
53
+ # Create the output image
54
+ h, w = gray.shape
55
+ output = np.zeros((h, w, 3), dtype=np.uint8)
56
+ output[..., 0] = np.clip(red, 0, 255).astype(np.uint8) # Red channel
57
+ output[..., 1] = 0 # Green channel (always 0)
58
+ output[..., 2] = np.clip(blue, 0, 255).astype(np.uint8) # Blue channel
59
+ return Image.fromarray(output, mode="RGB")
60
 
61
+ def generate_depth_map(input_image):
62
+ """
63
+ Generate a depth map from the input image and create an initial chromostereopsis output.
64
+ """
65
+ global current_original_image, current_depth_image
66
+ if input_image is None:
67
+ current_original_image = None
68
+ current_depth_image = None
69
+ return None, None
70
+ try:
71
+ # Store original image
72
+ current_original_image = input_image
73
+ # Run depth estimation
74
+ result = depth_pipeline(input_image)
75
+ depth_pil = result["depth"]
76
+ # Normalize depth map
77
+ current_depth_image = process_depth_to_pil(depth_pil)
78
+ # Use default parameters for initial chromostereopsis effect
79
+ threshold = 50.0 * 255.0 / 100.0
80
+ feather = 10.0 * 255.0 / 100.0
81
+ black_level = 0.0
82
+ white_level = 255.0
83
+ chromostereo_result = apply_chromo_stereopsis(
84
+ current_original_image,
85
+ current_depth_image,
86
+ threshold,
87
+ feather,
88
+ black_level,
89
+ white_level
90
+ )
91
+ return current_depth_image.convert("RGB"), chromostereo_result
92
+ except Exception as e:
93
+ print(f"Error during depth generation: {e}")
94
+ current_original_image = None
95
+ current_depth_image = None
96
+ return None, None
97
 
98
+ def update_chromostereopsis(threshold_percent, feather_percent, black_level, white_level):
99
+ """
100
+ Update the chromostereopsis effect with new parameters for live preview.
101
+ """
102
+ global current_original_image, current_depth_image
103
+ if current_original_image is None or current_depth_image is None:
104
+ return None
105
+ try:
106
+ threshold = (threshold_percent / 100.0) * 255.0
107
+ feather = (feather_percent / 100.0) * 255.0
108
+ chromostereo_result = apply_chromo_stereopsis(
109
+ current_original_image,
110
+ current_depth_image,
111
+ threshold,
112
+ feather,
113
+ black_level,
114
+ white_level
115
+ )
116
+ return chromostereo_result
117
+ except Exception as e:
118
+ print(f"Error during chromostereopsis update: {e}")
119
+ return None
120
 
121
+ def clear_results():
122
+ """
123
+ Clear stored images and reset outputs.
124
+ """
125
+ global current_original_image, current_depth_image
126
+ current_original_image = None
127
+ current_depth_image = None
128
+ return None, None
129
 
130
+ with gr.Blocks(title="ChromoStereoizer", theme=gr.themes.Soft()) as demo:
131
+ gr.Markdown("# ChromoStereoizer")
132
+ with gr.Row():
133
+ # Left column: Input image and generate button
134
+ with gr.Column(scale=1):
135
+ input_image = gr.Image(
136
+ label="Upload Image",
137
+ type="pil",
138
+ height=400
139
+ )
140
+ generate_btn = gr.Button(
141
+ "Generate Depth Map",
142
+ variant="primary",
143
+ size="lg"
144
+ )
145
+ # Right column: Outputs and controls
146
+ with gr.Column(scale=1):
147
+ gr.Markdown("**Depth Map**")
148
+ depth_output = gr.Image(
149
+ type="pil",
150
+ height=400,
151
+ interactive=False,
152
+ show_download_button=True,
153
+ show_label=False
154
+ )
155
+ gr.Markdown("**ChromoStereoizer Result**")
156
+ chromo_output = gr.Image(
157
+ type="pil",
158
+ height=400,
159
+ interactive=False,
160
+ show_download_button=True,
161
+ show_label=False
162
+ )
163
+ with gr.Row():
164
+ threshold_slider = gr.Slider(
165
+ minimum=1,
166
+ maximum=100,
167
+ value=50,
168
+ step=1,
169
+ label="Threshold (%)"
170
+ )
171
+ feather_slider = gr.Slider(
172
+ minimum=0,
173
+ maximum=100,
174
+ value=10,
175
+ step=1,
176
+ label="Feather (%)"
177
+ )
178
+ with gr.Row():
179
+ black_level_slider = gr.Slider(
180
+ minimum=0,
181
+ maximum=255,
182
+ value=0,
183
+ step=1,
184
+ label="Black Level"
185
+ )
186
+ white_level_slider = gr.Slider(
187
+ minimum=0,
188
+ maximum=255,
189
+ value=255,
190
+ step=1,
191
+ label="White Level"
192
+ )
193
+ with gr.Row():
194
+ clear_btn = gr.Button("Clear", variant="secondary")
195
+ # Event bindings
196
+ generate_btn.click(
197
+ fn=generate_depth_map,
198
+ inputs=[input_image],
199
+ outputs=[depth_output, chromo_output],
200
+ show_progress=True
201
+ )
202
+ threshold_slider.change(
203
+ fn=update_chromostereopsis,
204
+ inputs=[threshold_slider, feather_slider, black_level_slider, white_level_slider],
205
+ outputs=chromo_output,
206
+ show_progress=False
207
+ )
208
+ feather_slider.change(
209
+ fn=update_chromostereopsis,
210
+ inputs=[threshold_slider, feather_slider, black_level_slider, white_level_slider],
211
+ outputs=chromo_output,
212
+ show_progress=False
213
+ )
214
+ black_level_slider.change(
215
+ fn=update_chromostereopsis,
216
+ inputs=[threshold_slider, feather_slider, black_level_slider, white_level_slider],
217
+ outputs=chromo_output,
218
+ show_progress=False
219
+ )
220
+ white_level_slider.change(
221
+ fn=update_chromostereopsis,
222
+ inputs=[threshold_slider, feather_slider, black_level_slider, white_level_slider],
223
+ outputs=chromo_output,
224
+ show_progress=False
225
+ )
226
+ clear_btn.click(
227
+ fn=clear_results,
228
+ inputs=[],
229
+ outputs=[depth_output, chromo_output]
230
+ )
231
 
232
  if __name__ == "__main__":
233
+ demo.launch(
234
+ server_name="0.0.0.0",
235
+ server_port=7860,
236
+ share=False
237
+ )