blanchon commited on
Commit
50704a0
1 Parent(s): 2ba904e

Add examples with mask

Browse files
app.py CHANGED
@@ -107,16 +107,39 @@ async def process_image(
107
  return None
108
 
109
 
110
- def resize(image: Image.Image, shortest_side: int = 768) -> Image.Image:
111
- if image.width <= shortest_side and image.height <= shortest_side:
112
- return image
113
- if image.width < image.height:
114
- return image.resize(
115
- size=(shortest_side, int(shortest_side * image.height / image.width))
116
- )
117
- return image.resize(
118
- size=(int(shortest_side * image.width / image.height), shortest_side)
 
 
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
- image_np = image_and_mask["background"]
134
- image_np = cast(np.ndarray, image_np)
 
 
135
 
136
- # Save mask to ./masks.png
137
  mask = Image.fromarray(mask_np)
138
- mask = resize(mask)
139
- # mask.save("mask.png")
140
 
141
- # Save image to ./images.png
142
  image = Image.fromarray(image_np)
143
- image = resize(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 output, image
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.Markdown("""
164
- # 🧹 Room Cleaner
165
- Upload an image and and use pen tool (pencil icon at the bottom) to mark the areas you want to remove.
166
- Click on the "Run" button to process the image and remove the marked areas.
167
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  with gr.Row():
169
  with gr.Column():
170
  # The image overflow, fix
171
  image_and_mask = gr.ImageMask(
172
- label="Input Image and Mask",
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="Compare Original and Processed",
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 = [img.replace("inputs", "masks") for img in images_examples]
206
- output_examples = [img.replace("inputs", "outputs") for img in images_examples]
 
 
 
 
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
- "background": "./examples/ex1.jpg",
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
- "background": "./examples/ex2.jpg",
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
- "background": "./examples/ex3.jpg",
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
- "background": "./examples/ex4.jpg",
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