Spaces:
Running
Running
Add examples with mask
Browse files- app.py +94 -52
- examples/ex1_mask_only.png +0 -0
- examples/ex2_mask_only.png +0 -0
- examples/ex3_mask_only.png +0 -0
- examples/ex4_mask_only.png +0 -0
app.py
CHANGED
@@ -107,16 +107,39 @@ async def process_image(
|
|
107 |
return None
|
108 |
|
109 |
|
110 |
-
def
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
|
|
|
|
119 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
|
121 |
|
122 |
async def run_async(
|
@@ -124,24 +147,31 @@ async def run_async(
|
|
124 |
progress: gr.Progress = gr.Progress(),
|
125 |
) -> tuple[Image.Image, Image.Image] | None:
|
126 |
if not image_and_mask:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
return None
|
128 |
|
129 |
alpha_channel = image_and_mask["layers"][0]
|
130 |
alpha_channel = cast(np.ndarray, alpha_channel)
|
131 |
mask_np = np.where(alpha_channel[:, :, 3] == 0, 0, 255).astype(np.uint8)
|
132 |
|
133 |
-
|
134 |
-
|
|
|
|
|
135 |
|
136 |
-
# Save mask to ./masks.png
|
137 |
mask = Image.fromarray(mask_np)
|
138 |
-
mask =
|
139 |
-
# mask.save("mask.png")
|
140 |
|
141 |
-
# Save image to ./images.png
|
142 |
image = Image.fromarray(image_np)
|
143 |
-
image =
|
144 |
-
# image.save("image.png")
|
145 |
|
146 |
output = await process_image(
|
147 |
image, # type: ignore
|
@@ -150,9 +180,10 @@ async def run_async(
|
|
150 |
)
|
151 |
|
152 |
if output is None:
|
|
|
153 |
return None
|
154 |
|
155 |
-
return
|
156 |
|
157 |
|
158 |
def run_sync(*args):
|
@@ -160,16 +191,31 @@ def run_sync(*args):
|
|
160 |
|
161 |
|
162 |
with gr.Blocks() as demo:
|
163 |
-
gr.
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
with gr.Row():
|
169 |
with gr.Column():
|
170 |
# The image overflow, fix
|
171 |
image_and_mask = gr.ImageMask(
|
172 |
-
label="
|
173 |
layers=False,
|
174 |
show_fullscreen_button=False,
|
175 |
sources=["upload"],
|
@@ -177,11 +223,13 @@ with gr.Blocks() as demo:
|
|
177 |
interactive=True,
|
178 |
height="full",
|
179 |
width="full",
|
|
|
|
|
180 |
)
|
181 |
|
182 |
with gr.Column():
|
183 |
image_slider = ImageSlider(
|
184 |
-
label="
|
185 |
interactive=False,
|
186 |
)
|
187 |
|
@@ -201,9 +249,13 @@ with gr.Blocks() as demo:
|
|
201 |
)
|
202 |
|
203 |
# Build examples
|
204 |
-
images_examples = glob.glob("examples
|
205 |
-
mask_examples = [
|
206 |
-
|
|
|
|
|
|
|
|
|
207 |
# examples = [
|
208 |
# [
|
209 |
# img,
|
@@ -212,50 +264,40 @@ with gr.Blocks() as demo:
|
|
212 |
# ]
|
213 |
# for img, mask, out in zip(images_examples, mask_examples, output_examples)
|
214 |
# ]
|
|
|
|
|
|
|
|
|
|
|
|
|
215 |
examples = [
|
216 |
[
|
217 |
-
|
218 |
-
|
219 |
-
"layers": [],
|
220 |
-
"composite": "./examples/ex1_mask.png",
|
221 |
-
},
|
222 |
-
# ("./examples/ex1.jpg", "./examples/ex1_result.png"),
|
223 |
(
|
224 |
"https://dropshare.blanchon.xyz/public/dropshare/ex1.jpg",
|
225 |
"https://dropshare.blanchon.xyz/public/dropshare/ex1_results.png",
|
226 |
),
|
227 |
],
|
228 |
[
|
229 |
-
|
230 |
-
|
231 |
-
"layers": [],
|
232 |
-
"composite": "./examples/ex2_mask.png",
|
233 |
-
},
|
234 |
-
# ("./examples/ex2.jpg", "./examples/ex2_result.png"),
|
235 |
(
|
236 |
"https://dropshare.blanchon.xyz/public/dropshare/ex2.jpg",
|
237 |
"https://dropshare.blanchon.xyz/public/dropshare/ex2_result.png",
|
238 |
),
|
239 |
],
|
240 |
[
|
241 |
-
|
242 |
-
|
243 |
-
"layers": [],
|
244 |
-
"composite": "./examples/ex3_mask.png",
|
245 |
-
},
|
246 |
-
# ("./examples/ex3.jpg", "./examples/ex3_result.png"),
|
247 |
(
|
248 |
"https://dropshare.blanchon.xyz/public/dropshare/ex3.jpg",
|
249 |
"https://dropshare.blanchon.xyz/public/dropshare/ex3_result.png",
|
250 |
),
|
251 |
],
|
252 |
[
|
253 |
-
|
254 |
-
|
255 |
-
"layers": [],
|
256 |
-
"composite": "./examples/ex4_mask.png",
|
257 |
-
},
|
258 |
-
# ("./examples/ex4.jpg", "./examples/ex4_result.png"),
|
259 |
(
|
260 |
"https://dropshare.blanchon.xyz/public/dropshare/ex4.jpg",
|
261 |
"https://dropshare.blanchon.xyz/public/dropshare/ex4_result.png",
|
|
|
107 |
return None
|
108 |
|
109 |
|
110 |
+
def make_example(background_path: str, mask_path: str) -> EditorValue:
|
111 |
+
example1_background = np.array(Image.open(background_path))
|
112 |
+
example1_mask_only = np.array(Image.open(mask_path))[:, :, -1]
|
113 |
+
|
114 |
+
example1_layers = np.zeros(
|
115 |
+
(example1_background.shape[0], example1_background.shape[1], 4), dtype=np.uint8
|
116 |
+
)
|
117 |
+
example1_layers[:, :, 3] = example1_mask_only
|
118 |
+
|
119 |
+
example1_composite = np.zeros(
|
120 |
+
(example1_background.shape[0], example1_background.shape[1], 4), dtype=np.uint8
|
121 |
)
|
122 |
+
example1_composite[:, :, :3] = example1_background
|
123 |
+
example1_composite[:, :, 3] = np.where(example1_mask_only == 255, 0, 255)
|
124 |
+
|
125 |
+
return {
|
126 |
+
"background": example1_background,
|
127 |
+
"layers": [example1_layers],
|
128 |
+
"composite": example1_composite,
|
129 |
+
}
|
130 |
+
|
131 |
+
|
132 |
+
def resize_image(img: Image.Image, min_side_length: int = 768) -> Image.Image:
|
133 |
+
if img.width <= min_side_length and img.height <= min_side_length:
|
134 |
+
return img
|
135 |
+
|
136 |
+
aspect_ratio = img.width / img.height
|
137 |
+
if img.width < img.height:
|
138 |
+
new_height = int(min_side_length / aspect_ratio)
|
139 |
+
return img.resize((min_side_length, new_height))
|
140 |
+
|
141 |
+
new_width = int(min_side_length * aspect_ratio)
|
142 |
+
return img.resize((new_width, min_side_length))
|
143 |
|
144 |
|
145 |
async def run_async(
|
|
|
147 |
progress: gr.Progress = gr.Progress(),
|
148 |
) -> tuple[Image.Image, Image.Image] | None:
|
149 |
if not image_and_mask:
|
150 |
+
gr.Info("Please upload an image and draw a mask")
|
151 |
+
return None
|
152 |
+
|
153 |
+
image_np = image_and_mask["background"]
|
154 |
+
image_np = cast(np.ndarray, image_np)
|
155 |
+
|
156 |
+
# If the image is empty, return None
|
157 |
+
if np.sum(image_np) == 0:
|
158 |
+
gr.Info("Please upload an image")
|
159 |
return None
|
160 |
|
161 |
alpha_channel = image_and_mask["layers"][0]
|
162 |
alpha_channel = cast(np.ndarray, alpha_channel)
|
163 |
mask_np = np.where(alpha_channel[:, :, 3] == 0, 0, 255).astype(np.uint8)
|
164 |
|
165 |
+
# if mask_np is empty, return None
|
166 |
+
if np.sum(mask_np) == 0:
|
167 |
+
gr.Info("Please mark the areas you want to remove")
|
168 |
+
return None
|
169 |
|
|
|
170 |
mask = Image.fromarray(mask_np)
|
171 |
+
mask = resize_image(mask)
|
|
|
172 |
|
|
|
173 |
image = Image.fromarray(image_np)
|
174 |
+
image = resize_image(image)
|
|
|
175 |
|
176 |
output = await process_image(
|
177 |
image, # type: ignore
|
|
|
180 |
)
|
181 |
|
182 |
if output is None:
|
183 |
+
gr.Info("Processing failed")
|
184 |
return None
|
185 |
|
186 |
+
return image, output
|
187 |
|
188 |
|
189 |
def run_sync(*args):
|
|
|
191 |
|
192 |
|
193 |
with gr.Blocks() as demo:
|
194 |
+
gr.HTML("""
|
195 |
+
<div style="text-align:center;">
|
196 |
+
<h1>🧹 Room Cleaner</h1>
|
197 |
+
<div>
|
198 |
+
<p>Upload an image and use the pencil tool (✏️ icon at the bottom) to <b>mark the areas you want to remove</b>.</p>
|
199 |
+
<p>For best results, include the shadows and reflections of the objects you want to remove.</p>
|
200 |
+
<p>You can remove multiple objects at once.</p>
|
201 |
+
<p>If you forget to mask some parts of your object, it's likely that the model will reconstruct them.</p>
|
202 |
+
<br>
|
203 |
+
<video width="640" height="360" controls style="margin: 0 auto; border-radius: 10px;">
|
204 |
+
<source src="https://dropshare.blanchon.xyz/public/dropshare/room_cleaner_demo.mp4" type="video/mp4">
|
205 |
+
</video>
|
206 |
+
<br>
|
207 |
+
<p>Finally, click on the <b>"Run"</b> button to process the image.</p>
|
208 |
+
<p>Wait for the processing to complete and compare the original and processed images using the slider.</p>
|
209 |
+
|
210 |
+
<p>⚠️ Note that the images are compressed to the workloads of the demo. </p>
|
211 |
+
</div>
|
212 |
+
</div>
|
213 |
+
""")
|
214 |
with gr.Row():
|
215 |
with gr.Column():
|
216 |
# The image overflow, fix
|
217 |
image_and_mask = gr.ImageMask(
|
218 |
+
label="Image and Mask",
|
219 |
layers=False,
|
220 |
show_fullscreen_button=False,
|
221 |
sources=["upload"],
|
|
|
223 |
interactive=True,
|
224 |
height="full",
|
225 |
width="full",
|
226 |
+
brush=gr.Brush(default_size=75, colors=["#000000"], color_mode="fixed"),
|
227 |
+
transforms=[],
|
228 |
)
|
229 |
|
230 |
with gr.Column():
|
231 |
image_slider = ImageSlider(
|
232 |
+
label="Result",
|
233 |
interactive=False,
|
234 |
)
|
235 |
|
|
|
249 |
)
|
250 |
|
251 |
# Build examples
|
252 |
+
images_examples = glob.glob("examples/*.jpg")
|
253 |
+
mask_examples = [
|
254 |
+
img.replace(".jpg", "") + "_mask_only.png" for img in images_examples
|
255 |
+
]
|
256 |
+
output_examples = [
|
257 |
+
img.replace(".jpg", "") + "results.png" for img in images_examples
|
258 |
+
]
|
259 |
# examples = [
|
260 |
# [
|
261 |
# img,
|
|
|
264 |
# ]
|
265 |
# for img, mask, out in zip(images_examples, mask_examples, output_examples)
|
266 |
# ]
|
267 |
+
|
268 |
+
example1 = make_example(images_examples[0], mask_examples[0])
|
269 |
+
example2 = make_example(images_examples[1], mask_examples[1])
|
270 |
+
example3 = make_example(images_examples[2], mask_examples[2])
|
271 |
+
example4 = make_example(images_examples[3], mask_examples[3])
|
272 |
+
|
273 |
examples = [
|
274 |
[
|
275 |
+
example1,
|
276 |
+
# ("./examples/ex1.jpg", "./examples/ex1_result.png")
|
|
|
|
|
|
|
|
|
277 |
(
|
278 |
"https://dropshare.blanchon.xyz/public/dropshare/ex1.jpg",
|
279 |
"https://dropshare.blanchon.xyz/public/dropshare/ex1_results.png",
|
280 |
),
|
281 |
],
|
282 |
[
|
283 |
+
example2,
|
284 |
+
# ("./examples/ex2.jpg", "./examples/ex2_result.png")
|
|
|
|
|
|
|
|
|
285 |
(
|
286 |
"https://dropshare.blanchon.xyz/public/dropshare/ex2.jpg",
|
287 |
"https://dropshare.blanchon.xyz/public/dropshare/ex2_result.png",
|
288 |
),
|
289 |
],
|
290 |
[
|
291 |
+
example3,
|
292 |
+
# ("./examples/ex3.jpg", "./examples/ex3_result.png")
|
|
|
|
|
|
|
|
|
293 |
(
|
294 |
"https://dropshare.blanchon.xyz/public/dropshare/ex3.jpg",
|
295 |
"https://dropshare.blanchon.xyz/public/dropshare/ex3_result.png",
|
296 |
),
|
297 |
],
|
298 |
[
|
299 |
+
example4,
|
300 |
+
# ("./examples/ex4.jpg", "./examples/ex4_result.png")
|
|
|
|
|
|
|
|
|
301 |
(
|
302 |
"https://dropshare.blanchon.xyz/public/dropshare/ex4.jpg",
|
303 |
"https://dropshare.blanchon.xyz/public/dropshare/ex4_result.png",
|
examples/ex1_mask_only.png
ADDED
examples/ex2_mask_only.png
ADDED
examples/ex3_mask_only.png
ADDED
examples/ex4_mask_only.png
CHANGED