gokaygokay commited on
Commit
ee16454
·
verified ·
1 Parent(s): a22dbe6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +63 -32
app.py CHANGED
@@ -4,6 +4,9 @@ import scipy.sparse as sp
4
  import scipy.sparse.linalg as splin
5
  from numba import jit
6
  import gradio as gr
 
 
 
7
 
8
  @jit(nopython=True)
9
  def build_poisson_sparse_matrix(ys, xs, im2var, img_s, img_t, mask):
@@ -213,18 +216,65 @@ def get_image(img_input, mask=False, scale=True):
213
 
214
  return img
215
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  def blend_images(bg_img, obj_img, mask_img, method):
217
  bg_img = get_image(bg_img)
218
  obj_img = get_image(obj_img)
219
-
220
- # Handle different input types for mask_img
221
- if isinstance(mask_img, dict):
222
- mask_img = mask_img.get('composite')
223
- if mask_img is None:
224
- mask_img = mask_img.get('background')
225
- elif isinstance(mask_img, str):
226
- mask_img = cv2.imread(mask_img, cv2.IMREAD_GRAYSCALE)
227
-
228
  mask_img = get_image(mask_img, mask=True)
229
 
230
  # Ensure mask and images have the same dimensions
@@ -246,14 +296,8 @@ def blend_images(bg_img, obj_img, mask_img, method):
246
 
247
  return (blend_img * 255).astype(np.uint8)
248
 
249
- def predict(im):
250
- return im["composite"]
251
-
252
- def create_default_mask(img):
253
- if img is None:
254
- return None
255
- gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
256
- _, mask = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY)
257
  return mask
258
 
259
  with gr.Blocks(theme='bethecloud/storj_theme') as iface:
@@ -267,7 +311,6 @@ with gr.Blocks(theme='bethecloud/storj_theme') as iface:
267
  mask_img = gr.ImageEditor(
268
  label="Mask Image",
269
  type="numpy",
270
- crop_size="1:1",
271
  brush=gr.Brush(colors=["#ffffff"], color_mode="fixed"),
272
  eraser=gr.Eraser(),
273
  )
@@ -279,25 +322,13 @@ with gr.Blocks(theme='bethecloud/storj_theme') as iface:
279
 
280
  output_image = gr.Image(label="Blended Image")
281
 
282
- def update_mask(obj_image):
283
- if obj_image is None:
284
- return None
285
- mask = create_default_mask(obj_image)
286
- return {"background": mask, "layers": [], "composite": mask}
287
-
288
- obj_img.change(
289
- update_mask,
290
- inputs=[obj_img],
291
- outputs=[mask_img]
292
- )
293
-
294
- mask_img.change(predict, outputs=mask_preview, inputs=mask_img, show_progress="hidden")
295
 
296
  blend_button.click(
297
  blend_images,
298
  inputs=[bg_img, obj_img, mask_img, method],
299
  outputs=output_image
300
- )
301
 
302
  def create_image_editor_input(image_path):
303
  return {
 
4
  import scipy.sparse.linalg as splin
5
  from numba import jit
6
  import gradio as gr
7
+ from PIL import Image
8
+ from typing import TypedDict
9
+
10
 
11
  @jit(nopython=True)
12
  def build_poisson_sparse_matrix(ys, xs, im2var, img_s, img_t, mask):
 
216
 
217
  return img
218
 
219
+ class ImageData(TypedDict):
220
+ background: np.ndarray
221
+ layers: list[np.ndarray]
222
+
223
+ def combine_masks(im_1: np.ndarray, im_2: np.ndarray):
224
+ if im_1.shape != im_2.shape:
225
+ raise ValueError("Images must have the same dimensions")
226
+ foreground_mask = im_2[:, :, 3] > 0
227
+ im_1[foreground_mask] = im_2[foreground_mask]
228
+ return im_1
229
+
230
+ def make_grey(image: np.ndarray, grey_value: int = 128):
231
+ rgb = image[:, :, :3]
232
+ alpha = image[:, :, 3]
233
+ opaque_mask = alpha == 255
234
+ rgb[opaque_mask] = np.stack((grey_value, grey_value, grey_value), axis=-1)
235
+ return np.dstack((rgb, alpha))
236
+
237
+ def create_mask(image: ImageData):
238
+ bg = image.get("background", None)
239
+ layers = image.get("layers", [])
240
+ if bg is None and not layers:
241
+ raise ValueError("No background or layers provided")
242
+ mask = layers[0] if layers else bg
243
+ for layer in layers[1:]:
244
+ mask = combine_masks(mask, layer)
245
+ mask = make_grey(mask)
246
+ return mask
247
+
248
+ def get_image(img_input, mask=False, scale=True):
249
+ if img_input is None:
250
+ raise ValueError("Image input is None")
251
+
252
+ if isinstance(img_input, dict):
253
+ img = create_mask(img_input)
254
+ elif isinstance(img_input, np.ndarray):
255
+ img = img_input
256
+ elif isinstance(img_input, str):
257
+ img = cv2.imread(img_input)
258
+ img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
259
+ else:
260
+ raise ValueError(f"Unsupported image input type: {type(img_input)}")
261
+
262
+ if img is None:
263
+ raise ValueError("Failed to load image")
264
+
265
+ if mask:
266
+ if len(img.shape) == 3:
267
+ img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
268
+ return np.where(img > 127, 1, 0).astype(np.uint8) # Threshold at 127 for the mask
269
+
270
+ if scale and img.dtype != np.float64:
271
+ return img.astype('float64') / 255.0
272
+
273
+ return img
274
+
275
  def blend_images(bg_img, obj_img, mask_img, method):
276
  bg_img = get_image(bg_img)
277
  obj_img = get_image(obj_img)
 
 
 
 
 
 
 
 
 
278
  mask_img = get_image(mask_img, mask=True)
279
 
280
  # Ensure mask and images have the same dimensions
 
296
 
297
  return (blend_img * 255).astype(np.uint8)
298
 
299
+ def update_mask_preview(image):
300
+ mask = create_mask(image)
 
 
 
 
 
 
301
  return mask
302
 
303
  with gr.Blocks(theme='bethecloud/storj_theme') as iface:
 
311
  mask_img = gr.ImageEditor(
312
  label="Mask Image",
313
  type="numpy",
 
314
  brush=gr.Brush(colors=["#ffffff"], color_mode="fixed"),
315
  eraser=gr.Eraser(),
316
  )
 
322
 
323
  output_image = gr.Image(label="Blended Image")
324
 
325
+ mask_img.change(update_mask_preview, inputs=mask_img, outputs=mask_preview)
 
 
 
 
 
 
 
 
 
 
 
 
326
 
327
  blend_button.click(
328
  blend_images,
329
  inputs=[bg_img, obj_img, mask_img, method],
330
  outputs=output_image
331
+ )
332
 
333
  def create_image_editor_input(image_path):
334
  return {