gokaygokay commited on
Commit
1486d83
1 Parent(s): ee16454

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +26 -115
app.py CHANGED
@@ -4,9 +4,6 @@ import scipy.sparse as sp
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):
@@ -187,88 +184,24 @@ def laplacian_blend(img1: np.ndarray, img2: np.ndarray, mask: np.ndarray, depth:
187
 
188
  return np.clip(imgs[-1], 0, 1)
189
 
190
- def get_image(img_input, mask=False, scale=True):
191
- if img_input is None:
192
- raise ValueError("Image input is None")
193
-
194
- if isinstance(img_input, dict):
195
- img = img_input.get('composite')
196
- if img is None:
197
- img = img_input.get('background')
198
- elif isinstance(img_input, np.ndarray):
199
- img = img_input
200
- elif isinstance(img_input, str):
201
- img = cv2.imread(img_input)
202
- img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
203
  else:
204
- raise ValueError(f"Unsupported image input type: {type(img_input)}")
205
-
206
- if img is None:
207
- raise ValueError("Failed to load image")
208
-
209
- if mask:
210
- if len(img.shape) == 3:
211
- img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
212
- return np.where(img > 127, 1, 0).astype(np.uint8) # Threshold at 127 for the mask
213
-
214
- if scale and img.dtype != np.float64:
215
- return img.astype('float64') / 255.0
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
 
@@ -277,11 +210,6 @@ def blend_images(bg_img, obj_img, mask_img, method):
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
281
- h, w = bg_img.shape[:2]
282
- obj_img = cv2.resize(obj_img, (w, h))
283
- mask_img = cv2.resize(mask_img, (w, h))
284
-
285
  if method == "Poisson":
286
  blend_img = np.zeros_like(bg_img)
287
  for b in range(3):
@@ -296,52 +224,35 @@ def blend_images(bg_img, obj_img, mask_img, method):
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:
304
  gr.HTML("<h1>Image Blending with Multiple Methods</h1>")
305
 
306
  with gr.Row():
307
- bg_img = gr.Image(label="Background Image", type="numpy")
308
- obj_img = gr.Image(label="Object Image", type="numpy")
309
-
 
 
 
310
  with gr.Row():
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
- )
317
- mask_preview = gr.Image(label="Mask Preview")
318
-
319
- method = gr.Radio(["Poisson", "Mixed Gradient", "Laplacian"], label="Blending Method", value="Poisson")
320
-
321
- blend_button = gr.Button("Blend Images")
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 {
335
- "background": image_path,
336
- "layers": [],
337
- "composite": image_path
338
- }
339
 
340
  gr.Examples(
341
  examples=[
342
- ["img1.jpg", "img2.jpg", create_image_editor_input("mask1.jpg"), "Poisson"],
343
- ["img3.jpg", "img4.jpg", create_image_editor_input("mask2.jpg"), "Mixed Gradient"],
344
- ["img6.jpg", "img9.jpg", create_image_editor_input("mask3.jpg"), "Laplacian"]
345
  ],
346
  inputs=[bg_img, obj_img, mask_img, method],
347
  outputs=output_image,
 
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):
 
184
 
185
  return np.clip(imgs[-1], 0, 1)
186
 
187
+ def get_image(img_path: str, mask: bool=False, scale: bool=True) -> np.array:
188
+ """
189
+ Gets image in appropriate format
190
+ """
191
+ if isinstance(img_path, np.ndarray):
192
+ img = img_path
 
 
 
 
 
 
 
193
  else:
194
+ img = cv2.imread(img_path)
195
+ img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # Convert BGR to RGB for file inputs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  if mask:
198
  if len(img.shape) == 3:
199
  img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
200
+ _, binary_mask = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
201
+ return np.where(binary_mask == 255, 1, 0)
202
 
203
+ if scale:
204
+ return img.astype('double') / 255.0
205
 
206
  return img
207
 
 
210
  obj_img = get_image(obj_img)
211
  mask_img = get_image(mask_img, mask=True)
212
 
 
 
 
 
 
213
  if method == "Poisson":
214
  blend_img = np.zeros_like(bg_img)
215
  for b in range(3):
 
224
 
225
  return (blend_img * 255).astype(np.uint8)
226
 
 
 
 
 
227
  with gr.Blocks(theme='bethecloud/storj_theme') as iface:
228
  gr.HTML("<h1>Image Blending with Multiple Methods</h1>")
229
 
230
  with gr.Row():
231
+ with gr.Column():
232
+ bg_img = gr.Image(label="Background Image", type="numpy", height=300)
233
+ with gr.Column():
234
+ obj_img = gr.Image(label="Object Image", type="numpy", height=300)
235
+ with gr.Column():
236
+ gr.Image(label="Mask Image", type="numpy", height=300)
237
  with gr.Row():
238
+ with gr.Column():
239
+ method = gr.Radio(["Poisson", "Mixed Gradient", "Laplacian"], label="Blending Method", value="Poisson")
240
+ with gr.Column():
241
+ blend_button = gr.Button("Blend Images")
 
 
 
 
 
 
 
242
 
243
  output_image = gr.Image(label="Blended Image")
244
 
 
 
245
  blend_button.click(
246
  blend_images,
247
  inputs=[bg_img, obj_img, mask_img, method],
248
  outputs=output_image
249
+ )
 
 
 
 
 
 
 
250
 
251
  gr.Examples(
252
  examples=[
253
+ ["img1.jpg", "img2.jpg", "mask1.jpg", "Poisson"],
254
+ ["img3.jpg", "img4.jpg", "mask2.jpg", "Mixed Gradient"],
255
+ ["img6.jpg", "img9.jpg", "mask3.jpg", "Laplacian"]
256
  ],
257
  inputs=[bg_img, obj_img, mask_img, method],
258
  outputs=output_image,