Files changed (1) hide show
  1. src/app.py +71 -60
src/app.py CHANGED
@@ -129,6 +129,29 @@ def process_prompt(img: Image.Image, prompt: str) -> tuple[Image.Image, Image.Im
129
  )
130
  return (img, output_image)
131
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
 
133
  def on_change_prompt(img: Image.Image | None, prompt: str | None):
134
  return gr.update(interactive=bool(img and prompt))
@@ -149,7 +172,9 @@ TITLE = """
149
 
150
  with gr.Blocks() as demo:
151
  gr.HTML(TITLE)
152
- with gr.Tab("By prompt", id="tab_prompt"):
 
 
153
  with gr.Row():
154
  with gr.Column():
155
  iimg = gr.Image(type="pil", label="Input")
@@ -177,30 +202,7 @@ with gr.Blocks() as demo:
177
  "examples/white-towels-rattan-basket-white-table-with-bright-room-background.jpg",
178
  "soap",
179
  ],
180
- [
181
- "examples/interior-decor-with-mirror-potted-plant.jpg",
182
- "potted plant",
183
- ],
184
- [
185
- "examples/detail-ball-basketball-court-sunset.jpg",
186
- "basketball",
187
- ],
188
- [
189
- "examples/still-life-device-table_23-2150994394.jpg",
190
- "glass of water",
191
- ],
192
- [
193
- "examples/knife-fork-green-checkered-napkin_140725-63576.jpg",
194
- "knife and fork",
195
- ],
196
- [
197
- "examples/city-night-with-architecture-vibrant-lights_23-2149836930.jpg",
198
- "frontmost black car on right lane",
199
- ],
200
- [
201
- "examples/close-up-coffee-latte-wooden-table_23-2147893063.jpg",
202
- "coffee cup on plate",
203
- ],
204
  [
205
  "examples/empty-chair-with-vase-plant_74190-2078.jpg",
206
  "chair",
@@ -215,6 +217,8 @@ with gr.Blocks() as demo:
215
  cache_examples=True,
216
  cache_mode="eager",
217
  )
 
 
218
  with gr.Tab("By bounding box", id="tab_bb"):
219
  with gr.Row():
220
  with gr.Column():
@@ -227,65 +231,72 @@ with gr.Blocks() as demo:
227
  label="Input",
228
  )
229
  with gr.Column():
230
- oimg = gr.ImageSlider(label="Output", max_height=1500, show_fullscreen_button=False)
231
  with gr.Row():
232
- btn = gr.ClearButton(components=[oimg], value="Erase Object", interactive=False)
233
 
234
  annotator.change(
235
  fn=on_change_bbox,
236
  inputs=[annotator],
237
- outputs=[btn],
238
  )
239
- btn.click(
240
  fn=process_bbox,
241
  inputs=[annotator],
242
- outputs=[oimg],
243
  api_name=False,
244
  )
245
 
246
- examples = [
247
  {
248
  "image": "examples/white-towels-rattan-basket-white-table-with-bright-room-background.jpg",
249
  "boxes": [{"xmin": 836, "ymin": 475, "xmax": 1125, "ymax": 1013}],
250
  },
251
- {
252
- "image": "examples/interior-decor-with-mirror-potted-plant.jpg",
253
- "boxes": [{"xmin": 47, "ymin": 907, "xmax": 397, "ymax": 1633}],
254
- },
255
- {
256
- "image": "examples/detail-ball-basketball-court-sunset.jpg",
257
- "boxes": [{"xmin": 673, "ymin": 954, "xmax": 911, "ymax": 1186}],
258
- },
259
- {
260
- "image": "examples/still-life-device-table_23-2150994394.jpg",
261
- "boxes": [{"xmin": 429, "ymin": 586, "xmax": 571, "ymax": 834}],
262
- },
263
- {
264
- "image": "examples/knife-fork-green-checkered-napkin_140725-63576.jpg",
265
- "boxes": [{"xmin": 972, "ymin": 226, "xmax": 1092, "ymax": 1023}],
266
- },
267
- {
268
- "image": "examples/city-night-with-architecture-vibrant-lights_23-2149836930.jpg",
269
- "boxes": [{"xmin": 215, "ymin": 637, "xmax": 411, "ymax": 855}],
270
- },
271
- {
272
- "image": "examples/close-up-coffee-latte-wooden-table_23-2147893063.jpg",
273
- "boxes": [{"xmin": 255, "ymin": 456, "xmax": 1080, "ymax": 1064}],
274
- },
275
- {
276
  "image": "examples/empty-chair-with-vase-plant_74190-2078.jpg",
277
  "boxes": [{"xmin": 35, "ymin": 320, "xmax": 383, "ymax": 983}],
278
  },
279
  ]
280
 
281
- ex = gr.Examples(
282
- examples=examples,
283
  inputs=[annotator],
284
- outputs=[oimg],
285
  fn=process_bbox,
286
  cache_examples=True,
287
  cache_mode="eager",
288
  )
289
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  demo.queue(max_size=30, api_open=False)
291
- demo.launch(show_api=False, ssr_mode=False)
 
129
  )
130
  return (img, output_image)
131
 
132
+ # --- NEW BATCH PROCESSING FUNCTIONS ---
133
+ def process_batch_prompt(files: list[Any], prompt: str):
134
+ """Processes multiple images sequentially with the same prompt."""
135
+ results = []
136
+ if not files:
137
+ return []
138
+
139
+ for file_obj in files:
140
+ # Open the image from the file path
141
+ img = Image.open(file_obj.name)
142
+ resized_img = resize(img)
143
+
144
+ # Run the eraser
145
+ output_image = _run(
146
+ ProcessParams(image=resized_img, prompt=prompt),
147
+ )
148
+ results.append(output_image)
149
+
150
+ return results
151
+
152
+ def on_change_batch(files: list[Any] | None, prompt: str | None):
153
+ return gr.update(interactive=bool(files and prompt))
154
+ # --------------------------------------
155
 
156
  def on_change_prompt(img: Image.Image | None, prompt: str | None):
157
  return gr.update(interactive=bool(img and prompt))
 
172
 
173
  with gr.Blocks() as demo:
174
  gr.HTML(TITLE)
175
+
176
+ # --- TAB 1: SINGLE IMAGE (PROMPT) ---
177
+ with gr.Tab("By prompt (Single)", id="tab_prompt"):
178
  with gr.Row():
179
  with gr.Column():
180
  iimg = gr.Image(type="pil", label="Input")
 
202
  "examples/white-towels-rattan-basket-white-table-with-bright-room-background.jpg",
203
  "soap",
204
  ],
205
+ # ... (Example list abbreviated for brevity, keep your original list here) ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  [
207
  "examples/empty-chair-with-vase-plant_74190-2078.jpg",
208
  "chair",
 
217
  cache_examples=True,
218
  cache_mode="eager",
219
  )
220
+
221
+ # --- TAB 2: SINGLE IMAGE (BOUNDING BOX) ---
222
  with gr.Tab("By bounding box", id="tab_bb"):
223
  with gr.Row():
224
  with gr.Column():
 
231
  label="Input",
232
  )
233
  with gr.Column():
234
+ oimg_bb = gr.ImageSlider(label="Output", max_height=1500, show_fullscreen_button=False)
235
  with gr.Row():
236
+ btn_bb = gr.ClearButton(components=[oimg_bb], value="Erase Object", interactive=False)
237
 
238
  annotator.change(
239
  fn=on_change_bbox,
240
  inputs=[annotator],
241
+ outputs=[btn_bb],
242
  )
243
+ btn_bb.click(
244
  fn=process_bbox,
245
  inputs=[annotator],
246
+ outputs=[oimg_bb],
247
  api_name=False,
248
  )
249
 
250
+ examples_bb = [
251
  {
252
  "image": "examples/white-towels-rattan-basket-white-table-with-bright-room-background.jpg",
253
  "boxes": [{"xmin": 836, "ymin": 475, "xmax": 1125, "ymax": 1013}],
254
  },
255
+ # ... (Example list abbreviated for brevity, keep your original list here) ...
256
+ {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  "image": "examples/empty-chair-with-vase-plant_74190-2078.jpg",
258
  "boxes": [{"xmin": 35, "ymin": 320, "xmax": 383, "ymax": 983}],
259
  },
260
  ]
261
 
262
+ ex_bb = gr.Examples(
263
+ examples=examples_bb,
264
  inputs=[annotator],
265
+ outputs=[oimg_bb],
266
  fn=process_bbox,
267
  cache_examples=True,
268
  cache_mode="eager",
269
  )
270
 
271
+ # --- TAB 3: BATCH PROCESSING (NEW) ---
272
+ with gr.Tab("Batch by prompt", id="tab_batch"):
273
+ gr.Markdown("Upload multiple images and apply the same erase prompt to all of them.")
274
+ with gr.Row():
275
+ with gr.Column():
276
+ # file_count="multiple" allows selecting many images
277
+ ibatch = gr.File(file_count="multiple", file_types=["image"], label="Upload Images")
278
+ batch_prompt = gr.Textbox(label="What should we erase from all these images?")
279
+ with gr.Column():
280
+ # Gallery displays multiple results
281
+ obatch = gr.Gallery(label="Batch Results", show_label=True, columns=[2], object_fit="contain", height="auto")
282
+
283
+ with gr.Row():
284
+ btn_batch = gr.Button("Erase from All Images", interactive=False, variant="primary")
285
+
286
+ # Enable button only if files and prompt exist
287
+ for inp in [ibatch, batch_prompt]:
288
+ inp.change(
289
+ fn=on_change_batch,
290
+ inputs=[ibatch, batch_prompt],
291
+ outputs=[btn_batch],
292
+ )
293
+
294
+ btn_batch.click(
295
+ fn=process_batch_prompt,
296
+ inputs=[ibatch, batch_prompt],
297
+ outputs=[obatch],
298
+ api_name=False,
299
+ )
300
+
301
  demo.queue(max_size=30, api_open=False)
302
+ demo.launch(show_api=False, ssr_mode=False)